这边由于我不知道我们公司的设备代码怎么设计的,所以不太清楚通用性如何,不过一般而言应该差不多吧。
首先我自定义了一个蓝牙连接管理的类,初始化的参数为Activity的context(这里我写的很随意,理论上这个类写在Service中更好):
public class BTManager { private Context context = null; private BluetoothAdapter adapter = null; private BroadcastReceiver receiver = null; private BTService bts = null; // 初始化 public BTManager(Context context) { this.context = context; initAdapter(); initRecevier(); } }首先判断手机支不支持蓝牙功能,如果支持则开启蓝牙
// 看是否支持蓝牙 private void initAdapter() { adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter == null) { Toast.makeText(context, "该设备不支持蓝牙!", Toast.LENGTH_SHORT).show(); return; } enabledBT(); } // 开启蓝牙 private void enabledBT() { if (!adapter.isEnabled()) { Intent mIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); context.startActivity(mIntent); } }然后初始化广播,这个广播是要给Acitivty注册的,用来通知界面蓝牙连接的状态:
// 初始化广播 private void initRecevier() { if(receiver == null){ receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String actionName = intent.getAction(); if (actionName.equals("android.bluetooth.device.action.FOUND")) { // 获取找到设备的对象 BluetoothDevice device = (BluetoothDevice) intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 如果找到的设备和想要搜索的设备名一致,就发送找到广播 if (device.getName() != null && device.getName().equalsIgnoreCase( Params.deviceName)) { Intent it = new Intent( "com.fisee.bluetooth.findFinished"); it.putExtra("state", true); context.sendBroadcast(it); cancelDiscover(); bts = new BTService(device); } } else if (actionName .equals("android.bluetooth.adapter.action.DISCOVERY_FINISHED")) { // 搜索结束 Intent it = new Intent("com.fisee.bluetooth.findFinished"); it.putExtra("state", false); context.sendBroadcast(it); cancelDiscover(); } } }; } }android.bluetooth.device.action.FOUND为找到设备后收到的广播,但是周围开启的蓝牙设备都有可能被搜索到,所以要将搜索到的设备名和我们要搜索的设备名进行比较,如果一致则停止搜寻设备,进行连接。
android.bluetooth.adapter.action.DISCOVERY_FINISHED为搜索结束后收到的广播,一般蓝牙搜索的过程会持续12s,12s后没有找到要匹配的设备则收到此广播。
下面是开始搜寻设备的方法和停止搜寻设备的方法:
// 开始搜寻设备 public void discover(String name) { if (adapter == null) { return; } Params.deviceName = name; if (adapter.isDiscovering()) { Toast.makeText(context, "正在搜索请等待...", Toast.LENGTH_SHORT).show(); } else { // 注册广播 IntentFilter filter = new IntentFilter(); filter.addAction("android.bluetooth.device.action.FOUND"); filter.addAction("android.bluetooth.adapter.action.DISCOVERY_FINISHED"); context.registerReceiver(receiver, filter); adapter.startDiscovery(); } } // 停止搜索设备 private void cancelDiscover() { // 如果还在搜寻设备,则停止 if (adapter.isDiscovering()) { adapter.cancelDiscovery(); } // 注销广播 context.unregisterReceiver(receiver); }在搜寻开始时注册广播,如果搜寻结束,要记住注销广播。
然后我写了一个内部类,专门用来处理蓝牙收发数据:
public class BTService { private BluetoothDevice target = null;// socket连接的对象 private Thread thread = null;// 接收数据线程 private BluetoothSocket socket = null;// bt socket对象 private boolean running = false;// socket是否正在运行 public BTService(BluetoothDevice device) { running = false; closeSocket(); target = device; if (thread == null) { thread = new Thread() { public void run() { try { Log.e("CREAT BT SOCKET", "creating bt socket"); /** * 蓝牙socket连接的建立 */ Method m = target.getClass().getMethod( "createRfcommSocket", new Class[] { Integer.TYPE }); socket = ((BluetoothSocket) m.invoke(target, new Object[] { Integer.valueOf(1) })); socket.connect(); } catch (IOException e) { closeSocket(); Log.e("IOException", "creat bt socket exception"); } catch (SecurityException e) { closeSocket(); Log.e("SecurityException", "close bt socket exception"); } catch (NoSuchMethodException e) { closeSocket(); Log.e("Exception", "close bt socket exception"); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } if (socket == null) return; running = true; OnConnect(); byte[] buf = new byte[1024]; Log.e("creating success", "create bt socket success"); while (running) { try { InputStream isr = socket.getInputStream(); int sz = isr.read(buf); isr = null; if (sz <= 0) { // Log.e("BluetoothSockTask", // " read error size:" + // sz); } else { // Log.e("BluetoothSockTask", // " receive data success size:" + sz); OnRecv(buf, sz); } } catch (Exception e) { // Log.e("Exception","receive bt socket data exception"); if (running) closeSocket(); } } } }; } thread.start(); } // 关闭socket private void closeSocket() { running = false; if (this.socket == null) { return; } try { socket.close(); System.out.println("closing bt socket"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } clear_bond(); socket = null; } public void clear_bond() { BluetoothAdapter m_adapter = BluetoothAdapter.getDefaultAdapter(); BluetoothDevice m_btdevice = null; Method removeBondMethod = null; int i = 0; Set<BluetoothDevice> m_dev_set = m_adapter.getBondedDevices(); for (Iterator<BluetoothDevice> it = m_dev_set.iterator(); it .hasNext();) { Log.e("", "clear bond++++++++++++++ " + i); m_btdevice = it.next(); i++; try { removeBondMethod = m_btdevice.getClass().getMethod( "removeBond");// 移除沾和 } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { @SuppressWarnings("unused") Boolean returnValue = (Boolean) removeBondMethod .invoke(m_btdevice); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } //socket创建成功 public void OnConnect(){ Intent intent = new Intent( "com.fisee.bluetooth.bluetoothConnected"); context.sendBroadcast(intent); } //接收到数据 public void OnRecv(byte[] buf,int size){ byte[] data = new byte[size]; for (int i = 0; i < size; i++) { data[i] = buf[i]; } //处理数据 System.out.println(data.length); } /** * 蓝牙socket发送出的数据 * * @param data * @param size * @return */ public int sendData(byte[] data, int size) { if ((!this.running) || (data == null) || (this.socket == null)) return -1; try { OutputStream out = this.socket.getOutputStream(); if (data.length <= size) { out.write(data); size = data.length; } else { out.write(data, 0, size); } out.flush(); } catch (IOException e) { e.printStackTrace(); return 0; } return size; } }running相当于是个标志位,用来判断socket的状态,同时也控制着接收蓝牙数据的线程。sendData(byte[] data, int size) 方法是用来发送蓝牙包的。