1.常规操作经典蓝牙
最近有一个功能需要使用蓝牙BLE,如果在使用之前蓝牙是关闭的状态,需要先打开蓝牙,并且在使用完之后,需要把蓝牙关闭。
我们的功能是在后台服务执行,最开始使用常规的方式判断并打开蓝牙:

boolean isEnableBefor = bluetoothAdapter.isEnabled();  //判断蓝牙是否打开
if (!isEnableBefor) {bluetoothAdapter.enable();  //使用常规方式打开蓝牙}

这个时候会打开整个经典蓝牙,然后用户界面也会感知到蓝牙的打开;如果用户正在使用,然后这个时候功能执行完毕关闭蓝牙,会让用户觉得体验很不友好,甚至认为这是个程序设计上的问题。

2.BLE和经典蓝牙的关系
于是决定本功能模块单独使用蓝牙BLE,而不去操作经典蓝牙,这样就不会影响到设置模块对蓝牙开关的操作逻辑了。
实际上我们在之前分析过,在打开蓝牙的过程中,首先就是打开BLE,在Android系统中对应的就是GattService;再打开BLE之后,再去打开其他的Profile服务,所有Profile服务开启完毕之后,再通过广播形式通知蓝牙开关打开成功。
我们可以把蓝牙BLE看成是整个经典蓝牙树的一个子集。我们现在要做的,就是只启动GattService 整个Profile,不去启动后面其他的Profile。

3.源码修改
实际上在源码中存在有单独操作BLE的方法,但在谷歌官方的SDK中,并没有开放这些方法。但源码位于:framework\base\core\java\android\bluetooth\BluetoothAdapter.java

 /*** Return true if Bluetooth LE(Always BLE On feature) is currently* enabled and ready for use* <p>This returns true if current state is either STATE_ON or STATE_BLE_ON** @return true if the local Bluetooth LE adapter is turned on* @hide*/@SystemApipublic boolean isLeEnabled() {final int state = getLeState();if (DBG) {Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));}return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);}
 * @return true to indicate Bluetooth LE will be available, or false on immediate error* @hide*/@SystemApipublic boolean enableBLE() {if (!isBleScanAlwaysAvailable()) {return false;}......return false;}

我们看到,这些方法都是隐藏的,而且必须是系统级应用才能调用。
我们要调用,需要去掉@SystemApi,然后再编译一个framework.jar,具体的操作可以看这里:编译自己的framework 或者用我已经编译好的jar包:framwork.jar

4.前提条件
在打开BLE之前我们还要做一件事,就是确保 isBleScanAlwaysAvailable()返回的是true,不然执行enableBLE()是没有作用的。我在一步步查看了Bluetooth源码之后发现,其实就是操作的一个全局的字段,可执行如下操作:

Settings.Global.putInt(context.getContentResolver(),Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,1);

这样就会保证对BLE的操作可以顺利执行下去了。

5.状态改变的广播接收
打开BLE的时候,是一个异步的过程,状态的改变蓝牙服务会通过广播的形式通知出来:

IntentFilter filter = new IntentFilter();filter.addAction(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);context.registerReceiver(btReceiver, filter);BroadcastReceiver btReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if(intent.getAction().equals(BluetoothAdapter.ACTION_BLE_STATE_CHANGED)){int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);Log.d(TAG,"ACTION_LE_STATE_CHANGED: " + state);if (BluetoothAdapter.STATE_BLE_ON == state || BluetoothAdapter.STATE_ON == state) {Log.d(TAG, "BluetoothBLE opened!");}}}};

Android单独打开和关闭BLE相关推荐

  1. Android 蓝牙 单独打开和关闭BLE - 详解

    同学,别退出呀,我可是全网最牛逼的 Android 蓝牙分析博主,我写了上百篇蓝牙文章,请点击下面了解本专栏,进入本博主主页看看再走呗,一定不会让你后悔的,记得一定要去看主页置顶文章哦. 1.常规操作 ...

  2. android打开sqlite数据库,Android:打开和关闭SQLite数据库

    我正在开发和android应用程序,我经常使用它访问本地数据库.这个数据库可以从不同的therads访问,所以我对数据库有一个协调问题.我使用以下open()和close()方法.Android:打开 ...

  3. Android Bluetooth打开和关闭的三种方式(很详细)

    转载:http://www.ifeegoo.com/android-turn-on-and-turn-off-bluetooth.html 摘要:Android 中打开和关闭 Bluetooth 的代 ...

  4. Android程序打开和关闭输入法

    2019独角兽企业重金招聘Python工程师标准>>> 一.打开输入法窗口: /*** 动态显示软键盘** @param context 上下文* @param edit 输入框*/ ...

  5. Android:打开和关闭输入法

    一.打开输入法窗口: InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INP ...

  6. android 关闭自动亮度,android – 如何打开和关闭自动亮度? (不重复)

    我只是试图打开和关闭自动亮度. 我开始使用此代码(在onCreate方法内) final ToggleButton autoBrightToggle = (ToggleButton) findView ...

  7. Android中打开扬声器关闭麦克风的代码实现

    //获取音频服务 AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);   ...

  8. android 页面退出动画,android Activity打开和关闭动画

    activity 之间的动画跳转,或者是关闭的的时候的动画关闭. public class SActivity extends AppCompatActivity { @Override protec ...

  9. Android 书本打开和关闭动画

    作者: Jooyer, 时间: 2018.12.08 Github地址,欢迎点赞,fork 我偶尔一次发现掌阅的打开书本动画不错,然后度娘了一下,发现一个链接:download.csdn.net/do ...

最新文章

  1. 创业思维 - Qunar的故事
  2. 某头条程序员吐槽:前同事银行流水造假,背调也是找同事编的!工资翻了300%!自己老实巴交提供真实银行流水,却惨遭压薪!...
  3. 如何在Python中声明一个数组?
  4. Extjs5.0 学习之路【资源篇】
  5. 比较完整的熊猫烧香解决方案
  6. 基于语音识别的智能垃圾分类控制系统设计
  7. 趣味项目—MyQQ机器人(二)关于python的pandas根据索引读写指定数据的方法实现签到功能
  8. 使用快解析一招解决电脑dns异常问题
  9. 基于Opencv3的活动轮廓模型--CV, RSF and DRLSE
  10. Directx11教程四十三之glow(边缘发光)
  11. POJ 1062 昂贵的聘礼【经典的最短路问题】
  12. sync failed 错误 springboot
  13. 自动化手工操作工具PyAutoGUI :鼠标操作
  14. go 判断切片是否存在某元素_Golang切片(Slice)
  15. 纸短情长 寄语青春 2021 我们毕业了!
  16. docker status exited(255)
  17. 计算机专业横向发展职业群,作为物联网什么是横向发展职业群
  18. 分账系统价格表的构成你了解吗?
  19. Anaconda3 + PyQt5 + Eric6 安装
  20. 你觉得什么是暴利行业?

热门文章

  1. 2016-04-01-信息系统实践手记4-平台对接的一些思考
  2. 搭建RobotFramework环境(Windows)
  3. 超好用!React 封装全屏弹框
  4. 智慧城市小程序如何将商家入驻入口一键关闭
  5. 名词解释atm网络_网络名词解释
  6. Spring Cloud构建微服务架构-Hystrix断路器
  7. 自然线代-阶梯形矩阵四
  8. win10/win11安装qt4.8
  9. android one s8,非官方的LineageOS 17.1将安卓10带入三星Galaxy S8和Note 8
  10. 微信接口返回invalid media_id hint原因分析