在Doze

时间:2017-04-20 01:38:25

标签: android service android-service android-doze

应用程序正在运行SDK 23及更高版本。我在完成任务并使用AlaramManager(setExactAndAllowWhileIdle)安排下一个任务后使用Service运行一些任务。这工作正常。如果手机连续闲置2或3天,则进入打盹模式。打盹模式后,应用程序丢失网络和唤醒锁也无法正常工作。

即使手机是Doze也有办法,我们可以运行任何网络插入问题的应用程序。我试图保持应用程序的网络,但我需要设备根植。

adb shell dumpsys deviceidle whitelist +<Package Name>

有谁能建议我哪种方式可以不间断地运行应用程序?

4 个答案:

答案 0 :(得分:3)

您可以通过发送高pirority GCM消息,请求Android将您的应用程序列入白名单以打瞌睡模式。但请记住,这可能会使您的应用未获得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

答案 1 :(得分:3)

实际上没有运行前台服务就无法做到这一点。列入白名单可能不适合您的应用程序,即使它是,您要求用户给予您许可,从最终用户的角度来看,这可能被视为危险的东西。

然而,我有一个关于此的伎俩。听取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 {
            stopAutomationForegroundService();
            //startAlarmManagerLogic();
            return;
        }
        AutomationReceiver.completeWakefulIntent(intent);
        return;
    }
}

答案 2 :(得分:2)

首先,不是直接呼叫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);
        }
}

WakefulBroadcastReceiverstartWakefulService()会让您的应用在10秒内完成所需的操作。

此外,

您可以随时要求用户使用 -

让您的应用忽略电池优化功能
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>

答案 3 :(得分:0)

在Android N之后,没有应用可以永远在后台运行。但是,您可以使用Firebase Job Dispatcher,它可以帮助您运行应用程序,即使它处于打盹模式。在Firebase Job Dispatcher的帮助下,如果条件匹配,您可以告诉系统您的应用应该在特定时间运行。