android - 应用程序被杀死后发布通知
问题描述
大约一周以来,我一直在尝试为我的日历日计划应用程序发出通知。只要应用程序在最近的任务中,通知就可以正常工作,但删除后它根本不起作用。
最初我尝试使用调用 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);
解决方案
在 Android Oreo 中,后台执行限制已更改,因此如果您在 >= Api 26 上进行测试,这就是您可能会遇到此行为的原因。我会先检查一下。
除了后台执行限制之外,您似乎正在启动一项服务以发送Notification
using AlarmManager
.
为什么不安排AlarmManager
启动此服务并Notification
使用服务中的NotificationManager
通过NotificationManager#notify (int id, Notification notification)发布?
此外,由于这是一个已启动的服务,您可能会或可能不会在启动该服务的同一 Fragment 或 Activity 中调用 stopService。
根据文档stopSelf()
,您应该为已启动的服务执行此操作,或者在服务完成工作时调用服务。我希望这可以对您的问题有所了解。
祝你好运,编码愉快!
推荐阅读
- android - 通过 mtp 连接安卓手机
- android - Android Auto - 如何显式打开谷歌地图进行导航以显示在汽车屏幕上(intent.setPackege 不起作用)
- java - Java OOP:检查 X 或 Y 对象是否在 Array[i] 中,然后打印文本
- c++ - 带 * 的 C++ 布尔函数,你能帮帮我吗?我的代码有什么问题?
- powershell - 如何将 PowerShell 输出格式化为表格
- video - 未在 agora 会议中录制视频
- android-studio - IDE 致命错误 - 插件 Gradle 中的异常
- typescript - NestJS,尝试使用 ormconfig.ts,它破坏了一切
- postgresql - 如何为新的 GCP Cloud SQL PostgreSQL 用户授予 SELECT 权限?
- python-3.x - PySide2:QWidget 在装饰器中无法按预期工作