Android - AlarmManager 在应用程序关闭后不工作

Android - AlarmManager is not working after app is closed

我正在使用 AlarmManager 在特定时间调用函数。它在 Genymotion 模拟器中成功运行,但在 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 但它仍然不起作用。

有什么建议吗?

API 19 开始,警报传送不准确:OS 将转移警报以尽量减少唤醒和电池使用。因此,从 19 以上开始,您可以使用 here.

官方文档中所述的 setWindow 方法

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

The WorkManager API is a suitable and recommended replacement for all previous Android background scheduling APIs

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

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

Applications are strongly discouraged from using exact alarms unnecessarily as they reduce the OS's ability to minimize battery use.

阅读更多AlarmManager  |  Android Developers - setExactAndAllowWhileIdle

我每天都使用这个功能来更改我的应用程序。

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 // 一个广播接收器来显示示例

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();
        }
    }
}

在某些设备上(特别是 low-end 和中国制造商),除非用户明确启用,否则不允许应用执行后台功能(如果应用不是 运行ning)。这是为了防止流氓应用程序通过执行后台活动耗尽电池。

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

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

对于小米设备,请参见https://dontkillmyapp.com/xiaomi