美文网首页Android轮子
Android保活——蓝牙唤醒(主动kill掉也可唤醒)

Android保活——蓝牙唤醒(主动kill掉也可唤醒)

作者: Zoe_and_Android | 来源:发表于2019-12-26 17:57 被阅读0次

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

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

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

public void startScan(ScanCallback callback)

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

public int startScan(List<ScanFilter> 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,这时想做什么操作就根据你的项目需要了。至于系统会为你扫描多久,这个还没测试。

二、权限

<uses-permission android:name="android.permission.BLUETOOTH" />

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<uses-permission android:name="android.permission.FOREGROUND_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保活——蓝牙唤醒(主动kill掉也可唤醒)

    项目需要后台保活,但无论怎么保活,只要用户主动kill掉,app依然是活不了。 发现了蓝牙唤醒这个方式,用户主动k...

  • Android进程保活

    1、像素保活 2、提升进程优先级(前台进程) 3、进程间相互唤醒(Android5.0以前可用,Android 5...

  • Android 8.0 进程拉活 --- 蓝牙唤醒

    前言: IPhone 可以通过 ibeacon 设备发出的蓝牙广播来唤醒应用,但android有没有类似的机制来进...

  • Android耗电量优化

    导致Android电量消耗过快的原因 1.对设备的频繁唤醒 :在Android中AlarmManager可唤醒设备...

  • 如何使用蓝牙设备唤醒您的Mac?

    如何使用蓝牙设备唤醒您的电脑呢?您可以点按已配对的蓝牙鼠标,或按下已配对蓝牙键盘上的按键,以唤醒您的 Mac。您可...

  • 如何使用蓝牙设备唤醒您的Mac?

    如何使用蓝牙设备唤醒您的电脑呢?您可以点按已配对的蓝牙鼠标,或按下已配对蓝牙键盘上的按键,以唤醒您的 Mac。您可...

  • React Naitve唤醒三方APP

    可以通过此方法唤醒内置应用 如设置、电话簿.....或者调用三方应用 android唤醒 android 唤醒AP...

  • Android -- 进程保活

    提供几个进程保活技术:1像素Activity,前台服务,账号同步,Jobscheduler,相互唤醒,系统服务捆绑...

  • Android 进程优先级和 LowMemoryKiller 机

    一 进程生命周期 Android 系统会尽量长时间地保持应用进程,用户应用退出后,如果没有主动把进程 kill 掉...

  • 安卓进程保活

    1、通过各大手机厂商提供的推送服务,进行唤醒保活; 2、双进程相互守护保活,如果是手机有一键清理,就双双死掉了;不...

网友评论

    本文标题:Android保活——蓝牙唤醒(主动kill掉也可唤醒)

    本文链接:https://www.haomeiwen.com/subject/igfloctx.html