Can not create Alarm Manager

2019-09-07 04:24发布

Sorry for my bad English. I faced with the problem. I try to create persistent alarm notification. Alarm notification must start every 10 seconds. I am using Alarm Manager,but it doest't work. What i am doing wrong?

public class RemindReceiver extends BroadcastReceiver {

private Class<?> activityClass;

public RemindReceiver() {

}

public RemindReceiver(Class<?> activityClass) {

    this.activityClass = activityClass;
}

@Override
public void onReceive(Context context, Intent intent) {

    NotificationManager notifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    Notification notification = new Notification(R.mipmap.ic_launcher, "Some Text", System.currentTimeMillis());

    Intent intentTL = new Intent(context, activityClass);
    notification.setLatestEventInfo(context, "Title", "Some Text",
            PendingIntent.getActivity(context, 0, intentTL, PendingIntent.FLAG_CANCEL_CURRENT));
    notification.flags = Notification.DEFAULT_LIGHTS | Notification.FLAG_AUTO_CANCEL;
    notifyManager.notify(1, notification);

    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis(), 1000 * 5, pendingIntent);
}

public void setRemind(Context context) {

    AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, RemindReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, System.currentTimeMillis(), 1000 * 5 , pendingIntent);
}}

Fragment:

public class PersonListFragment extends Fragment {

private RemindReceiver remindReceiver;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.person_list_fragment_layout, container, false);

    Button nextButton = (Button) rootView.findViewById(R.id.next_button);
    ListView personListView = (ListView) rootView.findViewById(R.id.name_list_view);
    List<Person> personList = PersonListGenerator.generate();

    PersonListAdapter adapter = new PersonListAdapter(getActivity(), personList);
    personListView.setAdapter(adapter);

    Context context = getActivity().getApplicationContext();
    remindReceiver = new RemindReceiver(PersonListActivity.class);
    remindReceiver.setRemind(context);
    remindReceiver.onReceive(getActivity(), new Intent());

    nextButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Intent intent = new Intent(getActivity(), ExpandablePersonListActivity.class);
            startActivity(intent);
        }
    });

    return rootView;
}}

And piece of my Android Manifest:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<receiver android:name=".utility.RemindReceiver"
        android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
    </receiver>

2条回答
家丑人穷心不美
2楼-- · 2019-09-07 04:42

If you really want to wake up every 10 seconds, consider the note at setRepeating():

Note: for timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.

Apart from that, if you just test with 10 seconds, it is inaccurate by design as of API 19:

Note: as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.

Thus, the alarm will not be delivered within the 10 seconds, because it will be delayed.

For me, that meant sometimes waiting a minute or more for my alarm, which worked pre-API-19.

Thus, you can expect exact alarm wakeup behavior only if you do not use setRepeating.

(Apart from that, @Damian has the right direction with his answer that the times need to be matched): use either

alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    SystemClock.elapsedRealtime() + 1000 * 5, 
    1000 * 5, 
    pendingIntent);

or try the current system time:

alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
    System.currentTimeMillis() + 1000 * 5, 
    1000 * 5, 
    pendingIntent);

Please change your code to include the +1000 * 5. Else the alarm is scheduled at the moment of execution, and thus, passes.

查看更多
姐就是有狂的资本
3楼-- · 2019-09-07 04:49

Can you try SystemClock.elapsedRealtime() ?

e.g.:

    alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 1000 * 5, pendingIntent);

I vaguely remember AlarmManager.ELAPSED_REALTIME_WAKEUP needing SystemClock.elapsedRealtime() and not System.currentTimeMillis()

I can't however find where I read this before. I will update when I find it.

edit:

According to: AlarmManager.set(int type, long triggerAtMillis, PendingIntent operation) sdk docs..

Parameters

  • type: One of ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC, or RTC_WAKEUP. triggerAtMillis time in milliseconds that the alarm should go off, using the
  • appropriate: clock (depending on the alarm type).
  • operation: Action to perform when the alarm goes off; typically comes from IntentSender.getBroadcast().
查看更多
登录 后发表回答