原文网址:http://www.ifeegoo.com/android-turn-on-and-turn-off-bluetooth.html

摘要:Android 中打开和关闭 Bluetooth 的代码虽然并不困难,但是我们还是需要注意一些细节和异常情况,这样我们才能更好的优化我们的与 Bluetooth 相关的应用。

Runtime Environment
OS: Windows 8.1
IDE: ADT Bundle v22.6.2
Device:
Nexus 5 / Android 4.4.4
MI 2SC / MIUI-4.7.11 (Android 4.1.1 JRO03L) Android 中打开和关闭 Bluetooth 的代码虽然并不困难,但是我们还是需要注意一些细节和异常情况,这样我们才能更好的优化我们的与 Bluetooth 相关的应用。

在研究打开和关闭 Bluetooth 之前,我们应该了解 Android 版本和 Bluetooth 版本之间的关系,请参考本博客文章 《Android 版本与 Bluetooth 版本之间的关系》。

Android 在 Android 2.0 Eclair / API Level 5 中就已经有开放的操作 Bluetooth 的 API 了,在此版本已经有以下公开类:

1 /**
2 * 本地 Bluetooth 适配器,执行基本的 Bluetooth 任务,例如:初始设备扫描、查询已经绑定
3 * (或已经配对)的设备、通过已知的 MAC 地址来实例化 BluetoothDevice 对象、创建
4 * BluetoothServerSocket 来监听其它设备的连接请求等。
5 */
6 BluetoothAdapter.java
7  
8 /**
9  * 描述设备的一般特性和能力。例如,它会指定一般设备类型,例如:手机、电脑、耳机等,还
10  * 有是否支持音频或电话等服务。但是不能可靠的描述诸如设备支持哪些 Profile 或者 Service。
11  */
12 BluetoothClass.java
13  
14 /**
15  * 表示一个远程的 Bluetooth 设备。它能让你与各个设备创建连接或者查询信息。
16  * 例如:名字、地址、类和绑定状态等。
17  */
18 BluetoothDevice.java
19  
20 /**
21  * Bluetooth socket 和 TCP socket 有些类似。最普通的 Bluetooth socket 类型是 RFCOMM,
22  * 这是 Android API 支持的类型。RFCOMM 是一个方向性的连接。通过 Bluetooth 传输流。
23  * 同样也称作 SPP (Serial Port Profile)。
24  */
25 BluetoothServerSocket.java
26 BluetoothSocket.java
Android 中打开 Bluetooth:有以下三种方法:
1.强制打开
2.调用系统弹出框提示用户打开
3.跳转到系统设置中让用户自己打开

1.强制打开 Bluetooth 的代码:

1 BluetoothAdapter.getDefaultAdapter() 需要注册权限:
2 "android.permission.BLUETOOTH" />
3  
4 BluetoothAdapter.enable() 需要注册权限:
5 "android.permission.BLUETOOTH_ADMIN" />
1 /**
2  * Bluetooth 管理类
3  *
4  * @author ifeegoo www.ifeegoo.com
5  *
6  */
7 public class BluetoothManager
8 {
9  
10     /**
11      * 当前 Android 设备是否支持 Bluetooth
12      *
13      * @return true:支持 Bluetooth false:不支持 Bluetooth
14      */
15     public static boolean isBluetoothSupported()
16     {
17         return BluetoothAdapter.getDefaultAdapter() != null ? true : false;
18     }
19  
20     /**
21      * 当前 Android 设备的 bluetooth 是否已经开启
22      *
23      * @return true:Bluetooth 已经开启 false:Bluetooth 未开启
24      */
25     public static boolean isBluetoothEnabled()
26     {
27         BluetoothAdapter bluetoothAdapter = BluetoothAdapter
28                 .getDefaultAdapter();
29  
30         if (bluetoothAdapter != null)
31         {
32             return bluetoothAdapter.isEnabled();
33         }
34  
35         return false;
36     }
37  
38     /**
39      * 强制开启当前 Android 设备的 Bluetooth
40      *
41      * @return true:强制打开 Bluetooth 成功 false:强制打开 Bluetooth 失败
42      */
43     public static boolean turnOnBluetooth()
44     {
45         BluetoothAdapter bluetoothAdapter = BluetoothAdapter
46                 .getDefaultAdapter();
47  
48         if (bluetoothAdapter != null)
49         {
50             return bluetoothAdapter.enable();
51         }
52  
53         return false;
54     }
55 }
以上强制打开 Bluetooth 是调用了 BluetoothAdapter.enable() 方法。首先需要获取 BluetoothAdapter 对象,如果这个对象为 null 的话,说明当前设备不支持 Bluetooth 功能。还有以下几点需要注意:
1° 在 Nexus 5 Android 4.4.4 原生系统中,在没有任何其它管理 Bluetooth 权限的应用情况下,调用强制打开 Bluetooth 的方法,没有任何提示就直接打开 Bluetooth 了。
2° 在小米手机 MI 2SC / MIUI-4.7.11 (Android 4.1.1 JRO03L) 上系统自带的 “安全中心” – “应用权限管理” – “开启蓝牙” 中,有三种设置:
允许:调用强制打开 Bluetooth 代码,没有任何提示,Bluetooth 被成功打开。
提示:会弹出提示框,提示安全警告 “ ***应用尝试开启蓝牙”,可以选择“拒绝”或“允许”,还有记住此次选择(备注:如果不记住的话,下次还会弹出同样的提示框,除非你自己去修改了应用开启蓝牙的权限)。
拒绝:调用强制打开 Bluetooth 代码,没有任何提示,Bluetooth 强制打开失败。
备注:各种手机自带的权限管理功能或者第三方权限管理应用略有不同。
3° 对于 BluetoothAdapter.enable() 这个方法,API 中有以下说明 (备注:初始 API 中,如 Android 2.0 Eclair / API Level 5 中并没有这段提示)
Bluetooth should never be enabled without direct user consent. If you want to turn on Bluetooth in order to create a wireless connection, you should use the ACTION_REQUEST_ENABLE Intent, which will raise a dialog that requests user permission to turn on Bluetooth. The enable() method is provided only for applications that include a user interface for changing system settings, such as a “power manager” app.
没有直接的用户的允许绝不要开启 Bluetooth。如果你想要打开 Bluetooth 创建一个无线连接,你应当使用 ACTION_REQUEST_ENABLE Intent,这样会弹出一个提示框提示用户是否开启 Bluetooth,enable() 方法仅提供给有 UI 、更改系统设置的应用来使用,例如“电源管理”应用。
从以上官方 API 提示可以看出:不建议你调用此方法来打开 Bluetooth,至少是在没有任何用户提醒的前提下!

2.调用系统弹出框提示用户打开:

1 this.startActivityForResult(requestBluetoothOn, REQUEST_CODE_BLUETOOTH_ON) 需要注册权限:
2 "android.permission.BLUETOOTH" />
1 public class MainActivity extends Activity
2 {
3     /**
4      * 自定义的打开 Bluetooth 的请求码,与 onActivityResult 中返回的 requestCode 匹配。
5      */
6     private static final int REQUEST_CODE_BLUETOOTH_ON = 1313;
7  
8     /**
9      * Bluetooth 设备可见时间,单位:秒。
10      */
11     private static final int BLUETOOTH_DISCOVERABLE_DURATION = 250;
12  
13     @Override
14     protected void onCreate(Bundle savedInstanceState)
15     {
16         super.onCreate(savedInstanceState);
17         this.setContentView(R.layout.activity_main);
18  
19         if ((BluetoothManager.isBluetoothSupported())
20                 && (!BluetoothManager.isBluetoothEnabled()))
21         {
22             this.turnOnBluetooth();
23         }
24     }
25  
26     /**
27      * 弹出系统弹框提示用户打开 Bluetooth
28      */
29     private void turnOnBluetooth()
30     {
31         // 请求打开 Bluetooth
32         Intent requestBluetoothOn = new Intent(
33                 BluetoothAdapter.ACTION_REQUEST_ENABLE);
34  
35         // 设置 Bluetooth 设备可以被其它 Bluetooth 设备扫描到
36         requestBluetoothOn
37                 .setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
38  
39         // 设置 Bluetooth 设备可见时间
40         requestBluetoothOn.putExtra(
41                 BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
42                 BLUETOOTH_DISCOVERABLE_DURATION);
43  
44         // 请求开启 Bluetooth
45         this.startActivityForResult(requestBluetoothOn,
46                 REQUEST_CODE_BLUETOOTH_ON);
47     }
48  
49     @Override
50     protected void onActivityResult(int requestCode, int resultCode, Intent data)
51     {
52         // requestCode 与请求开启 Bluetooth 传入的 requestCode 相对应
53         if (requestCode == REQUEST_CODE_BLUETOOTH_ON)
54         {
55             switch (resultCode)
56             {
57             // 点击确认按钮
58                 case Activity.RESULT_OK:
59                 {
60                     // TODO 用户选择开启 Bluetooth,Bluetooth 会被开启
61                 }
62                 break;
63  
64                 // 点击取消按钮或点击返回键
65                 case Activity.RESULT_CANCELED:
66                 {
67                     // TODO 用户拒绝打开 Bluetooth, Bluetooth 不会被开启
68                 }
69                 break;
70                 default:
71                 break;
72             }
73         }
74     }
75 }
对于以上弹出系统弹框提示用户打开 Bluetooth 的代码,有以下几点需要注意:
1° 这种调用系统的弹出框提示用户打开 Bluetooth 的方式,一般不会受到系统或者第三方权限管理应用的阻止。只有当你不提示用户的情况下,可以理解为“偷偷摸摸”的打开 Bluetooth ,这个是被认为侵犯用户的知情权,系统或者第三方权限管理应用可能加以阻止:直接禁止不提示用户的情况下打开 Bluetooth,或者提示用户,又或者是让用户自己选择哪些应用可以强制开启 Bluetooth。而在 Nexus 5 / Android 4.4.4 原生系统强制打开 Bluetooth 是没有任何提示,并且可以成功打开。
2° 弹出系统的提示框提醒用户打开 Bluetooth 的主要代码:
this.startActivityForResult(requestBluetoothOn,REQUEST_CODE_BLUETOOTH_ON);
注意:这个方法是需要 Activity 的对象来调用的!并且需要在 Activity 中重写 onActivityResult 方法来获取用户操作弹出提示框的结果!
3° 这种弹出的系统弹框,根据系统的不同,UI 会有所不同,下图左边是 Nexus 5 Android 4.4.4 系统手机显示效果,右边是小米手机 MI 2SC / MIUI-4.7.11 (Android 4.1.1 JRO03L) 系统显示的效果:
4° 如果你只设置了 Bluetooth 设备的可见时间,而不去调用 setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE) 方法的话,Bluetooth 依然是不可见的。你设置的 Bluetooth 的可见时间是不生效的,当前 Android 系统的 Bluetooth 不可见!
5° 设置 Bluetooth 设备的可见时间的时候,在 Android 4.4.2 官方 API 中的说明如下:
The current default is 120 seconds, and requests over 300 seconds will be capped. These values could change.
当前默认值是 120s ,300s 是上限。这些值可能会变。
目前测试出来的有以下结论:
— 可设置的可见时间为 [1,3600] s ,也就是最小1秒钟,最大1个小时。
— 设置的可见时间为 0 时,表示打开 Bluetooth 之后一直可见,设置小于0或者大于3600 时,系统会默认为 120s。
6° 如果你设备的 Bluetooth 已经打开,而且你不设置设备的可见时间的话,调用以上开启 Bluetooth 的方法,是不会有任何提示的。当然,如果 Bluetooth 已经开启,也可以通过这个方法来修改 Bluetooth 的可见性。

3.跳转到系统设置中让用户自己打开:

1 // 跳转到系统 Bluetooth 设置
2 this.startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
考虑到涉及用户隐私和用户体验,推荐以下方式开启 Bluetooth :
1° 采用强制开启 Bluetooth 的方式打开 Bluetooth ,但是调用强制开启 Bluetooth 代码之前,我们自己在应用中提示用户,我们的应用需要开启 Bluetooth ,让用户自己选择是否开启 Bluetooth 。自己在应用中提示用户我们需要开启 Bluetooth 相对于弹出系统的提示框提示用户当前应用需要开启 Bluetooth 的优势在于我们可以控制提示的内容和提示的方式以及 UI。
2° 假若用户选择了开启 Bluetooth,但是强制开启 Bluetooth 失败,比如系统自带的权限管理禁止你的应用开启 Bluetooth ,我们不去提示用户说当前系统禁止了应用开启 Bluetooth,让用户自己去解除禁止。这样显然用户体验很差。这种情况下,我们再去调用弹出系统提示框提醒用户打开 Bluetooth 即可。这种方式一般系统或者第三方应用不会禁止。
3° 如果弹出系统提示框提醒用户打开 Bluetooth 有问题的话,最后采用提示用户自己去系统 Bluetooth 设置中打开 Bluetooth,跳转到系统的 Bluetooth 设置界面。 Android 中关闭 Bluetooth:有以下俩种方法:
1.强制关闭
2.跳转到系统设置中让用户自己关闭

1.强制关闭:

1 BluetoothAdapter.getDefaultAdapter() 需要注册权限:
2 "android.permission.BLUETOOTH" />
3  
4 BluetoothAdapter.disable() 需要注册权限:
5 "android.permission.BLUETOOTH_ADMIN" />
1 /**
2  * Bluetooth 管理类
3  *
4  * @author ifeegoo www.ifeegoo.com
5  *
6  */
7 public class BluetoothManager
8 {
9     /**
10      * 当前 Android 设备是否支持 Bluetooth
11      *
12      * @return true:支持 Bluetooth false:不支持 Bluetooth
13      */
14     public static boolean isBluetoothSupported()
15     {
16         return BluetoothAdapter.getDefaultAdapter() != null ? true : false;
17     }
18  
19     /**
20      * 当前 Android 设备的 bluetooth 是否已经开启
21      *
22      * @return true:Bluetooth 已经开启 false:Bluetooth 未开启
23      */
24     public static boolean isBluetoothEnabled()
25     {
26         BluetoothAdapter bluetoothAdapter = BluetoothAdapter
27                 .getDefaultAdapter();
28  
29         if (bluetoothAdapter != null)
30         {
31             return bluetoothAdapter.isEnabled();
32         }
33  
34         return false;
35     }
36  
37     /**
38      * 强制开启当前 Android 设备的 Bluetooth
39      *
40      * @return true:强制打开 Bluetooth 成功 false:强制打开 Bluetooth 失败
41      */
42     public static boolean turnOnBluetooth()
43     {
44         BluetoothAdapter bluetoothAdapter = BluetoothAdapter
45                 .getDefaultAdapter();
46  
47         if (bluetoothAdapter != null)
48         {
49             return bluetoothAdapter.enable();
50         }
51  
52         return false;
53     }
54      
55     /**
56      * 强制关闭当前 Android 设备的 Bluetooth
57      *
58      * @return  true:强制关闭 Bluetooth 成功 false:强制关闭 Bluetooth 失败
59      */
60     public static boolean turnOffBluetooth()
61     {
62         BluetoothAdapter bluetoothAdapter = BluetoothAdapter
63                 .getDefaultAdapter();
64  
65         if (bluetoothAdapter != null)
66         {
67             return bluetoothAdapter.disable();
68         }
69  
70         return false;
71     }
72 }
以上强制关闭 Bluetooth 是调用了 BluetoothAdapter.disable() 方法。首先需要获取 BluetoothAdapter 对象,如果这个对象为 null 的话,说明当前设备不支持 Bluetooth 功能。还有以下几点需要注意:
1° 目前发现常见的系统或者第三方权限管理应用好像对关闭 Bluetooth 并不做限制。
2° 如果系统或者第三方权限管理应用限制你的应用关闭 Bluetooth 的话,请参考强制开启 Bluetooth 要注意的点 1° 和 2°。
3° 对于 BluetoothAdapter.disable() 这个方法,API 中有以下说明 (备注:初始 API 中,如 Android 2.0 Eclair / API Level 5 中并没有这段提示)
Bluetooth should never be disabled without direct user consent. The disable() method is provided only for applications that include a user interface for changing system settings, such as a “power manager” app.
没有直接的用户的允许绝不要关闭 Bluetooth。disable() 方法仅提供给有 UI 、更改系统设置的应用来使用,例如“电源管理”应用。
从以上官方 API 提示可以看出:不建议你调用此方法来关闭 Bluetooth,至少是在没有任何用户提醒的前提下!

2.跳转到系统设置中让用户自己关闭:

1 // 跳转到系统 Bluetooth 设置
2 this.startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
考虑到涉及用户隐私和用户体验,推荐以下方式关闭 Bluetooth :
1° 采用强制关闭 Bluetooth 的方式关闭 Bluetooth ,但是调用强制关闭 Bluetooth 代码之前,我们自己在应用中提示用户,我们的应用需要关闭 Bluetooth ,让用户自己选择是否关闭 Bluetooth 。自己在应用中提示用户我们需要关闭 Bluetooth ,暂时没有发现 Android 有提供了弹出系统提示框提示用户关闭 Bluetooth 的 API。
2° 假若用户选择了关闭 Bluetooth,但是强制关闭 Bluetooth 失败,比如系统自带的权限管理禁止你的应用关闭 Bluetooth ,我们不去提示用户说当前系统禁止了应用关闭 Bluetooth,让用户自己去解除禁止。这样显然用户体验很差。这种情况下,我们提示用户“由于某些原因导致应用关闭 Bluetooth 失败,请到系统设置中自己关闭 Bluetooth”,然后跳转到系统 Bluetooth 设置中。 本博客所有文章 如无特别注明均为原创。复制或转载请 以超链接形式注明转自 ifeegoo,原文地址《 Android:Bluetooth 的打开和关闭》

更多相关文章

  1. Android(安卓)Studio 开启方法提示(方法的文档说明)
  2. AndroidStudio快捷键整理--5
  3. 升级clockwork 3.0.0.5 后,无法刷包的解决方案(Amend to Edify)
  4. Android(安卓)Studio集成友盟SDK出现的问题解决及原因分析
  5. Android系列之SQLite与Android(安卓)Studio的数据交互
  6. 【android studio】解决模拟器无法打开问题
  7. Android(安卓)动态申请权限
  8. android 7.0 相机,拍照 调裁切提示 “无法加载此图片” 解决方案
  9. mac下启动adb并安装apk

随机推荐

  1. Android(安卓)数据库SQLite的使用简单Dem
  2. Android(安卓)启动模拟器是出现“Failed
  3. android 获取外置sd卡根目录
  4. 运行时权限解析以及申请的实现(可完美解决
  5. Android教程之MediaStore
  6. Android(安卓)操作软键盘
  7. android WebView加载html5介绍
  8. Android中的style和theme的用法
  9. Android实现页面悬浮显示
  10. Android(安卓)的res/values/colors自定义