实现功能
- 检测是否拥有蓝牙权限
- 监视蓝牙开关
- 监视蓝牙连接断开
- 获取蓝牙配对列表
- 获取当前连接的蓝牙信息
1.在AndroidManifest.xml文件中添加蓝牙权限
<!-- 定位权限,用于获取手机的大致或精准位置 于发现附近的蓝牙设备通常是必需的 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 允许应用程序发现和配对蓝牙设备 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADACCESS_FINE_LOCATIONMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 允许应用程序连接到已配对的蓝牙设备并进行数据传输 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 允许应用发起对蓝牙设备的连接 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
2.在Activity的onCreate方法中进行运行时的动态权限获取(如果是在Activity类里面申请的直接把(Activity) mUniSDKInstance.getContext()替换成this即可。120这可以随便写)
有人问为什么在AndroidManifest.xml文件中添加了蓝牙权限,为什么运行时还要申请一遍
应为在 Android 6.0 (API 级别 23) 及更高版本中,用户需要在运行时授予权限。对于一些需要特殊权限的操作(如定位、读写存储等),仅在 AndroidManifest.xml 文件中声明这些权限是不够的,你还需要在运行时进行权限请求
ActivityCompat.requestPermissions((Activity) mUniSDKInstance.getContext(), new String[]{Manifest.permission.BLUETOOTH}, 120);
注意:这个请求会在手机上面进行UI弹窗,点击允许即可如果点击拒绝会获取不到蓝牙的任何操作
3.创建自定义广播接收器(BroadcastReceiver)。这个类会响应系统发出的关于蓝牙状态的广播
实现
- 监视蓝牙开关
- 监视蓝牙连接断开
- 获取当前连接的蓝牙信息
package io.bluet.uniplugin;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* 全局蓝牙广播器
*/
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e("Bluetooth", "action: "+action);
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
//蓝牙设备已断开连接
Log.e("Bluetooth", "蓝牙设备已断开连接");
}else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)){
//蓝牙连接
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e("Bluetooth", "蓝牙连接");
Log.e("Bluetooth", "连接蓝牙的名称: "+device.getName());
Log.e("Bluetooth", "连接蓝牙的地址: "+device.getAddress());
}
// 判断蓝牙是否打开
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
switch(state) {
case BluetoothAdapter.STATE_TURNING_ON:
// 蓝牙正在打开
Log.e("Bluetooth", "蓝牙正在打开");
break;
case BluetoothAdapter.STATE_ON:
// 蓝牙已经打开
Log.e("Bluetooth", "蓝牙已经打开");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
// 蓝牙正在关闭
Log.e("Bluetooth", "蓝牙正在关闭");
break;
case BluetoothAdapter.STATE_OFF:
// 蓝牙已经关闭
Log.e("Bluetooth", "蓝牙已经关闭");
break;
}
}
}
}
4.在AndroidManifest.xml文件中注册您的自定义广播接收器(BroadcastReceiver)的配置项
<receiver android:name="io.bluet.uniplugin.MyBroadcastReceiver" android:exported="true" android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
</intent-filter>
</receiver>
android:name
属性指定了您的广播接收器的完全限定类名(包名 + 类名)
android:exported="true"
表示其他应用可以给您的应用发送此广播。如果为"false"
则表示只有系统或者应用内部可以发送此广播
android:launchMode="singleInstance"
表示此接收器的启动模式为单实例模式,即在进程存在的情况下不会重新创建接收器,而是复用已存在的实例
<intent-filter>
标签为您的广播接收器定义了一个意图过滤器。这意味着您的广播接收器只接收满足过滤器配置的广播
过滤器配置了三个<action>
,分别为:
-
android.bluetooth.device.action.ACL_CONNECTED
: 蓝牙设备已连接的广播; -
android.bluetooth.device.action.ACL_DISCONNECTED
: 蓝牙设备已断开的广播; -
android.bluetooth.adapter.action.STATE_CHANGED
: 蓝牙状态已改变的广播。
在AndroidManifest.xml文件中的定义,MyBroadcastReceiver
是全局的广播接收器
注意:上面的代码判断不了第一次进入app蓝牙的问题 。应为进入app的时候才注册的广播接收器之前的蓝牙操作是检测不到的,只能检测在app内操作蓝牙的消息,app外操作的蓝牙是检测不到的。
5.下面代码是解决第一次进入app检测不到蓝牙通知的代码方法(每次进入app先使用这个进行判断蓝牙的一些列操作,后面app内的蓝牙操作可以用上面的广播进行实时获取蓝牙信息)
public static void checkBluetoothPermissions(Context context){
BluetoothAdapter defaultAdapter = BluetoothAdapter.getDefaultAdapter();
if (defaultAdapter == null){
// 设备不支持蓝牙功能
Log.e("Bluetooth", "设备不支持蓝牙功能");
return;
}else{
if (!defaultAdapter.isEnabled()){
//蓝牙未开启
Log.e("Bluetooth", "蓝牙未开启");
return;
}else{
// 蓝牙已开启
Log.e("Bluetooth", "蓝牙已开启");
}
}
try {
Set<BluetoothDevice> bluetoothDeviceSet = defaultAdapter.getBondedDevices();
if (bluetoothDeviceSet.size() > 0){ //判断适配器里面是否有自己的耳机
for (BluetoothDevice device : bluetoothDeviceSet) { //这里的循环是获取手机里面所有配对成功的蓝牙信息
// device 是已配对或已连接的蓝牙设备
String deviceName = device.getName(); // 获取设备名称
String deviceHardwareAddress = device.getAddress(); // 获取设备MAC地址
// 根据设备的名称或地址,判断是哪一个蓝牙设备
Log.e("Bluetooth", "蓝牙名称: "+device.getName());
Log.e("Bluetooth", "蓝牙地址: "+device.getAddress());
// Test 改成独特的耳机名称
if ("Test".equals(deviceName)){
defaultAdapter.getProfileProxy(context, new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile bluetoothProfile) {
List<BluetoothDevice> devices = bluetoothProfile.getConnectedDevices();
for (BluetoothDevice device : devices) {
// device 是已连接的蓝牙设备
String deviceName = device.getName(); // 获取设备名称
String deviceHardwareAddress = device.getAddress(); // 获取设备MAC地址
// 根据设备的名称或地址,判断是哪一个蓝牙设备
if ("Test".equals(deviceName)){
}else{
}
}
}
@Override
public void onServiceDisconnected(int i) {
}
}, BluetoothProfile.A2DP);
}else{
}
}
}else{
Log.e("Bluetooth", "蓝牙列表里面没有配对或已连接的蓝牙设备");
}
}catch (SecurityException e){
Log.e("Bluetooth","获取不到蓝牙权限");
}
}
Activity类里面的方法可以监听到app的生命周期,比如退出,进入,切换app。但是要在AndroidManifest.xml配置程序的入口
<activity
android:name="com.xxx.xxx.MyActivity改成自己的Activity程序入口类即可"
android:configChanges="orientation|keyboardHidden|keyboard|navigation"
android:label="@string/app_name"
android:launchMode="singleTask"
android:hardwareAccelerated="true"
android:theme="@style/TranslucentTheme"
android:screenOrientation="user"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>