【问题标题】:Using a service to start an ongoing notification that can take an action使用服务启动可以采取行动的持续通知
【发布时间】:2016-11-12 00:13:30
【问题描述】:

我创建了一个服务,以便我可以有一个持久的通知。我希望此通知有一个选项,可以将意图发送到我的另一个活动。

该选项本质上会在应用程序生成的每个进程中停止。因此,一旦按下操作,通知也需要关闭。

我正在尝试使用待处理的广播意图来完成此操作,但由于某种原因,广播接收器没有捕捉到该意图。我在服务的 onCreate() 方法中动态注册接收器,并在服务的 onDestroy() 方法中取消注册。

public class myService extends IntentService {
    private boolean shown = false;
    private ButtonReceiver buttonReceiver;

    //Side note: this is legacy code. Necessary?
    public myService() {
        super("myService");
    }

    @Override
    public void onCreate() {
        super.onCreate();

        IntentFilter filter = new IntentFilter("com.myapp.KILL_NOTIFICATION");
        this.buttonReceiver = new ButtonReceiver();
        this.registerReceiver(this.buttonReceiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(this.buttonReceiver);
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        if(intent.getAction() == "com.myapp.START_SERVICE") {
            //generate a unique id for the notification
            int id = Integer.parseInt(new SimpleDateFormat("ddHHmmss", Locale.US).format(new Date()));

            //create a pending intent to send off when the kill action is pressed
            Intent buttonIntent = new Intent("com.myapp.KILL_NOTIFICATION");
            buttonIntent.putExtra("notificationId", id);
            PendingIntent btPendingIntent = PendingIntent.getBroadcast(this, 0, buttonIntent, 0);

            Notification.Builder builder = new Notification.Builder(getApplicationContext());
            builder.setAutoCancel(false);
            builder.setContentTitle("my app");
            //builder.setContentText("Press this notification to kill.");
            builder.setOngoing(true);
            builder.setSmallIcon(R.drawable.ic_launcher);
            //builder.setContentIntent(pendingIntent);
            builder.addAction(R.drawable.ic_clear_black_24dp, "Kill my app", btPendingIntent);
            builder.setWhen(0);
            builder.setPriority(Notification.PRIORITY_MAX);

            Notification notification = builder.build();
            NotificationManager notificationManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            //TODO need to find first unused notif id
            notificationManager.notify(id, notification);
        }
    }

    public class ButtonReceiver extends BroadcastReceiver {

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

            int notificationId = intent.getIntExtra("notificationId", 0);

            Intent killIntent = new Intent("com.myapp.KILL_EVERYTHING");
            killIntent.addCategory(Intent.CATEGORY_DEFAULT);
            startActivity(killIntent);

            //cancel notification
            NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.cancel(notificationId);
        }
    }
}

【问题讨论】:

    标签: android android-intent android-broadcastreceiver


    【解决方案1】:

    IntentService 会在 onHandleIntent() 方法完成后自行停止,因此当它发生时,您的动态注册的接收器不再用于获取广播。

    您不需要Service 来维持持续的Notification。在您的情况下,您可以直接发出Notification,而不是启动Service 来执行此操作。然后在清单中静态注册您的 Receiver 类,并使用显式 IntentNotification 向其广播。

    ButtonReceiver 移动到它自己的类文件中,并像这样在清单中注册它:

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

    您需要在传递给onReceive()context 参数上调用startActivity(),就像您是getSystemService() 一样。您还需要将以下标志添加到 Intent

    killIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    

    然后只需将buttonIntentNotificationPendingIntent 更改为:

    Intent buttonIntent = new Intent(this, ButtonReceiver.class);
    

    如果这是 ButtonReceiver 将处理的唯一广播,那么您将不再需要 KILL_NOTIFICATION 操作。

    【讨论】:

    • 我想使用服务的原因是因为我的“主要”活动不是持久的。它实际上只是作为其他几个模块和应用程序的控制流存在,使用意图来做出决策。一旦该控制流完成(远少于一秒),应用程序就会完成,这样它就不会留在后台。正在进行的通知需要向这个主要活动发送一个意图,以便它知道关闭所有内容。如果由主要活动启动,通知是否仍然存在?
    • 是的。可以这样想:您当前正在从一个非持久性组件发出Notification - 因为IntentServiceonHandleIntent() 完成后立即完成 - 而Notification 仍然存在,是吗?我自己使用一个个人应用程序,它从引导接收器发出一个持续的Notification,甚至没有启动一个ActivityService。持续的Notification 直到您的应用程序以编程方式将其删除,或者您的应用程序以某种方式被强制停止,才会真正去任何地方。
    • 太棒了。这一切听起来都是正确的。只要我有机会实施和测试它,我就会接受你的回答。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多