【问题标题】:Android: AlarmManager used to call a Service to notify the userAndroid:AlarmManager用来调用一个Service来通知用户
【发布时间】:2013-01-22 04:51:57
【问题描述】:

编辑在我的清单中添加这一行解决了我的问题(Service 很好创建)。

<service android:name=".TimersService" >

发帖

我目前正在尝试实现警报以通知用户倒计时已完成。我有一个方法createAlarm() 通过AlarmManager 添加一个新警报。此方法当前在 Fragment 内部调用。它看起来像这样:

private final void createAlarm(String name, long milliInFuture) {

        Intent myIntent = new Intent(getActivity().getApplication(),
                TimersService.class);

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

        PendingIntent pendingIntent = PendingIntent.getService(getActivity()
                .getApplication(), 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);

        alarmManager.set(AlarmManager.RTC_WAKEUP,
                milliInFuture, pendingIntent); 

    }

我希望这种方法能够添加警报。即使设备处于睡眠模式,也应该调用警报。它应该在时间milliInFuture 被调用(这是System.currentTimeMillis()+ 某个时间)。当警报响起时,它应该启动一个服务。服务如下。这个Service 应该只做一件事:通知用户警报已经结束。我的Service类如下:

public class TimersService extends Service {

    private NotificationManager mNM;
    private int NOTIFICATION = 3456;


    public class LocalBinder extends Binder {
        TimersService getService() {
            return TimersService.this;
        }
    }

    @Override
    public void onCreate() {
        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        showNotification();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("LocalService", "Received start id " + startId + ": " + intent);
            return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mNM.cancel(NOTIFICATION);
        Toast.makeText(this, "Alarm", Toast.LENGTH_SHORT).show();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

        private final IBinder mBinder = new LocalBinder();

    private void showNotification() {

        final NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext());
        builder.setSmallIcon(R.drawable.clock_alarm);
        builder.setContentTitle("Time is up");
        builder.setContentText("SLIMS");
        builder.setVibrate(new long[] { 0, 200, 100, 200 });
        final Notification notification = builder.build(); 

        mNM.notify(NOTIFICATION, notification);
        NOTIFICATION += 1;
    }

}

当我运行我的代码时,我的方法 createAlarm 被调用。但是我的服务永远不会被创建。我根据 Alexander 的 Fragotsis 找到的 here 编写了这段代码。我的Service 类的灵感来自Service class 的Android 参考。

知道为什么我的Service 没有被调用吗?关于警报、服务或通知,我应该在我的Manifest 中写些什么吗?

感谢您的帮助

Ho 和我将不胜感激有关我的代码的任何建议。如果您知道在固定时间后通知用户的更简单方法,请告诉我!

【问题讨论】:

  • 如果您所做的只是发出通知,请考虑使用 BroadcastReceiver。
  • 另外,服务是否在清单中声明?如果您还没有这样做,请这样做。
  • 感谢您的快速回答!你对清单是正确的。但我还有一些问题。我希望我的服务在我的通知完成后完成。我应该在 onStartCommand() 中添加 stopSelf() 还是会出现问题?
  • 这应该不是问题,但可以考虑使用接收器。

标签: android android-service alarmmanager android-notifications


【解决方案1】:

由于您所做的只是通知您的用户一次,因此服务并不是解决此问题的最佳方法。服务旨在在后台工作。通知并不是真正适合服务的工作类型——它太短了。因此,我建议您改用 BroadcastReceiver。

类应该是这样的:

public class TimerReceiver extends BroadcastReceiver {
  private static final int NOTIFICATION = 3456; 

/*since you're always doing a 1-time notification, we can make this final and static, the number
 won't change. If you want it to change, consider using SharedPreferences or similar to keep track 
 of the number. You would have the same issue with a Service since you call stopself() and so,
 you would delete the object every time.*/

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

    final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
    builder.setSmallIcon(R.drawable.clock_alarm);
    builder.setContentTitle("Time is up");
    builder.setContentText("SLIMS");
    builder.setVibrate(new long[] { 0, 200, 100, 200 });
    final Notification notification = builder.build(); 

    mNM.notify(NOTIFICATION, notification);
  }

要调用接收者,您需要将 Intent 更改为指向新类,并且 getService() 需要为 getBroadcast()。所以这个

Intent myIntent = new Intent(getActivity().getApplication(),
                TimersService.class);


PendingIntent pendingIntent = PendingIntent.getService(getActivity()
                .getApplication(), 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);

需要

Intent myIntent = new Intent(getActivity().getApplication(),
                TimerReceiver.class);

PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity()
                .getApplication(), 0, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);

此外,您应该能够安全地将 getActivity().getApplication() 更改为 getActivity()

最后你需要一个清单声明:

<receiver android:name=".TimerReceiver" ></receiver>

【讨论】:

  • 感谢您的精彩解释!这很有帮助,但我还有一个问题。如果两个通知在时间上非常接近,会发生什么?如果它们具有相同的 ID(与现在一样),是第二个通知被取消还是第一个被删除?如果用户有时间删除第一个,我想这两个通知都会出现。
  • 相同的 id = 相同的通知。您可以将一个 int extra 传递给您用于接收者的意图,该意图指定您希望通知具有的 Id(如果您想区分)。
猜你喜欢
  • 2011-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
相关资源
最近更新 更多