gpt4 book ai didi

android - 如何通过蓝牙获取 InputStream 并放入 Textview?

转载 作者:太空宇宙 更新时间:2023-11-03 12:58:27 25 4
gpt4 key购买 nike

这是我在 SO 中的第一个问题。我是 Android 编程的新手(并且很兴奋),这是我的问题:我正在使用我的 Android 手机和微 Controller 构建一个项目。微 Controller 有一个距离传感器并传输它的值。我已经设法连接到微 Controller 并发送正确的信号,但我无法获得距离测量值或其他任何信息。该应用程序不会崩溃或不会从微 Controller 获取数据的任何事情(我的计算机从微 Controller 获取数据(数据是一个字符串))。我的 android 应用程序代码是这样的:

公共(public)类加速度计扩展 Activity {

// Intent request codes
private static final int REQUEST_CONNECT_DEVICE = 1;
private static final int REQUEST_ENABLE_BT = 2;
private static final int RECIEVE_MESSAGE = 3;

// Program variables
private byte microcOut;
private boolean ledStat;
private boolean connectStat = false;
private Button btnled;
private Button connect_button;
private TextView yAccel, xAccel, incoming;
protected static final int MOVE_TIME = 80;
private long lastWrite = 0;
OnClickListener myClickListener;
ProgressDialog myProgressDialog;
private Toast failToast;
private Handler mHandler,h;
private StringBuilder sb = new StringBuilder();

// Sensor object used to handle accelerometer
private SensorManager mySensorManager;
private List<Sensor> sensors;
private Sensor accSensor;

// Bluetooth Stuff
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private InputStream inStream = null;
private ConnectThread mConnectThread = null;
private ConnectedThread mConnectedThread;

private String deviceAddress = null;
// Well known SPP UUID (will *probably* map to RFCOMM channel 1 (default) if not in use);
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

//Sound Clip to make app prettier
MediaPlayer myclip;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_accelerometer);
myclip = MediaPlayer.create(this, R.raw.cartcar);
myclip.start();
// Finds buttons in .xml layout file
btnled = (Button) findViewById(R.id.led_button1);
connect_button = (Button) findViewById(R.id.connect_button1);
yAccel = (TextView) findViewById(R.id.accText1);
xAccel = (TextView) findViewById(R.id.accText2);
incoming = (TextView) findViewById(R.id.incoming);
// Set Sensor
mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
sensors = mySensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if(sensors.size() > 0) accSensor = sensors.get(0);

myProgressDialog = new ProgressDialog(this);
failToast = Toast.makeText(this, R.string.failedToConnect, Toast.LENGTH_SHORT);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (myProgressDialog.isShowing()) {
myProgressDialog.dismiss();
}

// Check if bluetooth connection was made to selected device
if (msg.what == 1) {
// Set button to display current status
connectStat = true;
connect_button.setText(R.string.connected);

// Reset the BluCar
microcOut = 0;
ledStat = false;
write(microcOut);
}else {
// Connection failed
failToast.show();
}
}
};


h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE: // if receive massage
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
incoming.setText("Data from Arduino: " + sbprint); // update TextView
}
//Log.d(TAG, "...String:"+ sb.toString() + "Byte:" + msg.arg1 + "...");
break;
}
};
};
// Check whether bluetooth adapter exists
btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter == null) {
Toast.makeText(this, R.string.no_bt_device, Toast.LENGTH_LONG).show();
finish();
return;
}

// If BT is not on, request that it be enabled.
if (!btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
/**********************************************************************
* Buttons for controlling BluCar
*/
connect_button.setOnClickListener(new View.OnClickListener() {

// Connect to Bluetooth Module
@Override
public void onClick(View v) {
if (connectStat) {
// Attempt to disconnect from the device
disconnect();
}else{
// Attempt to connect to the device
connect();
}
}
});

// Toggle Headlights
btnled.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ledStat) {
microcOut = (byte) (microcOut & 124);
btnled.setText(R.string.ledbuttonON);
ledStat = false;
}else{
microcOut = (byte) (microcOut | 128);
btnled.setText(R.string.ledbuttonOFF);
ledStat = true;
}
write(microcOut);
}
});

}
/** Thread used to connect to a specified Bluetooth Device */
public class ConnectThread extends Thread {
private String address;
private boolean connectionStatus;

ConnectThread(String MACaddress) {
address = MACaddress;
connectionStatus = true;
}

public void run() {
// When this returns, it will 'know' about the server,
// via it's MAC address.
try {
BluetoothDevice device = btAdapter.getRemoteDevice(address);

// We need two things before we can successfully connect
// (authentication issues aside): a MAC address, which we
// already have, and an RFCOMM channel.
// Because RFCOMM channels (aka ports) are limited in
// number, Android doesn't allow you to use them directly;
// instead you request a RFCOMM mapping based on a service
// ID. In our case, we will use the well-known SPP Service
// ID. This ID is in UUID (GUID to you Microsofties)
// format. Given the UUID, Android will handle the
// mapping for you. Generally, this will return RFCOMM 1,
// but not always; it depends what other BlueTooth services
// are in use on your Android device.
try {
btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
connectionStatus = false;
}
}catch (IllegalArgumentException e) {
connectionStatus = false;
}

// Discovery may be going on, e.g., if you're running a
// 'scan for devices' search from your handset's Bluetooth
// settings, so we call cancelDiscovery(). It doesn't hurt
// to call it, but it might hurt not to... discovery is a
// heavyweight process; you don't want it in progress when
// a connection attempt is made.
btAdapter.cancelDiscovery();

// Blocking connect, for a simple client nothing else can
// happen until a successful connection is made, so we
// don't care if it blocks.
try {
btSocket.connect();
} catch (IOException e1) {
try {
btSocket.close();
} catch (IOException e2) {
}
}

// Create a data stream so we can talk to server.
try {
outStream = btSocket.getOutputStream();
} catch (IOException e2) {
connectionStatus = false;
}

// Send final result
if (connectionStatus) {
mHandler.sendEmptyMessage(1);
}else {
mHandler.sendEmptyMessage(0);
}
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
// Show please wait dialog
myProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.pleaseWait), getResources().getString(R.string.makingConnectionString), true);

// Get the device MAC address
deviceAddress = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS);
// Connect to device with specified MAC address
mConnectThread = new ConnectThread(deviceAddress);
mConnectThread.start();

}else {
// Failure retrieving MAC address
Toast.makeText(this, R.string.macFailed, Toast.LENGTH_SHORT).show();
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled
} else {
// User did not enable Bluetooth or an error occured
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
finish();
}
}
}

public void write(byte data) {
if (outStream != null) {
try {
outStream.write(data);
} catch (IOException e) {
}
}
}

public void emptyOutStream() {
if (outStream != null) {
try {
outStream.flush();
} catch (IOException e) {
}
}
}

public void connect() {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceList.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}

public void disconnect() {
if (outStream != null) {
try {
outStream.close();
connectStat = false;
connect_button.setText(R.string.disconnected);
} catch (IOException e) {
}
}
}
private final SensorEventListener mSensorListener = new SensorEventListener() {

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}

@Override
public void onSensorChanged(SensorEvent event) {
// Checks whether to send steering command or not
long date = System.currentTimeMillis();
if (date - lastWrite > MOVE_TIME) {
yAccel.setText(" " + event.values[1]);
xAccel.setText(" " + event.values[0]);
if (event.values[1] > 2.5) {
// Turn right
microcOut = (byte) (microcOut & 248);
microcOut = (byte) (microcOut | 4);
}else if (event.values[1] < -2.5) {
// Turn left
microcOut = (byte) (microcOut & 244);
microcOut = (byte) (microcOut | 8);
}else {
// Center the steering servo
microcOut = (byte) (microcOut & 240);
}
write(microcOut);
lastWrite = date;
}
}
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_accelerometer, menu);
return true;
}
public void onResume() {
super.onResume();
mySensorManager.registerListener(mSensorListener, accSensor, SensorManager.SENSOR_DELAY_GAME);
}
@Override
public void onDestroy() {
emptyOutStream();
disconnect();
if (mSensorListener != null) {
mySensorManager.unregisterListener(mSensorListener);
}
super.onDestroy();
myclip.release();
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;

// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }

mmInStream = tmpIn;
mmOutStream = tmpOut;
}

public void run() {
byte[] buffer = new byte[256]; // buffer store for the stream
int bytes; // bytes returned from read()

// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer); // Get number of bytes and message in "buffer"
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
}

/* Call this from the main activity to send data to the remote device */
public void write(String message) {

byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {

}
}
}

我已经阅读了有关该主题的所有内容(BluetoothChat、互联网上人们的项目...),但我很累。非常感谢任何帮助。

--编辑--

我已经设法将输入流输入到我的 texteview 中。我现在的问题是我的应用程序在尝试连接到我的设备(微 Controller 或我的电脑)时卡在进度对话框中(它已连接到设备但进度对话框不会消失)并等待进入。过了一会儿(比如 5-6 秒),即使有东西进来,它仍然卡住,我不得不强制它关闭。我认为问题在于处理程序处理线程的方式。在调试器中没有问题,所有线程都运行正常。

我的代码中的更改是:在我的连接线程中: `/** 用于连接指定蓝牙设备的线程 */ 公共(public)类 ConnectThread 扩展线程 { 私有(private)字符串地址; 私有(private) bool 连接状态;

    ConnectThread(String MACaddress) {
address = MACaddress;
connectionStatus = true;
}

public void run() {
// When this returns, it will 'know' about the server,
// via it's MAC address.
try {
BluetoothDevice device = btAdapter.getRemoteDevice(address);

// We need two things before we can successfully connect
// (authentication issues aside): a MAC address, which we
// already have, and an RFCOMM channel.
// Because RFCOMM channels (aka ports) are limited in
// number, Android doesn't allow you to use them directly;
// instead you request a RFCOMM mapping based on a service
// ID. In our case, we will use the well-known SPP Service
// ID. This ID is in UUID (GUID to you Microsofties)
// format. Given the UUID, Android will handle the
// mapping for you. Generally, this will return RFCOMM 1,
// but not always; it depends what other BlueTooth services
// are in use on your Android device.
try {
btSocket = device.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
connectionStatus = false;
}
}catch (IllegalArgumentException e) {
connectionStatus = false;
}

// Discovery may be going on, e.g., if you're running a
// 'scan for devices' search from your handset's Bluetooth
// settings, so we call cancelDiscovery(). It doesn't hurt
// to call it, but it might hurt not to... discovery is a
// heavyweight process; you don't want it in progress when
// a connection attempt is made.
btAdapter.cancelDiscovery();

// Blocking connect, for a simple client nothing else can
// happen until a successful connection is made, so we
// don't care if it blocks.
try {
btSocket.connect();
} catch (IOException e1) {
try {
btSocket.close();
} catch (IOException e2) {
}
}

// Create a data stream so we can talk to server.
try {
outStream = btSocket.getOutputStream();
} catch (IOException e2) {
connectionStatus = false;
}
try{
inStream = btSocket.getInputStream();
}catch (IOException e2){
connectionStatus = false;
}
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (connectionStatus) {
try {
byte[] b = new byte[64]; // buffer store for the stream
// Read from the InputStream
bytes = inStream.read(b); // Get number of bytes and message in "buffer"
mHandler.obtainMessage(RECIEVE_MESSAGE, bytes, -1, b).sendToTarget(); // Send to message queue Handler
} catch (IOException e) {
break;
}
}
// Send final result
if (connectionStatus) {
mHandler.obtainMessage(1);
}else {
mHandler.sendEmptyMessage(0);
}
}
}

`在我的 onCreate 方法中的 mHandler 中:

 mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (myProgressDialog.isShowing()) {
myProgressDialog.dismiss();
}

// Check if bluetooth connection was made to selected device
if (msg.what == 1) {
// Set button to display current status
connectStat = true;
connect_button.setText(R.string.connected);
// Reset the BluCar
microcOut = 0;
ledStat = false;
write(microcOut);
}else if (msg.what == 2){
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("."); // determine the end-of-line
if (endOfLineIndex > 0) { // if end-of-line,
String sbprint = sb.substring(0, endOfLineIndex); // extract string
sb.delete(0, sb.length()); // and clear
incoming.setText(sbprint); // update TextView
connectStat = true;
connect_button.setText(R.string.connected);
}else{
incoming.setText("Problem!");
}
}else {
// Connection failed
failToast.show();
}
}
};

我需要做的另一件事是当缓冲区已满时如何清空缓冲区。

PS:感谢大家的帮助,我真的很感激。

最佳答案

作为使用处理程序的替代方法,只需在线程运行时获取信息..

我已经这样做了并且对我有用。

public void run() {
byte[] buffer = new byte[128]; // buffer store for the stream
int bytes; // bytes returned from read()

// Keep listening to the InputStream until an exception occurs
while (true) {
try {


bytes = mmInStream.read(buffer);
byte[] readBuf = (byte[]) buffer;
String strIncom = new String(readBuf, 0, bytes); // create string from bytes array
sb.append(strIncom); // append string
int endOfLineIndex = sb.indexOf("\r\n"); // determine the end-of-line
if (endOfLineIndex > 0) {
// add the current string to eol to a local string
String sbprint = sb.substring(0, endOfLineIndex);

// get the start and end indexes of the heading
int startHeading = sb.indexOf("HE");
int endHeading = sb.indexOf("/HE");

// set the heading
Henry.this.setCurrentHeading(sb.substring((startHeading + 2), endHeading));

// get the start and end indexes of the front range
int startFrontRange = sb.indexOf("FR");
int endFrontRange = sb.indexOf("/FR");

// get the front range
Henry.this.currentFrontRange = sb.substring((startFrontRange + 2), endFrontRange);
... ( grab all the information you need here ) ...

// debugging output what we have
// System.out.println("recv: " + sbprint);

// clean out the sb to ready next run
sb.delete(0, sb.length());
}

我将从串行连接中检索到的所有信息保存在我的应用程序 (Henry) 中,然后任何想要使用这些信息的 Activity 都会从应用程序中获取它。如果 View 需要对信息有更新的看法,我会在 View 中添加一个计时器,以根据需要随时启动刷新方法。这具有能够在您的 Android 应用程序中的任何位置使用信息的额外优势。

我通过这种方式从 arduino 向设备发送了大约 10 个数据点,并从设备向 arduino 发送了大约 3 个数据点。我在数据点周围添加了自己的标记以识别它们。

希望这对您有所帮助!

关于android - 如何通过蓝牙获取 InputStream 并放入 Textview?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15399181/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com