AlarmManager 未重复 Intent
Intent not repeated by AlarmManager
这是我的 BootBroadcast
public class BootBroadcast extends BroadcastReceiver {
public static final String FILE_NAME = "BootBroadcast.java";
private static final long REPEAT_TIME_TO_CHECK_EXPENSES = 1000 * 60; //1 minute
@Override
public void onReceive(Context context, Intent intent) {
Log.v(FILE_NAME, "in onReceive");
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent service1 = new Intent(context, ISCheckExpenses.class);
Log.v(FILE_NAME, "starting service1");
context.startService(service1);
PendingIntent pending1 = PendingIntent.getBroadcast(context, 0, service1, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.SECOND, 600);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, pending1);
}
}
这是我的 ISCheckExpenses
public class ISCheckExpenses extends IntentService {
public static final String FILE_NAME = "ISCER";
private int recurringExpensesNotificationID = 001;
private int recurringExpensesMultiplier = 123;
public ISCheckExpenses(){
super(ISCheckExpenses.class.getName());
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
protected void onHandleIntent(Intent intent){
Log.d(FILE_NAME, "IntentService Started!");
//do some processing and send a notification to the user
String subject, content;
subject = getString(R.string.recurring_expenses_notification_due_subject);
content = getApplicationContext().getString(R.string.recurring_expenses_notification_due_content);
sendNotification(recurringExpensesNotificationID,1,subject,content);
}
private void sendNotification(int notificationID, int notificationType, String subject, String content){
Intent myIntent = new Intent(this, MainActivity.class);
int randomID = 1;
myIntent.putExtra("intentCaller","expensesRecurring");
randomID = recurringExpensesMultiplier * requestID;
//just to make sure the random ID is non-negative
if (randomID < 0){
randomID = randomID * -1;
}
myIntent.setAction(Intent.ACTION_VIEW);
myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pIntent = PendingIntent.getActivity(getBaseContext(), randomID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder n = new NotificationCompat.Builder(this)
.setContentTitle(subject)
.setContentText(content)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pIntent)
.setAutoCancel(true);
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
n.build().flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(notificationID, n.build());
}
}
这两个文件都已经在我的 AndroidManifest.xml
中了
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".ISCheckExpenses"
android:exported="false"
android:icon="@mipmap/ic_launcher"
android:enabled="true" />
<receiver android:name=".BootBroadcast" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
重启设备几秒钟后,将显示通知。然后我单击通知将其清除。我的应用应该会在 1 分钟后重新显示通知,对吗?但事实并非如此。我希望每 1 分钟在我的 logcat 中看到 "IntentService Started!".. 但什么也没出现? "IntentService Started!" 只显示一次。
我在这里错过了什么?谢谢
顺便说一下,我在 KitKat 和 Lollipop 上测试过这个。
问题是您正在尝试使用 PendingIntent
开始您的 Service
广播。您需要让闹钟向另一个 BroadcastReceiver
发送广播,因为您希望唤醒设备,然后让该接收器启动您的 Service
。您可能还需要与唤醒锁协调,以确保设备保持足够长的唤醒时间。
你得到第一个 "IntentService Started!" 因为你明确地从你的 BootReceiver 调用 startService()
,但是你的警报管理器设置为在 10 分钟后触发,而不是在第一次出现后 1 分钟后触发,因为你这样做:
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.SECOND, 600);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, pending1);
即您将 600
秒(10 分钟)添加到当前时间,并将其用于 AlarmManager 应该首次触发的时间。我不只是将添加的时间从 600 秒更改为 60 秒,而是更改 BroadcastReceiver
,这样我就不会调用 startService()
并设置第一次调用时间,而是将当前的AlarmManager.setInexactRepeating()
的 triggerAtMillis
时间以毫秒为单位,以便它立即触发,然后以 60 秒的间隔触发 - 即,将 onReceive()
方法更改为:
@Override
public void onReceive(Context context, Intent intent) {
Log.v(FILE_NAME, "in onReceive");
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent service1 = new Intent(context, ISCheckExpenses.class);
Log.v(FILE_NAME, "starting service1");
context.startService(service1);
PendingIntent pending1 = PendingIntent.getBroadcast(context, 0, service1, PendingIntent.FLAG_UPDATE_CURRENT);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, pending1);
}
您还应该记住,当您使用 setInexactRepeating()
时,警报可能会再延迟最多 60 秒,如文档中所述。
我的错误是我误解了 BroadcastReceiver 和 AlarmManager 应该工作。我不应该像上面那样在 onReceive 中执行 AlarmManager,我应该创建另一个函数来调用 new Intent 并将调用 activity 作为 Context 传递,将 BroadcastReceiver 作为 class.
我的 BroadcastReceiver 看起来是这样的:
public class BootBroadcast extends BroadcastReceiver {
//private static final long REPEAT_TIME_TO_CHECK_EXPENSES = 1000 * 30;
//private static final long REPEAT_TIME_TO_ANALYZE_LOCATION = 1000 * 30;
@Override
public void onReceive(Context context, Intent intent) {
int what = intent.getIntExtra("what",0);
if (what == 1) {
Intent intentService1 = new Intent(context, ISCheckRecurringItemsAndCC.class);
context.startService(intentService1);
}else if (what == 2) {
Intent service2 = new Intent(context, ISCheckLocationAndRating.class);
context.startService(service2);
}else{
//should only reach here when the device boots
Intent intentService1 = new Intent(context, ISCheckRecurringItemsAndCC.class);
context.startService(intentService1);
Intent service2 = new Intent(context, ISCheckLocationAndRating.class);
context.startService(service2);
}
}
public void setAlarm(Context context){
Log.v(FILE_NAME,"inside setAlarm");
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent myIntent = new Intent(context, BootBroadcast.class);
myIntent.putExtra("what", 1);
PendingIntent myPendingIntent = PendingIntent.getBroadcast(context, 111, myIntent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, myPendingIntent);
myIntent = new Intent(context, BootBroadcast.class);
myIntent.putExtra("what", 2);
myPendingIntent = PendingIntent.getBroadcast(context, 222, myIntent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), REPEAT_TIME_TO_ANALYZE_LOCATION, myPendingIntent);
}
}
上面的代码现在对我来说工作得很好。
这是我的 BootBroadcast
public class BootBroadcast extends BroadcastReceiver {
public static final String FILE_NAME = "BootBroadcast.java";
private static final long REPEAT_TIME_TO_CHECK_EXPENSES = 1000 * 60; //1 minute
@Override
public void onReceive(Context context, Intent intent) {
Log.v(FILE_NAME, "in onReceive");
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent service1 = new Intent(context, ISCheckExpenses.class);
Log.v(FILE_NAME, "starting service1");
context.startService(service1);
PendingIntent pending1 = PendingIntent.getBroadcast(context, 0, service1, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.SECOND, 600);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, pending1);
}
}
这是我的 ISCheckExpenses
public class ISCheckExpenses extends IntentService {
public static final String FILE_NAME = "ISCER";
private int recurringExpensesNotificationID = 001;
private int recurringExpensesMultiplier = 123;
public ISCheckExpenses(){
super(ISCheckExpenses.class.getName());
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
protected void onHandleIntent(Intent intent){
Log.d(FILE_NAME, "IntentService Started!");
//do some processing and send a notification to the user
String subject, content;
subject = getString(R.string.recurring_expenses_notification_due_subject);
content = getApplicationContext().getString(R.string.recurring_expenses_notification_due_content);
sendNotification(recurringExpensesNotificationID,1,subject,content);
}
private void sendNotification(int notificationID, int notificationType, String subject, String content){
Intent myIntent = new Intent(this, MainActivity.class);
int randomID = 1;
myIntent.putExtra("intentCaller","expensesRecurring");
randomID = recurringExpensesMultiplier * requestID;
//just to make sure the random ID is non-negative
if (randomID < 0){
randomID = randomID * -1;
}
myIntent.setAction(Intent.ACTION_VIEW);
myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pIntent = PendingIntent.getActivity(getBaseContext(), randomID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder n = new NotificationCompat.Builder(this)
.setContentTitle(subject)
.setContentText(content)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pIntent)
.setAutoCancel(true);
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
n.build().flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(notificationID, n.build());
}
}
这两个文件都已经在我的 AndroidManifest.xml
中了<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".ISCheckExpenses"
android:exported="false"
android:icon="@mipmap/ic_launcher"
android:enabled="true" />
<receiver android:name=".BootBroadcast" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
重启设备几秒钟后,将显示通知。然后我单击通知将其清除。我的应用应该会在 1 分钟后重新显示通知,对吗?但事实并非如此。我希望每 1 分钟在我的 logcat 中看到 "IntentService Started!".. 但什么也没出现? "IntentService Started!" 只显示一次。
我在这里错过了什么?谢谢
顺便说一下,我在 KitKat 和 Lollipop 上测试过这个。
问题是您正在尝试使用 PendingIntent
开始您的 Service
广播。您需要让闹钟向另一个 BroadcastReceiver
发送广播,因为您希望唤醒设备,然后让该接收器启动您的 Service
。您可能还需要与唤醒锁协调,以确保设备保持足够长的唤醒时间。
你得到第一个 "IntentService Started!" 因为你明确地从你的 BootReceiver 调用 startService()
,但是你的警报管理器设置为在 10 分钟后触发,而不是在第一次出现后 1 分钟后触发,因为你这样做:
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.SECOND, 600);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, pending1);
即您将 600
秒(10 分钟)添加到当前时间,并将其用于 AlarmManager 应该首次触发的时间。我不只是将添加的时间从 600 秒更改为 60 秒,而是更改 BroadcastReceiver
,这样我就不会调用 startService()
并设置第一次调用时间,而是将当前的AlarmManager.setInexactRepeating()
的 triggerAtMillis
时间以毫秒为单位,以便它立即触发,然后以 60 秒的间隔触发 - 即,将 onReceive()
方法更改为:
@Override
public void onReceive(Context context, Intent intent) {
Log.v(FILE_NAME, "in onReceive");
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent service1 = new Intent(context, ISCheckExpenses.class);
Log.v(FILE_NAME, "starting service1");
context.startService(service1);
PendingIntent pending1 = PendingIntent.getBroadcast(context, 0, service1, PendingIntent.FLAG_UPDATE_CURRENT);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, pending1);
}
您还应该记住,当您使用 setInexactRepeating()
时,警报可能会再延迟最多 60 秒,如文档中所述。
我的错误是我误解了 BroadcastReceiver 和 AlarmManager 应该工作。我不应该像上面那样在 onReceive 中执行 AlarmManager,我应该创建另一个函数来调用 new Intent 并将调用 activity 作为 Context 传递,将 BroadcastReceiver 作为 class.
我的 BroadcastReceiver 看起来是这样的:
public class BootBroadcast extends BroadcastReceiver {
//private static final long REPEAT_TIME_TO_CHECK_EXPENSES = 1000 * 30;
//private static final long REPEAT_TIME_TO_ANALYZE_LOCATION = 1000 * 30;
@Override
public void onReceive(Context context, Intent intent) {
int what = intent.getIntExtra("what",0);
if (what == 1) {
Intent intentService1 = new Intent(context, ISCheckRecurringItemsAndCC.class);
context.startService(intentService1);
}else if (what == 2) {
Intent service2 = new Intent(context, ISCheckLocationAndRating.class);
context.startService(service2);
}else{
//should only reach here when the device boots
Intent intentService1 = new Intent(context, ISCheckRecurringItemsAndCC.class);
context.startService(intentService1);
Intent service2 = new Intent(context, ISCheckLocationAndRating.class);
context.startService(service2);
}
}
public void setAlarm(Context context){
Log.v(FILE_NAME,"inside setAlarm");
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent myIntent = new Intent(context, BootBroadcast.class);
myIntent.putExtra("what", 1);
PendingIntent myPendingIntent = PendingIntent.getBroadcast(context, 111, myIntent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), REPEAT_TIME_TO_CHECK_EXPENSES, myPendingIntent);
myIntent = new Intent(context, BootBroadcast.class);
myIntent.putExtra("what", 2);
myPendingIntent = PendingIntent.getBroadcast(context, 222, myIntent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), REPEAT_TIME_TO_ANALYZE_LOCATION, myPendingIntent);
}
}
上面的代码现在对我来说工作得很好。