项目需要后台保活,但无论怎么保活,只要用户主动kill掉,app依然是活不了。

发现了蓝牙唤醒这个方式,用户主动kill掉也可行。

Android 8.0开始提供了 startscan的方法,

public void startScan(ScanCallback callback)

public void startScan(List filters,ScanSettings settings,ScanCallback callback)

public int startScan(List filters,ScanSettings settings,PendingIntent callbackIntent)

第一个没有过滤条件,锁屏就停止扫描

第二个可以加过滤条件,锁屏不影响扫描

第三个的扫描结果由PendingIntent发送,即使app没有在运行,系统也可以扫描后唤醒app,这就是我们要的方法了。

一、一些概念

PendingIntent是对Intent的封装,是满足某些条件或触发某些事件后才执行指定的行为,主要用于闹钟、通知、桌面部件。Android的四大组件之间通信用Intent,跨进程通信用PendingIntent。

Android 8.0 引进了Context.startForegroundService(),在系统创建服务后,应用需要在ANR发生前调用startForeground(int ,android.app.Notification),如果未及时调用该方法,系统将报ANR错误 。系统给前台服务的ANR时间是20秒。

用startScan蓝牙唤醒的原理是:app向系统订阅了扫描结果(预先加了过滤条件),当蓝牙连接断开的时候,设备就会发广播,这时系统就可以扫描到对应的广播,唤醒对应的service,这时想做什么操作就根据你的项目需要了。至于系统会为你扫描多久,这个还没测试。

二、权限

三、动态请求定位权限(Android 6以上必须要)/**

* 请求位置权限

*/

public void requestLocationService() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

if (isGpsEnabled()) {

if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 99);

}

}else {

AlertDialog.Builder builder =new AlertDialog.Builder(this);

builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialogInterface, int i) {

// Show location settings when the user acknowledges the alert dialog

Intent intent =new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);

startActivity(intent);

}

});

Dialog alertDialog = builder.create();

alertDialog.getWindow().setGravity(Gravity.CENTER);

alertDialog.setCanceledOnTouchOutside(false);

alertDialog.show();

}

}

}

/**

* 判断位置权限是否打开

*

* @return

*/

public boolean isGpsEnabled() {

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

if (locationManager ==null) {

return false;

}

boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

return gps || network;

}

四、开启服务@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

///请求位置权限

requestLocationService();

///开启服务

startForegroundService(new Intent(this, TestService.class));

}

五、开启蓝牙扫描@RequiresApi(api = Build.VERSION_CODES.O)

private void onOPEN() {

List scanFilterList =new ArrayList<>();

ScanFilter.Builder builder =new ScanFilter.Builder();

builder.setServiceUuid(ParcelUuid.fromString("设备广播的UUID"));

ScanFilter scanFilter = builder.build();

scanFilterList.add(scanFilter);

ScanSettings.Builder settingBuilder =new ScanSettings.Builder();

settingBuilder.setScanMode(ScanSettings.SCAN_MODE_BALANCED);

settingBuilder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);

settingBuilder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);

settingBuilder.setLegacy(true);

ScanSettings settings = settingBuilder.build();

callbackIntent = PendingIntent.getForegroundService(this, 1, new Intent(action).setPackage(getPackageName()), PendingIntent.FLAG_UPDATE_CURRENT);

//启动蓝牙扫描

bluetoothAdapter.getBluetoothLeScanner().startScan(scanFilterList, settings, callbackIntent);

}

(1)setScanMode有四个参数可以选 :

SCAN_MODE_BALANCED:在平衡电源模式下执行蓝牙LE扫描。返回扫描结果的速度能够很好地权衡扫描频率和功耗。

SCAN_MODE_LOW_LATENCY:扫描使用最高占空比。建议只在应用程序在前台运行时使用此模式。

SCAN_MODE_LOW_POWER:在低功耗模式下执行蓝牙LE扫描。这是默认的扫描模式,因为它消耗的能量最少。如果扫描应用程序不在前台,则强制执行此模式。

SCAN_MODE_OPPORTUNISTIC:一种特殊的蓝牙LE扫描模式。使用这种扫描模式的应用程序将被动地侦听其他扫描结果,而不启动BLE扫描本身

(2)settingBuilder.setMatchMode有两个参数可以选:

MATCH_MODE_AGGRESSIVE:  信号弱也会报告

MATCH_MODE_STICKY:  信号比较强和扫描到的次数比较多才会报告

(3)settingBuilder.setCallbackType也有其他参数可选,但适用的就一个

(4)  ScanFilter  的过滤方法有几个,如下图,打勾的是测试了可行的,但只有第一个DeviceAddress有唯一性

六、服务里接收扫描结果@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Log.i(TAG, "onStartCommand");

if (intent.getAction() ==null) {

return super.onStartCommand(intent, flags, startId);

}

//获取返回的错误码-1

int errorCode = intent.getIntExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, -1);//ScanSettings.SCAN_FAILED_*

Log.i(TAG, "errorCode=" + errorCode);

//获取到的蓝牙设备的回调类型  1=CALLBACK_TYPE_ALL_MATCHES

int callbackType = intent.getIntExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, -1);//ScanSettings.CALLBACK_TYPE_*

Log.i(TAG, "callbackType=" + callbackType);

List scanResults = (List) intent.getSerializableExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT);

if (scanResults !=null) {

for (ScanResult result : scanResults) {

Log.i(TAG, result.getDevice().getName() +",," + result.getDevice().getAddress() +",," + result.getRssi() +",," + result.getScanRecord());

}

}

return super.onStartCommand(intent, flags, startId);

}

七、service的onCreate()记得调用startForeground(int ,android.app.Notification)

android 定时唤醒蓝牙,Android保活——蓝牙唤醒(主动kill掉也可唤醒)相关推荐

  1. android定时提醒功能,Android后台定时提醒功能实现

    需要类似的功能,找了很久,估计这个能让我实现.转一下. https://blog.csdn.net/qq_34445403/article/details/78727477 考虑到自己每次在敲代码或者 ...

  2. android 定时闹钟逻辑,Android 定时执行任务 AlarmManager的使用(可用于闹钟开发)...

    Android 定时执行任务 AlarmManager的使用(可用于闹钟开发) 2011年7月13日加注:所有的定时任务在手机重启后会消失,如果需要重启后继续用,可以加个开机自启,然后重新设置. Al ...

  3. android 定时换图片,Android 定时器实现图片的变换

    Android 定时器实现图片的变换 在Android中,要让每秒进行一次ui更新,就需要利用到定时器和handler,message的结合,如果不使用handler就不能达到更新ui的效果,我的理解 ...

  4. android 定时提醒service,android之定时提醒功能(周循环)

    一.需求介绍 不日前项目有个需求,做个提醒功能,类似市面上闹钟功能.下面附上需求界面 首先对需求进行解析,基本上就是闹钟的功能,只不过简化了一点,就是只有两个闹钟,一个是接小孩上学闹钟提醒,一个是接小 ...

  5. android 定时换图片,android 视频和图片切换并进行自动轮播

    刚入android没多久,遇到的比较郁闷的问题就是子线程主线程的问题,更改UI界面,本想做一个图片的轮播但是比较简单,然后就试试实现视频跟图片切换播放进行不停的循环播放.也用过不少控件,但是知其然不知 ...

  6. android定时调用gc,Android性能:远程触发GC

    一.远程触发GC原理 我们都知道 GC 是java虚拟机释放内存的机制. 一般的在当前进程触发GC有两种方式: 主动触发.调用System.gc() 被动触发.预分配的内存不足 or OOM之前 有没 ...

  7. android 定时播放wav,Android MediaPlayer播放音频与视频

    播放音频 首先创建出一个MediaPlayer对象 MediaPlayer mMediaPlayer = new MediaPlayer(); 设置声音源 public static final St ...

  8. android心跳包作用,Android开发Im总结-5:心跳包

    心跳包的作用: TCP长连接本质上不需要心跳包来维持, 大家可以试一试, 让两台电脑连上同一个wifi, 然后让其中一台做服务器, 另一台用一个普通的没有设置KeepAlive的Socket连上服务器 ...

  9. 疯狂Java和Android面试题大全(Android版)

    疯狂Java和Android面试题大全(Android版) 本大全每个月会定期更新,索取网址:http://www.fkjava.org Java核心技术部分 Java核心技术部分的面试题,可能覆盖J ...

  10. Android 8.0 蓝牙唤醒 Ble 锁屏 保活 后台 持续扫描 进程拉活 自动唤醒

    主要是api的说明,嫌啰嗦的可以直接看demo,demo中有个检测锁屏时间重复开启扫描的代码,主要是如果APP没有获得电量或者后台运行的权限,只能持续后台运行几小时. 这个demo的作用是实现8.0以 ...

最新文章

  1. seaborn使用violinplot函数可视化水平小提琴图(Make Horizontal Violin Plot with violinplot in Seaborn)
  2. 总结概括对于大数据、高并发的网站如何进行优化的问题
  3. 一个有趣的this指向问题
  4. 2017-2018网络攻防第二周
  5. WGS 1984 Web Mercator 对于在线地图服务的意义
  6. AI到底有多吃香?推荐一个斯坦福、CMU、清北学生都在上的AI课
  7. 频谱知识图谱:面向未来频谱管理的智能引擎人工智能技术与咨询
  8. npm报错 npm WARN deprecated....的问题解决方式
  9. Listener 快速开始
  10. jQuery编写插件()
  11. 测试raid性能软件,IO性能测试-关于RAID不可不知的那些事儿
  12. 如何锻炼个人的演讲、写作与沟通能力
  13. android 方向键 按钮,这不科学!安卓虚拟按键、实体键谁更好?
  14. 乐高打印机robotc
  15. 请让我像亲人一样爱你
  16. 百度区块链 XuperChain开发教程(第二部分)
  17. java生成一条唯一的邀请码_如何实现用户id生成一个唯一邀请码
  18. 【MMU篇】一文总结ARMv8中的MMU架构
  19. python小说文本挖掘_Python小说文本挖掘正则表达式分析案例
  20. [附源码]Python计算机毕业设计Django小型银行管理系统

热门文章

  1. ubuntu之路——day7.1 衡量模型好坏的因素偏差和方差biasvariance 以及在深度学习中的模型优化思路...
  2. Python Selenium 调用IE浏览器失败Unexpected error launching Internet Explorer解决方法
  3. 归并排序(包含逆序数对的个数51Nod1019)
  4. selenium+python在Windows的环境搭建
  5. 前端复习-02-ajax原生以及jq和跨域方面的应用。
  6. Bootstrap-1
  7. Python3 学习第十二弹: 补充something
  8. AMD and CMD are dead之KMDjs内核之依赖分析
  9. 利用图片延迟加载来优化页面性能(jQuery)
  10. DreamWeaver插件–Javascript文件美化、自动缩进