最近写了一个关于蓝牙的操作类,对蓝牙不熟悉的同学可以参考一下 功能包括 发现,搜索,连接,发送,接收等/ 直接上代码:
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[]);
写的比较简单,主要是为了对蓝牙使用不了解的人,大家使用之前一定要先看看大体的流程,不要直接使用,对自己并没有好处。