最近写了一个关于蓝牙的操作类,对蓝牙不熟悉的同学可以参考一下 功能包括 发现,搜索,连接,发送,接收等/ 直接上代码:
package com.***.****.BlueToothM; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Looper; import android.os.Message; import com.***.***.utils.LogUtil; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; /** * Created by bysd-2 on 2018/10/19. */ public class BlueToothHelper { public static final int REQUEST_BLUE_ENABLE = 110; private static Context mContext; private static BluetoothAdapter bluetoothAdapter; private static String UUID_STR = "00001101-0000-1000-8000-00805F9B34FB"; public static CURR_STATUS curr_status; private static ConnectThread connectThread; private static ReadThread readThread; private static SendThread sendThread; private static Handler queueMsg; public enum CURR_STATUS { CONNECTED, DISCONNECTED } // 初始化 这里需要注意是蓝牙如果没有开启则要开启后 在activity回调里再次获取发现搜索一下设备; public static BluetoothAdapter initBlueTooth(Context context, Activity currActivity) { mContext = context; BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); if (bluetoothAdapter != null) { if (!bluetoothAdapter.isEnabled()) { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); // intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); currActivity.startActivityForResult(intent, REQUEST_BLUE_ENABLE); } return bluetoothAdapter; } else { return null; } } // 初始化后可以调用此方法,还有在activity回调成功时调用; 此处还需要一个广播来接收相应的消息,这个广播我稍后发出来 ,广播其实也可以放到此工具类里,我只是分出来了,放到这个工具类里好处时各个状态比较好监听,放到外面则需要两个监听,有些多余; public static void startDiscover() { if (bluetoothAdapter != null) { if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); bluetoothAdapter.startDiscovery(); } else { bluetoothAdapter.startDiscovery(); } } } // 这个在连接之前,扫描设备超时的时候调用;节省资源; public static void cancelDiscover() { if (bluetoothAdapter != null) { bluetoothAdapter.cancelDiscovery(); } } // 退出的时候调用,释放及重置 public static void close() { if (bluetoothSocket != null) { try { bluetoothSocket.close(); } catch (IOException e) { e.printStackTrace(); } } if (bluetoothAdapter != null) { bluetoothAdapter = null; } if (connectThread != null) { connectThread = null; } if (readThread != null) { readThread = null; } if (sendThread != null) { sendThread = null; } // curr_status = CURR_STATUS.DISCONNECTED; } // 连接时的回调; 里面加了一个接收数据的回调; public static IConnectListener iConnectListener; public interface IConnectListener { void connectDevSuccess();//连接成功; void connectDevFail(String exception); // 连接出错; void dataRespon(byte[] bytes); // 接收 } // connect public static void connectDevice(IConnectListener l, BluetoothDevice device) { iConnectListener = l; // if (connectThread == null) { connectThread = new ConnectThread(device); connectThread.start(); } else { LogUtil.e(TAG, "connectThread != null"); } } private static final String TAG = BlueToothHelper.class.getSimpleName(); // private static InputStream inS = null; private static OutputStream outs = null; private static BluetoothSocket bluetoothSocket; private static final int SEND_CONNECT_FAIL = 1; private static final int SEND_CONNECT_SUCCESS = 2; private static final int SEND_FLAG = 110; static class ConnectThread extends Thread { private BluetoothDevice device; public ConnectThread(BluetoothDevice device) { this.device = device; } @Override public void run() { super.run(); // try { UUID uuid = UUID.fromString(UUID_STR); BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(device.getAddress()); // // TODO: 2018/10/23 此处通过uuid连接蓝牙;但有时候连接不上,不能保证每次都可以连接上; bluetoothSocket = remoteDevice.createRfcommSocketToServiceRecord(uuid); // RFcomm 是一种简单的传输协议 bluetoothSocket.connect(); // 靠谱的方式; 这种是比较暴力的方式,直接连蓝牙,API没有开放,估计是为了安全的角度,通过信道连接,范围1-30; 通过递归直到练到正确的信道上; // bluetoothSocket = cretateBluetoothSocketbyChannel(remoteDevice, 1, true); if (bluetoothSocket == null) { sendMSG(SEND_CONNECT_FAIL, "0: " + "change channel always error"); return; } LogUtil.e(TAG, "ok"); // inS = bluetoothSocket.getInputStream(); outs = bluetoothSocket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); try { if (bluetoothSocket != null) { bluetoothSocket.close(); } if (inS != null) { inS.close(); } if (outs != null) { outs.close(); } bluetoothSocket = null; inS = null; outs = null; } catch (IOException e1) { e1.printStackTrace(); // sendMSG(SEND_CONNECT_FAIL, "1: " + e.getMessage()); return; } // sendMSG(SEND_CONNECT_FAIL, "2: " + e.getMessage()); return; } // sendMSG(SEND_CONNECT_SUCCESS, null); } } /** * 有时候用api提供的方法remoteDevice.createRfcommSocketToServiceRecord(uuid)不能成功连接,connect总出错误; * * @param Device * @param channel * @param autoForward * @return */ private static BluetoothSocket cretateBluetoothSocketbyChannel(BluetoothDevice Device, int channel, boolean autoForward) { BluetoothSocket socket = null; try { // createRfcommSocket为内置方法,入参为int类型; invoke执行该方法并需传入当前类对象及所需的入参类型;得到该方法的返回; socket = (BluetoothSocket) Device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(Device, Integer.valueOf(channel)); socket.connect(); LogUtil.e(TAG, "connect is ok . " + channel); } catch (Exception e) { LogUtil.e(TAG, "get socket is failed . e: " + e.getMessage()); if (channel < 30) { if (autoForward) { socket = cretateBluetoothSocketbyChannel(Device, channel + 1, autoForward); } } else { return null; } } return socket; } private static void sendMSG(int what, Object object) { Message msg = mHandler.obtainMessage(); msg.what = what; msg.obj = object; mHandler.sendMessage(msg); } private static Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case SEND_CONNECT_FAIL: if (iConnectListener != null) { iConnectListener.connectDevFail((String) msg.obj); } // curr_status = CURR_STATUS.DISCONNECTED; break; case SEND_CONNECT_SUCCESS: // curr_status = CURR_STATUS.CONNECTED; // if (iConnectListener != null) { iConnectListener.connectDevSuccess(); } // if (readThread == null) { readThread = new ReadThread(); readThread.start(); } else { LogUtil.e(TAG, "readThread != null"); } // if (sendThread == null) { sendThread = new SendThread(); sendThread.start(); } break; } } }; static class SendThread extends Thread { @Override public void run() { super.run(); // Looper.prepare(); queueMsg = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == SEND_FLAG) { byte[] bytes = (byte[]) msg.obj; sendToBlt(bytes); } super.handleMessage(msg); } }; Looper.loop(); } } static class ReadThread extends Thread { @Override public void run() { super.run(); if (curr_status == CURR_STATUS.CONNECTED) { if (inS == null) { return; } try { int available = inS.available(); byte[] bRec = new byte[available]; int read = inS.read(bRec); // LogUtil.e(TAG, "rece /// available: " + available + " read: " + read); if (read > 0) { if (iConnectListener != null) { iConnectListener.dataRespon(bRec); } } Thread.sleep(200); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } } // 蓝牙发送 会放到队列里; public static void sendData(byte[] data) { if (queueMsg != null) { Message message = queueMsg.obtainMessage(); message.what = SEND_FLAG; message.obj = data; queueMsg.sendMessage(message); } } private static void sendToBlt(byte[] data) { if (curr_status == CURR_STATUS.CONNECTED) { try { LogUtil.e(TAG, "send data"); outs.write(data); } catch (IOException e) { LogUtil.e(TAG, "e: " + e.getMessage()); e.printStackTrace(); } } else { LogUtil.e(TAG, "sendToBlt is fail..."); } } }还有一个广播的 这个广播监听蓝牙的状态,可以根据自己的需要来进行你想监听的消息; 之前已经说了 这个广播可以放到上面一起 // 注意 下面没有获取了RSSI DEVICE这两个,没有去重;
package com.***.***.BlueToothM; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import com.***.***.BlueToothM.bean.BlueToothBean; /** * Created by bysd-2 on 2018/10/19. */ public class BlueToothReceiver extends BroadcastReceiver { private IStatusListener listener; public interface IStatusListener { void foundDevice(BlueToothBean btBean); void discoveryFinished(); void disConnected(); void connected(); } public void setIStatusListener(IStatusListener l) { this.listener = l; } @Override public void onReceive(Context context, Intent intent) { if (intent != null) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); short rssi = intent.getExtras().getShort(BluetoothDevice.EXTRA_RSSI); BlueToothBean btBean = new BlueToothBean(device, rssi); if (listener != null) { listener.foundDevice(btBean); } } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { if (listener != null) { listener.discoveryFinished(); } } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { BlueToothHelper.curr_status = BlueToothHelper.CURR_STATUS.DISCONNECTED; if (listener != null) { listener.disConnected(); } } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { BlueToothHelper.curr_status = BlueToothHelper.CURR_STATUS.CONNECTED; if (listener != null) { listener.connected(); } } } } }// 使用
registerListener(); // 注册那个广播,要记得解注册; blueToothReceiver.setIStatusListener(new MyListener()); // 实现这个监听; bluetoothAdapter = BlueToothHelper.initBlueTooth(getApplicationContext(), this); // 初始化 // BlueToothHelper.startDiscover(); // 开始搜素 // @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == BlueToothHelper.REQUEST_BLUE_ENABLE && resultCode == RESULT_OK) { Toast.makeText(MainActivity.this, "open bluetooth success", Toast.LENGTH_LONG).show(); BlueToothHelper.startDiscover(); } else { LogUtil.e(TAG, "requestCode: " + requestCode); } } // 连接蓝牙 BlueToothHelper.connectDevice(new BlueToothHelper.IConnectListener() { @Override public void connectDevSuccess() { } @Override public void connectDevFail(String exception) { } @Override public void dataRespon(byte[] bytes) { } }, device);好了 关于普通蓝牙的大概这么多, 还有发送的 方法 sendData(byte[]);
写的比较简单,主要是为了对蓝牙使用不了解的人,大家使用之前一定要先看看大体的流程,不要直接使用,对自己并没有好处。