最近在开发一个手机连接蓝牙设备的APP,其中有个需求是自动连接,用户不用确认。我在网上找到了一个工具类,但是网上很
多文章对这个工具类的使用方法都不能实现我的需求,要么弹出框不能隐藏,要么是隐藏输入框却不能配对成功。经过我多次尝
试,发现他们的配对方法用错了。
工具类:ClsUtils.java
/**************** 蓝牙配对函数 ***************/
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import android.bluetooth.BluetoothDevice;
import android.util.Log;
public class ClsUtils {
/**
* 与设备配对 参考源码: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", new Class[]{byte[].class});
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice, new Object[]{str.getBytes()});
Log.e("returnValue", "" + returnValue);
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
// 取消用户输入
static public boolean cancelPairingUserInput(Class<?> btClass, BluetoothDevice device) throws Exception {
Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
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) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
实现的界面,没有采用在Manifest文件里配置receiver的方法,因为发现那样配置结果还是会闪出配对密码输入框,附配对代码
本方法是根据蓝牙名称进行配对的,如需求不同可以自己该代码,不适用配对手机蓝牙设备,只适用于硬件开发中蓝牙模块中需
要输入密码的配对,(layout文件里只有一个按钮,这里就不给代码了):
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private BluetoothAdapter bluetoothAdapter;
private BluetoothDevice bluetoothDevice;
private Button search;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//开始配对按钮
search = findViewById(R.id.search_bluetooth);
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//检查蓝牙
if(bluetoothAdapter != null){
if(!bluetoothAdapter.isEnabled()){
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//设置蓝牙可见性
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,3000);
this.startActivity(intent);
//打开蓝牙
bluetoothAdapter.enable();
}
}else {
Toast.makeText(this,"本地设备驱动异常",Toast.LENGTH_LONG).show();
}
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//扫描设备
bluetoothAdapter.startDiscovery();
//注册广播
RegisterBluetoothReceiver();
}
});
}
//注册广播
public void RegisterBluetoothReceiver(){
// 设置广播信息过滤
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
// 注册广播接收器,接收并处理搜索结果
registerReceiver(BTReceive, intentFilter);
}
//处理蓝夜绑定的广播
private BroadcastReceiver BTReceive = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String bluetoothName;
if((bluetoothName = bluetoothDevice.getName()) != null){
// 如果查找到的设备符合要连接的设备,处理
if (bluetoothName.equalsIgnoreCase("HC-05")) {
//搜索蓝牙占用资源,搜索到后要及时关闭
bluetoothAdapter.cancelDiscovery();
//获取蓝牙的连接状态
int connectState = bluetoothDevice.getBondState();
switch (connectState){
//未配对
case BluetoothDevice.BOND_NONE:
//开始配对
try{
ClsUtils.createBond(bluetoothDevice.getClass(),bluetoothDevice);
}catch (Exception e){
e.printStackTrace();
}
break;
}
}
}
}else if(BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)){
try {
//如果不结束广播接收,配对界面会闪出
abortBroadcast();
//顺序一定要这样,否则会出问题
ClsUtils.setPin(bluetoothDevice.getClass(), bluetoothDevice, "1234");
//这行代码会在控制台报错
//ClsUtils.setPairingConfirmation(bluetoothDevice.getClass(), bluetoothDevice,true);
}catch (Exception e){
e.printStackTrace();
}
}
}
};
@Override
protected void onDestroy() {
super.onDestroy();
//注销广播
unregisterReceiver(BTReceive);
}
}
参考文章:https://blog.youkuaiyun.com/qq_30297763/article/details/79621137