AlarmManager:关闭屏幕时删除未决意图
AlarmManager: Pending intent removed when turning screen off
在 docs 之后,我设法使用 AlarmManager 设置了一个警报,只要我不关闭 phone 的屏幕,它就可以很好地工作。
这是adb shell dumpsys alarm
亮屏时的输出:
Batch{1304da7 num=1 start=190708622 end=190708622 flgs=0x1}:
RTC_WAKEUP #0: Alarm{f642254 type 0 when 1480059825231 alarm.poc.app}
tag=*walarm*:alarm.poc.app.ACTION
type=0 whenElapsed=+5m49s424ms when=2016-11-25 02:43:45
window=0 repeatInterval=0 count=0 flags=0x1
operation=PendingIntent{f78d3a6: PendingIntentRecord{f52e1e7 alarm.poc.app broadcastIntent}}
在我关闭屏幕几秒钟后,我的警报从命令输出中消失并且永远不会被调用(它在屏幕打开时工作)。
所以我有这些问题:
- 还有哪些其他应用程序可以使警报保持活动状态? 我可以在
adb shell dumpsys alarm
的输出中看到即使我清除了所有最近的警报,也没有删除大量其他警报应用。我可以看到 Whatsapp、Google 和许多其他随机应用程序的警报。
- 也许所有这些应用程序都有前台服务?我问这个是因为我设法 "workaround" 创建一个讨厌的前台服务的问题,该服务每次都会向日志中写入一些内容5秒。看起来有一个 运行 服务可以防止这个问题,但它完全丑陋,我认为让处理器一直保持清醒不是一个好主意。
我是这样设置闹钟的:
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(AlarmReceiver.MY_ACTION);
intent.putExtra("text", editText.getText().toString());
PendingIntent pending = PendingIntent.getBroadcast(this, 42,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// also tried with getBroadcast(this, 0, intent, 0)
manager.setExact(AlarmManager.RTC_WAKEUP, millis, pending);
我有一个 WakefulBroadcastReceiver(屏幕关闭时未调用):
public void onReceive(Context context, Intent receivedIntent) {
if (MY_ACTION.equals(receivedIntent.getAction())) {
System.out.println("good!!!");
String text = receivedIntent.getStringExtra("text");
Intent intentService = new Intent(context, TestService.class);
intentService.putExtra("text", text);
startWakefulService(context, intentService);
System.out.println("service started");
}
}
和清单:
...
<uses-permission android:name="android.permission.WAKE_LOCK"/>
...
<service android:name="alarm.poc.app.TestService"
android:exported="false"/>
<receiver android:name="alarm.poc.app.AlarmReceiver"
android:process=":remote">
<intent-filter>
<action android:name="alarm.poc.app.ACTION"/>
</intent-filter>
</receiver>
...
我正在棉花糖 phone、minSdkVersion 19 和 targetSdkVersion 24
上进行测试
我找到了问题的答案。
问题是我正在华为 phone 上进行测试,它们具有 "Protected Apps" 功能,当屏幕关闭时,除配置为受保护的应用程序外,所有应用程序都会终止。
dumpsys 输出中有这么多其他应用程序的原因是华为默认已经提供了一些流行的应用程序 "protected"。
我找到的唯一解决方案是检测华为 phones 并要求用户保护应用程序。这个答案涵盖了这种方法:
您应该在收到警报时使用WakeLocker 来唤醒设备。使用此源代码创建一个名为 WakeLocker 的新 class:
package your.packagename;
import android.content.Context; import android.os.PowerManager;
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context ctx) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, MainActivity.APP_TAG);
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
}
并在您的接收器中调用 WakeLocker.acquire(context);
作为第一件事。额外:一旦你的闹钟完成它的事情,调用WakeLocker.release();
也会很好。
您还需要权限:<uses-permission android:name="android.permission.WAKE_LOCK" />
在 docs 之后,我设法使用 AlarmManager 设置了一个警报,只要我不关闭 phone 的屏幕,它就可以很好地工作。
这是adb shell dumpsys alarm
亮屏时的输出:
Batch{1304da7 num=1 start=190708622 end=190708622 flgs=0x1}:
RTC_WAKEUP #0: Alarm{f642254 type 0 when 1480059825231 alarm.poc.app}
tag=*walarm*:alarm.poc.app.ACTION
type=0 whenElapsed=+5m49s424ms when=2016-11-25 02:43:45
window=0 repeatInterval=0 count=0 flags=0x1
operation=PendingIntent{f78d3a6: PendingIntentRecord{f52e1e7 alarm.poc.app broadcastIntent}}
在我关闭屏幕几秒钟后,我的警报从命令输出中消失并且永远不会被调用(它在屏幕打开时工作)。
所以我有这些问题:
- 还有哪些其他应用程序可以使警报保持活动状态? 我可以在
adb shell dumpsys alarm
的输出中看到即使我清除了所有最近的警报,也没有删除大量其他警报应用。我可以看到 Whatsapp、Google 和许多其他随机应用程序的警报。 - 也许所有这些应用程序都有前台服务?我问这个是因为我设法 "workaround" 创建一个讨厌的前台服务的问题,该服务每次都会向日志中写入一些内容5秒。看起来有一个 运行 服务可以防止这个问题,但它完全丑陋,我认为让处理器一直保持清醒不是一个好主意。
我是这样设置闹钟的:
AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(AlarmReceiver.MY_ACTION);
intent.putExtra("text", editText.getText().toString());
PendingIntent pending = PendingIntent.getBroadcast(this, 42,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// also tried with getBroadcast(this, 0, intent, 0)
manager.setExact(AlarmManager.RTC_WAKEUP, millis, pending);
我有一个 WakefulBroadcastReceiver(屏幕关闭时未调用):
public void onReceive(Context context, Intent receivedIntent) {
if (MY_ACTION.equals(receivedIntent.getAction())) {
System.out.println("good!!!");
String text = receivedIntent.getStringExtra("text");
Intent intentService = new Intent(context, TestService.class);
intentService.putExtra("text", text);
startWakefulService(context, intentService);
System.out.println("service started");
}
}
和清单:
...
<uses-permission android:name="android.permission.WAKE_LOCK"/>
...
<service android:name="alarm.poc.app.TestService"
android:exported="false"/>
<receiver android:name="alarm.poc.app.AlarmReceiver"
android:process=":remote">
<intent-filter>
<action android:name="alarm.poc.app.ACTION"/>
</intent-filter>
</receiver>
...
我正在棉花糖 phone、minSdkVersion 19 和 targetSdkVersion 24
上进行测试我找到了问题的答案。
问题是我正在华为 phone 上进行测试,它们具有 "Protected Apps" 功能,当屏幕关闭时,除配置为受保护的应用程序外,所有应用程序都会终止。
dumpsys 输出中有这么多其他应用程序的原因是华为默认已经提供了一些流行的应用程序 "protected"。
我找到的唯一解决方案是检测华为 phones 并要求用户保护应用程序。这个答案涵盖了这种方法:
您应该在收到警报时使用WakeLocker 来唤醒设备。使用此源代码创建一个名为 WakeLocker 的新 class:
package your.packagename;
import android.content.Context; import android.os.PowerManager;
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context ctx) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, MainActivity.APP_TAG);
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
}
并在您的接收器中调用 WakeLocker.acquire(context);
作为第一件事。额外:一旦你的闹钟完成它的事情,调用WakeLocker.release();
也会很好。
您还需要权限:<uses-permission android:name="android.permission.WAKE_LOCK" />