运行 在 phone 打瞌睡时在后台运行的应用程序
Run application in background when phone in Doze
应用程序是 运行ning SDK 23 及更高版本。在完成任务并使用 AlaramManager (setExactAndAllowWhileIdle) 安排下一个任务后,我正在 运行 使用 Service 执行一些任务。这工作正常。如果 phone 连续闲置 2 或 3 天,则它会进入打瞌睡模式。打瞌睡模式后,应用程序失去网络和唤醒锁也无法正常工作。
即使 phone 打瞌睡,我们是否可以 运行 具有任何网络干预的应用程序 issues.I 试图保留应用程序白名单,但我需要设备被 root。
adb shell dumpsys deviceidle whitelist +<Package Name>
谁能建议我不间断地 运行 应用程序的最佳方式?
您可以请求 android 通过发送高优先级 GCM 消息将您的应用列入休眠模式白名单。但请记住,这可能会使您的应用无法获得 Google Play:
的批准
Intent intent = new Intent();
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
else {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
}
context.startActivity(intent);
https://developer.android.com/training/monitoring-device-state/doze-standby.html#whitelisting-cases
实际上,如果没有 运行 前台服务,就无法做到这一点。列入白名单可能不适合您的应用程序,即使它适合您,您也要求用户授予您许可,从最终用户的角度来看,这可能被视为危险的事情。
不过,我有一个窍门。收听 android 的广播,当您发现该设备将进入休眠模式时,启动前台服务。在大多数情况下,用户将无法看到您的前台通知图像,也不知道您是 运行 服务。因为设备处于打瞌睡模式,这意味着它在用户不看的地方是稳定的。所以你可以做任何需要做的事情。
您还可以收听休眠模式结束时发送的广播。发生这种情况时,请停止您的前台服务并按照您的正常逻辑与警报管理器一起工作。
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(intent.getAction().equals("android.os.action.DEVICE_IDLE_MODE_CHANGED")){
if (pm.isDeviceIdleMode()) {
startForegroundService();
//stopAlarmManagerLogic();
} else {
stopForegroundService();
//startAlarmManagerLogic();
return;
}
return;
}
}
Android N 后,任何应用程序都不能运行 永远在后台。但是,您可以使用 Firebase Job Dispatcher,它可以帮助您 运行 您的应用程序,即使它处于休眠模式。在 Firebase Job Dispatcher 的帮助下,如果提供的条件匹配,您可以告诉系统您的应用应该在特定时间 运行。
Edit-WakefulBroadcastReceiver
现在 已弃用
首先,在 AlarmManager
中调用广播接收器而不是直接调用服务,然后调用该服务。
广播接收器应该扩展 WakefulBroadcastReceiver
而不是常规的 BroadcastReceiver
。
然后,让广播接收器安排一个新的警报,使用 startWakefulService()
代替 startService()
启动服务
public class MyAwesomeReceiver extends WakefulBroadcastReceiver {
int interval=2*60*60*1000;
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, MyAwesomeService.class);
Intent receiverIntent = new Intent(context, MyAwesomeReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 11, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+interval,alarmIntent);
startWakefulService(context, serviceIntent);
}
}
WakefulBroadcastReceiver
和 startWakefulService()
会让您的应用程序有 10 秒的时间 window 来完成它需要做的事情。
此外,
您始终可以要求用户使用-
让您的应用忽略电池优化功能
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
Intent intent=new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (powerManager.isIgnoringBatteryOptimizations(getPackageName())) {
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
}
else {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
并在清单中
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"></uses-permission>
应用程序是 运行ning SDK 23 及更高版本。在完成任务并使用 AlaramManager (setExactAndAllowWhileIdle) 安排下一个任务后,我正在 运行 使用 Service 执行一些任务。这工作正常。如果 phone 连续闲置 2 或 3 天,则它会进入打瞌睡模式。打瞌睡模式后,应用程序失去网络和唤醒锁也无法正常工作。
即使 phone 打瞌睡,我们是否可以 运行 具有任何网络干预的应用程序 issues.I 试图保留应用程序白名单,但我需要设备被 root。
adb shell dumpsys deviceidle whitelist +<Package Name>
谁能建议我不间断地 运行 应用程序的最佳方式?
您可以请求 android 通过发送高优先级 GCM 消息将您的应用列入休眠模式白名单。但请记住,这可能会使您的应用无法获得 Google Play:
的批准Intent intent = new Intent();
String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
else {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
}
context.startActivity(intent);
https://developer.android.com/training/monitoring-device-state/doze-standby.html#whitelisting-cases
实际上,如果没有 运行 前台服务,就无法做到这一点。列入白名单可能不适合您的应用程序,即使它适合您,您也要求用户授予您许可,从最终用户的角度来看,这可能被视为危险的事情。
不过,我有一个窍门。收听 android 的广播,当您发现该设备将进入休眠模式时,启动前台服务。在大多数情况下,用户将无法看到您的前台通知图像,也不知道您是 运行 服务。因为设备处于打瞌睡模式,这意味着它在用户不看的地方是稳定的。所以你可以做任何需要做的事情。
您还可以收听休眠模式结束时发送的广播。发生这种情况时,请停止您的前台服务并按照您的正常逻辑与警报管理器一起工作。
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(intent.getAction().equals("android.os.action.DEVICE_IDLE_MODE_CHANGED")){
if (pm.isDeviceIdleMode()) {
startForegroundService();
//stopAlarmManagerLogic();
} else {
stopForegroundService();
//startAlarmManagerLogic();
return;
}
return;
}
}
Android N 后,任何应用程序都不能运行 永远在后台。但是,您可以使用 Firebase Job Dispatcher,它可以帮助您 运行 您的应用程序,即使它处于休眠模式。在 Firebase Job Dispatcher 的帮助下,如果提供的条件匹配,您可以告诉系统您的应用应该在特定时间 运行。
Edit-WakefulBroadcastReceiver
现在 已弃用
首先,在 AlarmManager
中调用广播接收器而不是直接调用服务,然后调用该服务。
广播接收器应该扩展 WakefulBroadcastReceiver
而不是常规的 BroadcastReceiver
。
然后,让广播接收器安排一个新的警报,使用 startWakefulService()
代替 startService()
public class MyAwesomeReceiver extends WakefulBroadcastReceiver {
int interval=2*60*60*1000;
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, MyAwesomeService.class);
Intent receiverIntent = new Intent(context, MyAwesomeReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 11, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+interval,alarmIntent);
startWakefulService(context, serviceIntent);
}
}
WakefulBroadcastReceiver
和 startWakefulService()
会让您的应用程序有 10 秒的时间 window 来完成它需要做的事情。
此外,
您始终可以要求用户使用-
让您的应用忽略电池优化功能PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
Intent intent=new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (powerManager.isIgnoringBatteryOptimizations(getPackageName())) {
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
}
else {
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
并在清单中
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"></uses-permission>