我将实施从我的Android平板电脑向嵌入蓝牙IC芯片Andrino HC-06的电子设备发送命令的模块,用于通过蓝牙配置我的设备。在执行时,似乎在发送22 23 54 01 C8
时设备没有可观察到的响应。
它显示以下超时异常
预计设备将重新启动并返回许多消息。在将这些eta命令发送到我的设备进行远程控制时,我应该了解更多信息?
日志cat消息
05-23 18:19:44.866: E/BluetoothChatService(512): java.io.IOException: bt socket closed, read return: -1
05-23 18:19:44.866: E/BluetoothChatService(512): at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:429)
05-23 18:19:44.866: E/BluetoothChatService(512): at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:96)
05-23 18:19:44.866: E/BluetoothChatService(512): at java.io.InputStream.read(InputStream.java:162)
05-23 18:19:44.866: E/BluetoothChatService(512): at com.example.android.BluetoothChat.BluetoothChatService$ConnectedThread.run(BluetoothChatService.java:485)
以下是我的代码
private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT)
.show();
return;
}
// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
mOutEditText.setText(mOutStringBuffer);
}
}
发送命令
public void write(byte[] buffer) {
try {
boolean connected = false;
BluetoothSocket sock = null;
InputStream in = null ;
OutputStream out = null ;
BluetoothDevice zee = BluetoothAdapter.getDefaultAdapter().getRemoteDevice("00:14:01:12:28:12");
Method m = zee.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
sock = (BluetoothSocket) m.invoke(zee, Integer.valueOf(1));
sock.connect();
in = sock.getInputStream();
out = sock.getOutputStream();
char[] test = { 0x22 , 0x21 , 0x03 , 0x00 , 0xc9};
for(int k=0; k < test.length; k++){
new DataOutputStream(sock.getOutputStream()).writeByte(test[k]);
}
byte [] bfferX = new String(test).getBytes("UTF-8");*/
mmOutStream.write(buffer);
mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
答案 0 :(得分:1)
我想设备已经配对,并且android设备执行发现。
为什么你认为这是暂停的问题?该异常表示通信套接字已关闭。也许你成功地创造了一个BluetoothSocket
然后关闭它&#34;意外地&#34; (也许,在刷新之后,关闭与套接字相关的输出或输入流。)
由于您正在关注Android BluetoothChat示例,因此您应该:
1)执行发现并侦听可用设备:
private final BroadcastReceiver deviceFoundBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action) && mState==STATE_DISCOVERING) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
new ConnectThread(device).start();
}
}
};
2)连接到设备:
private class ConnectThread extends Thread {
private BluetoothSocket mmSocket;
private BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
try {
tmp = InsecureBluetooth.createRfcommSocketToServiceRecord(mmDevice, YOUR_UUID, false);
}
catch (IOException e) { }
mmSocket = tmp;
}
@Override
public void run() {
try {
btAdapter.cancelDiscovery(); // be sure discovery is cancelled
mmSocket.connect(); // blocking call, returns only on a successful connection or an exception
connected(mmSocket, mmSocket.getRemoteDevice());
new ConnectedThread(mmSocket, mmDevice.getAddress()).start(); // start connected thread
}
catch (IOException e) {}
}
public void cancel() {}
}
3)检索用于与配对设备通信的输入和输出流(在需要通信时不要关闭流):
private class ConnectedThread extends Thread {
private BluetoothSocket mmSocket;
private String macAddress;
public ConnectedThread(BluetoothSocket socket, String macAddress) {
this.macAddress = macAddress;
this.mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
mmInStream = mmSocket.getInputStream();
mmOutStream = mmSocket.getOutputStream();
}
catch (IOException e) {}
}
@Override
public void run() {
// perform communication
}
}
InsecureBluetooth类用于&#34;避免&#34;配对阶段基于this Stanford peace of code:
@TargetApi(10)
public class InsecureBluetooth {
static private class InUse extends RuntimeException { }
public static BluetoothServerSocket listenUsingRfcommWithServiceRecord(BluetoothAdapter adapter, String name, UUID uuid, boolean encrypt) throws IOException {
if(Build.VERSION.SDK_INT<10) {
try {
Class c_rfcomm_channel_picker = null;
Class[] children = BluetoothAdapter.class.getDeclaredClasses();
for(Class c : children) {
Log.e("TO", "class " + c.getCanonicalName());
if(c.getCanonicalName().equals(BluetoothAdapter.class.getName() + ".RfcommChannelPicker")) {
c_rfcomm_channel_picker = c;
break;
}
}
if(c_rfcomm_channel_picker == null)
throw new RuntimeException("can't find the rfcomm channel picker class");
Constructor constructor = c_rfcomm_channel_picker.getDeclaredConstructor(UUID.class);
if(constructor == null)
throw new RuntimeException("can't find the constructor for rfcomm channel picker");
Object rfcomm_channel_picker = constructor.newInstance(new Object[] {uuid});
Method m_next_channel = c_rfcomm_channel_picker.getDeclaredMethod("nextChannel", new Class[] {});
m_next_channel.setAccessible(true);
BluetoothServerSocket socket = null;
int channel;
int errno;
while (true) {
channel = (Integer)m_next_channel.invoke(rfcomm_channel_picker, new Object[] {});
if (channel == -1) {
throw new IOException("No available channels");
}
try {
socket = listenUsingRfcomm(channel, encrypt);
break;
} catch(InUse e) {
continue;
}
}
Field f_internal_service = adapter.getClass().getDeclaredField("mService");
f_internal_service.setAccessible(true);
Object internal_service = f_internal_service.get(adapter);
Method m_add_rfcomm_service_record = internal_service.getClass().getDeclaredMethod("addRfcommServiceRecord", new Class[] {String.class, ParcelUuid.class, int.class, IBinder.class});
m_add_rfcomm_service_record.setAccessible(true);
int handle = (Integer)m_add_rfcomm_service_record.invoke(internal_service, new Object[] { name, new ParcelUuid(uuid), channel, new Binder() } );
if (handle == -1) {
try {
socket.close();
} catch (IOException e) {}
throw new IOException("Not able to register SDP record for " + name);
}
Field f_internal_handler = null;
try {
f_internal_handler = adapter.getClass().getDeclaredField("mServiceRecordHandler");
} catch(Exception e) {
f_internal_handler = adapter.getClass().getDeclaredField("mHandler");
}
f_internal_handler.setAccessible(true);
Object internal_handler = f_internal_handler.get(adapter);
Method m_set_close_handler = socket.getClass().getDeclaredMethod("setCloseHandler", new Class[] {Handler.class, int.class});
m_set_close_handler.setAccessible(true);
m_set_close_handler.invoke(socket, new Object[] { internal_handler, handle});
return socket;
} catch (Exception e) {}
}
else {
return adapter.listenUsingInsecureRfcommWithServiceRecord(name, uuid);
}
}
private static BluetoothServerSocket listenUsingRfcomm(int port, boolean encrypt, boolean reuse) throws IOException, InUse {
BluetoothServerSocket socket = null;
try {
Constructor<BluetoothServerSocket> constructor = BluetoothServerSocket.class.getDeclaredConstructor(int.class, boolean.class, boolean.class, int.class);
if(constructor == null)
throw new RuntimeException("can't find the constructor");
constructor.setAccessible(true);
Field f_rfcomm_type = BluetoothSocket.class.getDeclaredField("TYPE_RFCOMM");
f_rfcomm_type.setAccessible(true);
int rfcomm_type = (Integer)f_rfcomm_type.get(null);
Field f_e_addr_in_use = BluetoothSocket.class.getDeclaredField("EADDRINUSE");
f_e_addr_in_use.setAccessible(true);
int e_addr_in_use = (Integer)f_e_addr_in_use.get(null);
socket = constructor.newInstance(new Object[] { rfcomm_type, false, encrypt, port } );
Field f_internal_socket = socket.getClass().getDeclaredField("mSocket");
f_internal_socket.setAccessible(true);
Object internal_socket = f_internal_socket.get(socket);
Method m_bind_listen = internal_socket.getClass().getDeclaredMethod("bindListen", new Class[] {});
m_bind_listen.setAccessible(true);
Object result = m_bind_listen.invoke(internal_socket, new Object[] {});
int errno = (Integer)result;
if(reuse && errno == e_addr_in_use) {
throw new InUse();
} else if (errno != 0) {
try {
socket.close();
} catch (IOException e) {}
internal_socket.getClass().getMethod("throwErrnoNative", new Class[] {int.class}).invoke(internal_socket, new Object[] { errno });
}
return socket;
} catch (Exception e) {}
}
public static BluetoothServerSocket listenUsingRfcomm(int port, boolean encrypt) throws IOException {
return listenUsingRfcomm(port, encrypt, false);
}
private static BluetoothSocket createRfcommSocketToServiceRecord(BluetoothDevice device, int port, UUID uuid, boolean encrypt) throws IOException {
try {
BluetoothSocket socket = null;
Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
int.class, int.class, boolean.class, boolean.class, BluetoothDevice.class, int.class, ParcelUuid.class);
if(constructor == null)
throw new RuntimeException("can't find the constructor for socket");
constructor.setAccessible(true);
Field f_rfcomm_type = BluetoothSocket.class.getDeclaredField("TYPE_RFCOMM");
f_rfcomm_type.setAccessible(true);
int rfcomm_type = (Integer)f_rfcomm_type.get(null);
socket = constructor.newInstance(new Object[] { rfcomm_type, -1, false, true, device, port, uuid != null ? new ParcelUuid(uuid) : null} );
return socket;
} catch (Exception e) {}
}
public static BluetoothSocket createRfcommSocketToServiceRecord(BluetoothDevice device, UUID uuid, boolean encrypt) throws IOException{
if(Build.VERSION.SDK_INT<10) {
return createRfcommSocketToServiceRecord(device, -1, uuid, encrypt);
}
else {
return device.createInsecureRfcommSocketToServiceRecord(uuid);
}
}
public static BluetoothSocket createRfcommSocket(BluetoothDevice device, int port, boolean encrypt) throws IOException {
return createRfcommSocketToServiceRecord(device, port, null, encrypt);
}
}