在我的应用程序中,我使用AlarmManager启动IntentService,该服务访问报价的内部数据库并随机选择一个,然后使用该报价触发通知。
它在我的Android 9,OnePlus6手机上运行正常。但是我从其他用户那里收到了很多crashlytics数据,说明:
Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.myapp.receiver.AlarmReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.myapp/.service.NotificationQuoteService }: app is in background uid UidRecord{e3c2e3d u0a203 TRNB idle procs:1 proclist:23491, seq(0,0,0)}
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3606)
at android.app.ActivityThread.access$1300(ActivityThread.java:237)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1796)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7045)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
我认为,这是由于Oreo的限制所致,每个后台任务都应通过前台通知来通知自己。 但是,显示前台通知以查询报价然后显示报价通知是不是很荒谬? 有很多应用程序在做类似的事情,它们查询内部数据并在通知中显示它,而在查询数据时不显示任何前台通知。
我该怎么做,有人可以指出我正确的方向吗?
添加了编辑代码:
AlarmManager在上午9点启动
private void prepareAlarmManager() {
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, AlarmReceiver.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
if (alarmManager != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent);
}
}
BroadcastReceiver处理AlarmManager
public class AlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 10;
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, NotificationQuoteService.class);
context.startService(serviceIntent);
}
}
IntentService查询内部SQLite数据库并触发通知
public class NotificationQuoteService extends IntentService {
private Context mContext;
private DatabaseHelper mDatabaseHelper;
public NotificationQuoteService() {
super("quote service");
}
@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
mDatabaseHelper = DatabaseHelper.getInstance(mContext);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
List<Quote> quoteList = mDatabaseHelper.getAllQuotes();
int size = quoteList.size();
int randomIndex = (int) (Math.random() * size);
Quote quote = quoteList.get(randomIndex);
NotificationHelper.showDefaultNotification(mContext, quote);
}
@Override
public void onDestroy() {
super.onDestroy();
L.e("hop", "service is destroyed");
}
}
答案 0 :(得分:0)
您无法在android 8或更高版本的后台启动服务。
context.startService(serviceIntent);
您可以以startForegroundService()的身份启动服务。
答案 1 :(得分:0)
在onReceive()启动服务中:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
在使用中,onCreate()会这样:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
startForeground(1, new Notification());
}