【问题标题】:Publishing notifications after app is killed应用程序被杀死后发布通知
【发布时间】:2018-08-13 23:37:12
【问题描述】:

大约一周以来,我一直在尝试为我的日历日计划应用程序发送通知。只要应用在最近的任务中,通知就可以正常工作,但删除后它根本就不起作用。

最初我尝试使用调用 BroadcastReciever 的简单 AlarmManager,但我知道它不提供此功能,所以我决定学习和使用 Service。

一开始我尝试了 IntentService,现在我尝试了 Service。我没有收到任何日志错误,所以我猜我对这个系统的理解存在根本问题,所以如果你能启发我,我将不胜感激。

这是我的班级整体处理通知:

package com.example.android.calendar.Helpers;

import android.app.AlarmManager;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import com.example.android.calendar.Model.Event;
import com.example.android.calendar.R;
import java.util.Calendar;
import java.util.HashMap;
import java.util.UUID;

public class NotificationService extends Service {

    private static Context mContext;
    private static final String NOTIFICATION_CHANNEL_ID = "notificationChannelId";
    private static final String NOTIFICATION_CHANNEL_NAME = "eventsNotificationChannel";

    public static final String EX_ID = "extraId";
    public static final String ACTION_START_SERVICE = "startService";
    public static final String ACTION_NOTIFY_ON_TIME = "notifyOnTime";

    private static HashMap<UUID, Notification> notifications = new HashMap<>();
    public static int mCounter = 0;

    public NotificationService(){
        super();
    }

    @Override
    public void onCreate(){
        super.onCreate();
        createNotificationChannel(this.getApplicationContext());
    }

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId){
        super.onStartCommand(intent, flags, startId);

        new Thread(new Runnable() {
            @Override
            public void run() {
                if(intent.getAction() == ACTION_NOTIFY_ON_TIME){
                    UUID id = (UUID) intent.getSerializableExtra(EX_ID);
                    Notification notification = notifications.get(id);
                    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                    notificationManager.notify(mCounter++, notification);
                }
                try{
                    Thread.sleep(1000);
                } catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }).start();

        return IntentService.START_REDELIVER_INTENT;
    }

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

    public void createNotificationChannel(Context context){
        mContext = context;
        NotificationManager mNM = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE);
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
        notificationChannel.enableVibration(true);
        notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 100});
        notificationChannel.enableLights(true);
        mNM.createNotificationChannel(notificationChannel);
    }

    public void createNotification(int minutesBefore, Event event){
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID).
                setSmallIcon(R.drawable.ic_launcher_foreground).setContentTitle(event.getLabel()).
                setContentText(event.getComment()).setAutoCancel(true);

        // If an event is edited, remove existing notification
        if(notifications.get(event.getId()) != null)
            notifications.remove(event.getId());

        Calendar mCalendar = Calendar.getInstance();
        notifications.put(event.getId(), mBuilder.build());
        mCalendar.setTime(event.getTime());
        mCalendar.set(Calendar.SECOND, 0);

        Intent intent = new Intent(mContext, NotificationService.class);
        intent.putExtra(EX_ID, event.getId());
        intent.setAction(ACTION_NOTIFY_ON_TIME);
        PendingIntent notificationIntent = PendingIntent.getService(mContext, (int)System.currentTimeMillis(),
                intent, PendingIntent.FLAG_CANCEL_CURRENT);
        long triggerInMills = mCalendar.getTimeInMillis() - Calendar.getInstance().getTimeInMillis();
        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        alarmManager.setExact(AlarmManager.RTC, System.currentTimeMillis() + triggerInMills, notificationIntent);
    }

    public void cancelNotification(Event event, PendingIntent notificationIntent){
        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(notificationIntent);
        notifications.remove(event.getId());
    }
}

很确定这无关紧要,但这里是我创建和启动服务的地方:

notificationService = new NotificationService();
Intent startServiceIntent = new Intent(getActivity(), NotificationService.class);
startServiceIntent.setAction(NotificationService.ACTION_START_SERVICE);
getActivity().startService(startServiceIntent);

【问题讨论】:

  • 查看一个信号。
  • 信号是什么意思?
  • 'One Signal' onesignal.com

标签: android android-service android-notifications


【解决方案1】:

在 Android Oreo 中,background execution limits have changed,因此如果您在 >= Api 26 上进行测试,那么您可能会遇到这种行为。我会先检查一下。

除了后台执行限制之外,您似乎正在启动一项服务以使用AlarmManager 发送Notification

为什么不直接安排AlarmManager 启动此服务并使用NotificationManager 通过NotificationManager#notify (int id, Notification notification) 从服务中发布Notification

此外,由于这是一个已启动的服务,您可能会或可能不会在启动该服务的同一 Fragment 或 Activity 中调用 stopService。

As per the documentation,您应该为已启动的服务执行此操作,或者在服务完成工作时调用服务中的stopSelf()。我希望这可以帮助您深入了解您的问题。

祝你好运,编码愉快!

【讨论】:

  • 感谢重播。为什么最好让 AlarmManager 启动服务,而不是在创建片段时启动服务?是因为在收到通知之前启动它是多余的还是存在更深层次的问题? (只是 geniually intrested,无论如何我都会改变它,因为它是多余的)。关于执行限制,它在设备设置中以什么方式表示?因为在通知设置中,所有应用的一切都开启了。
  • 好吧,似乎所有服务正在做的就是创建通知并使用 AlarmManager 安排它。这并不是服务的实际用例。您可以直接从片段中安排警报。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-23
  • 2020-10-23
  • 2021-09-21
  • 1970-01-01
  • 2018-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多