【问题标题】:Android - AlarmManager is not working after app is closedAndroid - 应用程序关闭后,AlarmManager 不工作
【发布时间】:2020-10-03 16:25:04
【问题描述】:

我正在使用AlarmManager 在某个时间调用一个函数。它在 Genymotion Emulator 中成功运行,但在 Redmi、Honor 等真实设备中无法运行。这是代码。

     Intent intent = new Intent(CreateContact.this, DeleteContactReceiver.class);
     intent.putExtra("name", name.getText().toString());
     intent.putExtra("phone", phoneNumber.getText().toString());
     PendingIntent pendingIntent = PendingIntent.getBroadcast(
                                getApplicationContext(), (int) System.currentTimeMillis(), intent, 0);
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
                                + (selected * 60000), pendingIntent);

min SDK 版本是21

编辑:我尝试使用setAndAllowWhileIdle,但仍然无法使用。

有什么建议吗?

【问题讨论】:

  • 为什么不使用 WorkManager?
  • @IgorBykov 我不知道工作经理是如何或做什么的。

标签: android alarmmanager


【解决方案1】:

使用 androidx WorkManager 库代替所有调度服务。

WorkManager API 是所有以前 Android 后台调度 API 的合适且推荐的替代品

https://developer.android.com/topic/libraries/architecture/workmanager

WorkManager 所做的是将所有现有的调度服务封装起来,根据可用的、API 级别等使用最合适的一种,甚至处理兼容性问题和系统错误强>。

一些教程:

https://medium.com/androiddevelopers/introducing-workmanager-2083bcfc4712

https://www.programmersought.com/article/82731596284/

https://medium.com/swlh/periodic-tasks-with-android-workmanager-c901dd9ba7bc

【讨论】:

  • 有没有 JAVA 中的 WorkManager 教程,因为我检查了链接,它是针对 Kotlin 的。
  • 我在最底部放了2个额外的教程,你会在网上找到很多。考虑到 Google 建议使用 WorkManager,因为直接使用任何现有的调度系统意味着您必须管理 API 更改、设备特定的错误、弃用等。使用 WorkManager,您不必再担心所有这些。跨度>
【解决方案2】:

在某些设备(尤其是低端和中国制造商)上,除非用户明确启用,否则不允许应用执行后台功能(如果应用未运行)。这是为了防止恶意应用通过执行后台活动来耗尽电池。

要解决此问题,您需要手动将您的应用添加到“受保护的应用”列表或“允许在后台运行”的应用列表中。要将您的应用添加到此列表中,您需要转到相应的设置。这在不同的设备上有所不同,但通常可以在“电源管理”或“安全”设置中找到。

在荣耀设备上,它位于“电池管理器->受保护的应用程序”中

小米设备见https://dontkillmyapp.com/xiaomi

【讨论】:

  • 同意。我也遇到过这种情况
【解决方案3】:

我每天都使用此功能对我的应用程序进行更改。

Manifest.xml

中添加了广播接收器
<receiver  android:name=".AlarmReceiver">
    <action android:name="alarm.running"/>
</receiver>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    AlarmManager alarmMgr;
    PendingIntent alarmIntent;
    Context context;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context=MainActivity.this;

        AlarmReceiver mScreenStateReceiver = new AlarmReceiver();
        IntentFilter screenStateFilter = new IntentFilter();
        screenStateFilter.addAction("alarm.running");
        registerReceiver(mScreenStateReceiver, screenStateFilter);

        alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmReceiver.class);
        intent.setAction("alarm.running");
        alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 36);

// setRepeating() lets you specify a precise custom interval--in this case,
// 1 day
        alarmMgr.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis()/1000,
                AlarmManager.INTERVAL_DAY, alarmIntent);
    }

}

AlarmReceiver.java // 一个广播接收器,用于显示示例的 toast

public class AlarmReceiver  extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getAction()){
            case "alarm.running":
                Toast.makeText(context, "alarm ran", Toast.LENGTH_SHORT).show();
        }
    }
}

【讨论】:

    【解决方案4】:

    使用setExactAndAllowWhileIdle() 方法代替set() 可以在特定时间精确触发动作。但是,请确保不要经常使用它,除非它是一项值得牺牲系统资源的任务。

    强烈建议应用程序不要不必要地使用精确警报,因为它们会降低操作系统最小化电池使用的能力。

    阅读更多AlarmManager  |  Android Developers - setExactAndAllowWhileIdle

    【讨论】:

      【解决方案5】:

      API 19 开始发送警报是不准确的:操作系统将切换警报以最大程度地减少唤醒和电池使用。因此,从上述 19 开始,您可以使用 here 官方文档中所述的 setWindow 方法。

      【讨论】:

      • 其实我最近才开始学习AlarmManager,所以对它了解不多。我搜索了一些示例,但没有找到。那么,你能用一个关于setWindow的例子来说明一下吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      • 1970-01-01
      相关资源
      最近更新 更多