AlarmManager在AlarmReceiver/BroadcastReceiver中从未调用onReceive方法

4

我还是无法使我的AlarmReceiver类中的onReceive方法触发。这个实现中有任何错误吗?

所有这些都应该做的就是等待一段时间(最好是6天),然后弹出一个通知。 (你能相信没有内置系统来实现这个功能吗?crontab 呢?)

MyActivity和BootReceiver在必要的条件下都设置了一个闹钟。AlarmService会发送通知。而AlarmReceiver应该捕获闹钟并启动AlarmService,但它从未捕获过那个广播,无论我做什么都不行。

哦,我一直在我的Droid X上测试,Android版本为2.3.4。 项目构建使用API 8。

P.S. 大多数内容都是改编自http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/

------------ MyActivity.java ------------

public class MyActivity extends Activity implements SensorEventListener {

    private void setupAlarm() {
        Log.i(TAG, "Setting up alarm...");
        AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, AlarmReceiver.class), 0);

        // Get alarm trigger time from prefs
        Log.i(TAG, "Getting alarm trigger time from prefs...");
        SharedPreferences mPrefs2 = PreferenceManager.getDefaultSharedPreferences(context);
        long trigger = SocUtil.getLongFromPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER);
        Log.i(TAG, "Trigger from prefs: " + trigger + " (" + new Date(trigger).toString() + ").");

        // If alarm trigger is not set
        if(trigger == new Long(-1).longValue()) {
            // Set it
            trigger = new Date().getTime() + NOTIFY_DELAY_MILLIS;
            SocUtil.saveLongToPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER, trigger);
            Log.i(TAG, "Trigger changed to: " + trigger + " (" + new Date(trigger).toString() + ").");

            // And schedule the alarm
            alarmMgr.set(AlarmManager.RTC, trigger, pendingIntent);
            Log.i(TAG, "Alarm scheduled.");
        }
        // If it is already set
        else {
            // Nothing to schedule. BootReceiver takes care of rescheduling it after a reboot
        }
    }

}

------------ AlarmService.java ------------

public class AlarmService extends IntentService {

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

   @Override
   public void onHandleIntent(Intent intent) {
      Log.i(AlarmConst.TAG, "AlarmService invoked.");
      this.sendNotification(this);
   }

   private void sendNotification(Context context) {
      Log.i(AlarmConst.TAG, "Sending notification...");
      Intent notificationIntent = new Intent(context, Splash.class);
      PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

      NotificationManager notificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
      Notification notification = new Notification(R.drawable.icon, "Test1", System.currentTimeMillis());
      notification.setLatestEventInfo(context, "Test2", "Test3", contentIntent);
      notificationMgr.notify(0, notification);
   }
}

------------ AlarmReceiver.java ------------

public class AlarmReceiver extends BroadcastReceiver {

   // onReceive must be very quick and not block, so it just fires up a Service
   @Override
   public void onReceive(Context context, Intent intent) {
      Log.i(AlarmConst.TAG, "AlarmReceiver invoked, starting AlarmService in background.");
      context.startService(new Intent(context, AlarmService.class));
   }
}

------------ BootReceiver.java ------------ (为了恢复被清除的闹钟,因为我使用操作系统安排的东西不重要到需要在重新启动后保留 -_-)

public class BootReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {
      Log.i(AlarmConst.TAG, "BootReceiver invoked, configuring AlarmManager...");


      Log.i(AlarmConst.TAG, "Setting up alarm...");
      AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
      PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, AlarmReceiver.class), 0);

      // Get alarm trigger time from prefs
      Log.i(AlarmConst.TAG, "Getting alarm trigger time from prefs...");
      SharedPreferences mPrefs2 = PreferenceManager.getDefaultSharedPreferences(context);
      long trigger = SocUtil.getLongFromPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER);
      Log.i(AlarmConst.TAG, "Trigger from prefs: " + trigger + " (" + new Date(trigger).toString() + ").");

      // If trigger exists in prefs
      if(trigger != new Long(-1).longValue()) {
          alarmMgr.set(AlarmManager.RTC, trigger, pendingIntent);
          Log.i(AlarmConst.TAG, "Alarm scheduled.");
      }
   }
}

------------ 清单文件 ------------

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <activity
        android:name=".MyActivity"
        android:label="@string/app_name" >
    </activity>

<receiver android:name="com.domain.app.BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<receiver android:name="com.domain.app.AlarmReceiver"></receiver>

    <service android:name="com.domain.app.AlarmService"></service>
3个回答

3

以下是我最近在MainActivity中使用的代码,用于每小时生成通知:

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent Notifyintent = new Intent(context, Notify.class);
PendingIntent Notifysender = PendingIntent.getBroadcast(this, 0, Notifyintent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 3600000, Notifysender);

然后在Notify.java文件中。
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class Notify extends BroadcastReceiver{

    @SuppressWarnings("deprecation")
    @Override
    public void onReceive(Context context, Intent intent) {
          NotificationManager myNotificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
          Notification notification = new Notification(R.drawable.ic_launcher, "Update Device", 0);
          Intent notificationIntent = new Intent(context, MainActivity.class);
          PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
          notification.setLatestEventInfo(context, "Device CheckIn", "Please run Device CheckIn", contentIntent);
          notification.flags |= Notification.FLAG_HIGH_PRIORITY;
          myNotificationManager.notify(0, notification);
    }
}

最后,在AndroidManifest.xml文件中,我在<application>标签之间添加了以下内容:

<receiver android:name=".Notify" android:exported="true">
         <intent-filter>
                <action android:name="android.intent.action.NOTIFY" />
            </intent-filter>
</receiver>

我在办公室已经有一个主要的代码,我知道它是可行的,如果需要更多帮助,请随时给我发送电子邮件,因为我曾面临同样的问题。

电子邮件:sbrichards@mit.edu


对我不起作用,刚刚尝试了你的代码。https://dev59.com/YWUo5IYBdhLWcg3wpg0f - Siddharth

0

您必须使用意图操作将AlarmReceiver注册,如下所示。并且操作字符串必须与您通过sendBroadcast()方法广播的操作相同。

例如:sendBroadcast(new Intent(""com.intent.action.SOMEACTION.XYZ""));

    <receiver android:name="com.domain.app.AlarmReceiver">

<intent-filter>
                <action android:name="com.intent.action.SOMEACTION.XYZ" />
            </intent-filter>
</receiver>

谢谢,但我不明白sendBroadcast应该在哪里使用。我理解AlarmManager会负责实际发送广播,而我的alarmreceiver会接收它。显然,我需要修复我的清单,为我的AlarmReceiver添加一个意图过滤器,但我不知道要放什么操作,因为我不知道广播实际上发送的是什么操作。 - mmseng

-3

我通过根本不使用 BroadcastReceiver 解决了这个问题。我阅读了很多有关如何进行通知提醒的教程和文章,它们都说要使用 BroadcastReceiver,但显然我没有理解到位,或者那是一堆废话。

现在,我只需让 AlarmManager 设置一个闹钟并带有一个直接指向我创建的新 ActivityIntent 即可。我仍然使用 BootReceiver 在重启后重置该闹钟。

这使得通知可以在应用内、应用外、应用进程关闭以及重启后工作。

感谢其他评论者的时间。


4
如果你想在闹钟响起时使用AlarmManager.ELAPSED_REALTIME_WAKEUP或AlarmManager.RTC_WAKEUP来请求设备唤醒,则使用BroadcastReceiver非常重要。在onReceive期间,设备保证会保持唤醒状态,但是对于启动服务就没有这样的保证:设备可能会在服务实际启动之前进入睡眠状态。如果你感兴趣,可以查看thisthis这些问题。 - Darth Beleg
这个问题对我来说已经非常不相关了,但是我仍然在被踩(9年后),所以我“取消”了我的答案。当时它对我的目的起到了作用,但显然我不知道自己在做什么,并且没有得到指导我找到正确解决方案的答案。 - mmseng

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