权限
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
动态申请权限
public class ApplyPermission {
public static void ApplyPermission(Context context) {
ActivityCompat.requestPermissions((Activity) context, new String[]{
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
}, 1);
}
}
连接工具类
/**
* @anthor GrainRain
* @funcation 蓝牙连接工具类
* @date 2019/11/7
*/
public class Util {
//存放蓝牙设备名列表
private static ArrayList<String> deviceNameList = new ArrayList<>();
//存放蓝牙设备mac地址列表
private static ArrayList<String> deviceMacList = new ArrayList<>();
//存放蓝牙设备名和地址 用于显示
private static ArrayList<String> deviceMsgList = new ArrayList<>();
//存放已配对蓝牙列表
private static ArrayList<String> pairedDeviceNameList = new ArrayList<>();
private static Context context;
private static BluetoothDevice btDevice;
private static ArrayList<BluetoothDevice> btDeviceList = new ArrayList<>();
private static OnConnectListener onConnectListener;
private static final String[] items = new String[100];
private static ArrayAdapter<String> adapter = null;
private static BluetoothAdapter blueadapter;
//这条是蓝牙串口通用的UUID,不要更改
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static BluetoothSocket btSocket = null;
private static OutputStream outStream = null;
private static InputStream inStream = null;
private static int deviceMatchingNum = 0;
private static boolean deviceMatching = false;
private static ReceiveThread rThread = null; //数据接收线程
public Util() {
for(int i = 0; i < items.length; i++) {
items[i] = "";
}
}
public void get(Context context, OnConnectListener listener) {
setContext(context);
showListDialog();
blueadapter = BluetoothAdapter.getDefaultAdapter();
//判断蓝牙是否打开
if(!blueadapter.isEnabled()) {
// blueadapter.enable();
} else {
getContext().registerReceiver(bluetoothReceiver, intentFilter);//用BroadcastReceiver 来取得结果
doDiscovry();
}
setOnConnectListener(listener);
listener.onConnectSuccess(null);
listener.onConnectFailed(null);
}
static IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//注册广播接收信号
private static final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction(); //得到action
//创建一个蓝牙device对象 从Intent中获取设备对象
btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
btDeviceList.add(btDevice);
//获取已配对蓝牙列表
// Set devices = blueadapter.getBondedDevices();
// for (BluetoothDevice bluetoothDevice : devices) {
// pairedDeviceNameList.add(bluetoothDevice.getName());
// }
//发现设备
if(BluetoothDevice.ACTION_FOUND.equals(action)){
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceMsgList.add(device.getName() + " " + device.getAddress());//将搜索到的蓝牙名称和地址添加到列表
deviceNameList.add(device.getName()); //将搜索到的蓝牙名称添加到列表
deviceMacList.add(device.getAddress()); //将搜索到的蓝牙地址添加到列表
Log.w("-----------------", deviceMsgList.get(deviceMsgList.size()-1));
items[deviceMsgList.size()-1] = deviceMsgList.get(deviceMsgList.size()-1);
adapter.notifyDataSetChanged();
}
}
};
private static void doDiscovry() {
if (blueadapter.isDiscovering()) {
//判断蓝牙是否正在扫描,如果是调用取消扫描方法;如果不是,则开始扫描
blueadapter.cancelDiscovery();
} else
blueadapter.startDiscovery();
}
//搜索到的蓝牙列表
private void showListDialog() {
final AlertDialog.Builder listDialog = new AlertDialog.Builder(context);
adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, items);
listDialog.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
for(int j = 0; j < btDeviceList.size(); j++) {
if(btDeviceList.get(j).getAddress().equals(btDeviceList.get(i).getAddress())) {
deviceMatching = true;
deviceMatchingNum = j;
}
}
//连接配对
if(deviceMatching) {
//HC-05设备如果有多个,第一个搜到的那个会被尝试。
if (btDeviceList.get(deviceMatchingNum).getBondState() == BluetoothDevice.BOND_NONE) {
//未配对 进行配对
try {
//通过工具类ClsUtils,调用createBond方法
PairUtils.createBond(btDeviceList.get(deviceMatchingNum).getClass(), btDeviceList.get(deviceMatchingNum));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
//已配对 进行连接
//mac 要连接的目标蓝牙设备MAC地址
new ConnectTask().execute(deviceMacList.get(deviceMatchingNum));
}
}
}
});
listDialog.setPositiveButton("返回", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface paramAnonymousDialogInterface, int paramAnonymousInt) {
listDialog.create();
}
});
listDialog.show();
}
//连接蓝牙设备的异步任务
static class ConnectTask extends AsyncTask<String,String,String> {
@Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
BluetoothDevice device = blueadapter.getRemoteDevice(params[0]);
try {
btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
btSocket.connect();
Log.e("error", "ON RESUME: BT connection established, data transfer link open.");
} catch (IOException e) {
try {
//将异常信息传递给回调接口
if(getOnConnectListener() != null) {
getOnConnectListener().onConnectFailed(e);
}
btSocket.close();
return "Socket 创建失败";
} catch (IOException e2) {
//将异常信息传递给回调接口
if(getOnConnectListener() != null) {
getOnConnectListener().onConnectFailed(e2);
}
Log .e("error","ON RESUME: Unable to close socket during connection failure", e2);
return "Socket 关闭失败";
}
}
//取消搜索
blueadapter.cancelDiscovery();
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
//将异常信息传递给回调接口
if(getOnConnectListener() != null) {
getOnConnectListener().onConnectFailed(e);
}
Log.e("error", "ON RESUME: Output stream creation failed.", e);
return "Socket 流创建失败";
}
return "蓝牙连接正常,Socket 创建成功";
}
@Override //这个方法是在主线程中运行的,所以可以更新界面
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
//连接成功则启动监听
rThread = new ReceiveThread();
rThread.start();
Log.e("Bluetooth", "连接状态:" + result);
super.onPostExecute(result);
}
}
//从蓝牙接收信息的线程
static class ReceiveThread extends Thread {
@Override
public void run() {
while(btSocket != null ) {
//定义一个存储空间buff
byte[] buff = new byte[1024];
try {
inStream = btSocket.getInputStream();
System.out.println("waitting for instream");
if(inStream != null) {
inStream.read(buff); //读取数据存储在buff数组中
}
processBuffer(buff,1024);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void processBuffer(byte[] buff,int size) {
int length = 0;
for(int i = 0; i < size; i++) {
if(buff[i] > '\0') {
length++;
} else {
break;
}
}
//newbuff字节数组,用于存放真正接收到的数据
byte[] newbuff = new byte[length];
int[] receiveData = new int[length];
for(int j = 0; j < length; j++) {
newbuff[j] = buff[j];
receiveData[j] = buff[j] & 0xff;
}
Log.w("收到数据: ", Arrays.toString(receiveData));
//回调
if(getOnConnectListener() != null) {
getOnConnectListener().onConnectSuccess(receiveData);
}
}
}
//发送String数据到蓝牙设备的异步任务
static class SendInfoTask extends AsyncTask<String,String,String> {
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.e("Bluetooth", "连接状态:" + result);
}
@Override
protected String doInBackground(String... arg0) {
// TODO Auto-generated method stub
if(btSocket == null) {
new ConnectTask().execute(deviceMacList.get(deviceMatchingNum));
return "还没有创建连接";
}
if(arg0[0].length()>0) {
//不是空白串
//String target=arg0[0];
byte[] msgBuffer = arg0[0].getBytes();
try {
if(outStream != null) {
// 将msgBuffer中的数据写到outStream对象中
outStream.write(msgBuffer);
}
} catch (IOException e) {
Log.e("error", "ON RESUME: Exception during write.", e);
return "发送失败";
}
}
return "发送成功";
}
}
//发送byte数据到蓝牙设备的异步任务
/*
static class SendInfoTask extends AsyncTask {
@Override
protected String doInBackground(byte[]... bytes) {
try {
outStream.write(bytes[0]);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
*/
//回调接口
public interface OnConnectListener{
//连接成功
void onConnectSuccess(int[] msg);
//连接异常信息
void onConnectFailed(Exception e);
}
public static OnConnectListener getOnConnectListener() {
return onConnectListener;
}
public void setOnConnectListener(OnConnectListener onConnectListener) {
this.onConnectListener = onConnectListener;
}
public static Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
}
配对工具类
/**
* @anthor GrainRain
* @funcation 配对工具类
* @date 2019/10/25
*/
public class PairUtils {
/**
* 与设备配对 参考源码:platform/packages/apps/Settings.git
* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
static public boolean createBond(Class btClass, BluetoothDevice btDevice) throws Exception {
Method createBondMethod = btClass.getMethod("createBond");
Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
return returnValue.booleanValue();
}
/**
* 与设备解除配对 参考源码:platform/packages/apps/Settings.git
* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
static public boolean removeBond(Class<?> btClass, BluetoothDevice btDevice) throws Exception {
Method removeBondMethod = btClass.getMethod("removeBond");
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
return returnValue.booleanValue();
}
static public boolean setPin(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice,
String str) throws Exception {
try {
Method removeBondMethod = btClass.getDeclaredMethod("setPin", byte[].class);
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,
new Object[]{
str.getBytes() });
Log.e("returnValue", "" + returnValue);
} catch (SecurityException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (IllegalArgumentException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
// 取消用户输入
static public boolean cancelPairingUserInput(Class<?> btClass, BluetoothDevice device)
throws Exception {
Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
// cancelBondProcess(btClass, device);
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
return returnValue.booleanValue();
}
// 取消配对
static public boolean cancelBondProcess(Class<?> btClass, BluetoothDevice device) throws Exception {
Method createBondMethod = btClass.getMethod("cancelBondProcess");
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
return returnValue.booleanValue();
}
//确认配对
static public void setPairingConfirmation(Class<?> btClass,BluetoothDevice device,boolean isConfirm)throws Exception {
Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation",boolean.class);
setPairingConfirmation.invoke(device,isConfirm);
}
/**
*
* @param clsShow
*/
static public void printAllInform(Class clsShow) {
try {
// 取得所有方法
Method[] hideMethod = clsShow.getMethods();
int i = 0;
for (; i < hideMethod.length; i++) {
Log.e("method name", hideMethod[i].getName() + ";and the i is:" + i);
}
// 取得所有常量
Field[] allFields = clsShow.getFields();
for (i = 0; i < allFields.length; i++) {
Log.e("Field name", allFields[i].getName());
}
} catch (SecurityException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (IllegalArgumentException e) {
// throw new RuntimeException(e.getMessage());
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
使用 activity
//打开蓝牙
if(!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
BluetoothAdapter.getDefaultAdapter().enable();
}
通过回调接收信息
new Util().get(BlueAct.this, new Util.OnConnectListener() {
@Override
public void onConnectSuccess(int[] msg) {
}
@Override
public void onConnectFailed(Exception e) {
}
});