Android设备睡眠时,AlarmManager闹钟无法正常工作

4

我需要在一段时间内运行一段代码,即使应用程序被杀死或设备处于睡眠状态。

我正在使用AlarmManager来实现这一点,但当设备休眠约五分钟时,Service不再被调用...... 有人知道我做错了什么吗?

这是我的代码:

public class Profiler extends IntentService {

    public static final int ALARM_MANAGER_ID = 21436587;

    public Profiler() {
        super("Profiler");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        JodaTimeAndroid.init(getApplicationContext());
        System.out.println("Testing profiles");
        List<Profile> profiles = MainActivity.getStoredProfiles(getApplicationContext());

        if (profiles != null) {
            for (Profile profile : profiles) {
                if(profile.check()) {
                    profile.set(getApplicationContext());
                }
            }
        }

        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        Intent intent2 = new Intent(getApplicationContext(), Profiler.class);
        PendingIntent pIntent = PendingIntent.getService(getApplicationContext(), ALARM_MANAGER_ID, intent2, PendingIntent.FLAG_CANCEL_CURRENT);
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, DateTime.now().plusSeconds(10).getMillis(), pIntent);
    }
}

这是另一个问题。这种调用服务的方法可靠吗?
以下是日志。
07-24 11:31:24.654 17689-19078/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:31:34.671 17689-20364/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:31:34.673 17689-20364/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:31:34.674 17689-20364/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:31:44.692 17689-21571/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:31:44.693 17689-21571/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:31:44.694 17689-21571/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:31:54.704 17689-22753/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:31:54.705 17689-22753/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:31:54.706 17689-22753/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:32:04.717 17689-24015/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:32:04.718 17689-24015/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:32:04.718 17689-24015/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}
07-24 11:35:29.032 17689-17475/cz.fjerabek.soundprofiler I/System.out: Testing profiles
07-24 11:35:29.040 17689-17475/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":11,"minute":15}
07-24 11:35:29.050 17689-17475/cz.fjerabek.soundprofiler I/System.out: {"type":"Time","hour":0,"minute":0}

                                                                       [ 07-24 11:35:29.056 17476:17476 I/         ]
                                                                       power log dlsym ok

应用程序在11:31启动,现在是11:40,你可以看到代码的最后执行时间是11:35,在那之前是11:32,间隔为3分钟,似乎每5分钟调用一次。

我正在使用以下方式启动服务:

Intent bgServiceIntent = new Intent(getApplicationContext(), Profiler.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        if(checkNotificationPolicy(getApplicationContext())) {
            startService(bgServiceIntent);
        }
    } else {
        startService(bgServiceIntent);
    }

我使用的设备是:华为P9 Lite(VNS-L21)


请使用Jobscheduler API而不是AlarmManager。 - SriMaharshi Manchem
JobSchedular不是一个合适的想法...向后兼容可能会成为一个问题。 - Abdul Waheed
是的,可能存在向后兼容性问题。minTargetSDK 应该为 21。 - SriMaharshi Manchem
1个回答

5
问题的原因很可能是Doze
根据其有关AlarmManager的文档:
引入了两种新的AlarmManager方法,以帮助安排闹钟:setAndAllowWhileIdle()和setExactAndAllowWhileIdle()。使用这些方法,您可以设置即使设备处于Doze模式下也会触发的闹钟。
根据API级别调用适当的AlarmManager方法,以确保即使设备处于睡眠状态,闹钟也会响起。
if (Build.VERSION.SDK_INT >= 23) {
    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
            alarmMillis, alarmIntent);
} else if (Build.VERSION.SDK_INT >= 19) {
    alarmManager.setExact(AlarmManager.RTC_WAKEUP,
            alarmMillis, alarmIntent);
} else {
    alarmManager.set(AlarmManager.RTC_WAKEUP,
            alarmMillis, alarmIntent);
}

请考虑以下内容:

setAndAllowWhileIdle()setExactAndAllowWhileIdle() 每个应用每 9 分钟只能触发一次闹钟。

你说你正在华为设备上进行测试。

华为(和其他制造商)实现了某些省电功能,可能会阻止闹钟响起。你需要将你的应用添加到“受保护”的应用中。

请查看以下问题:12

不建议以编程方式执行此操作,一个适当的解决方案是,在启动时警告用户(例如使用 AlertDialog),要求用户在电池管理器中手动将您的应用程序“受保护”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接