[英]Android 8.0 - BroadcastReceiver not receiving after a reboot
I am developing an app. 我正在开发一个应用程序。 I am facing a problem.
我面临一个问题。 The thing is my code is as follows:
事情是我的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.a5corp.weather">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher_x"
android:label="@string/app_name"
android:fullBackupContent="@xml/backup_rules"
android:theme="@style/AppTheme.NoActionBar">
...
<service android:name=".service.NotificationService" />
<receiver
android:name=".receiver.StartupReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.UpgradeReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
...
</application>
</manifest>
StartupReceiver: StartupReceiver:
public class StartupReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
...
NotificationService.setNotificationServiceAlarm(context, new Prefs(context).getNotifs());
}
else
Log.i("No" , "Boot");
}
}
UpgradeReceiver: 升级接收器:
public class UpgradeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("In" , UpgradeReceiver.class.getSimpleName());
NotificationService.setNotificationServiceAlarm(context , new Prefs(context).getNotifs());
}
}
NotificationService: NotificationService:
public class NotificationService extends IntentService {
private static final String TAG = "NotificationsService";
Prefs prefs;
Notification.Builder builder;
public NotificationService() {
super(TAG);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
CheckConnection checkNetwork = new CheckConnection(this);
if (!checkNetwork.isNetworkAvailable()) {
return;
}
...
try {
WeatherInfo weather;
weather = new Request(this).getItems(city, units);
weatherNotification(weather);
} catch (IOException e) {
Log.e(TAG, "Error get weather", e);
}
}
public static Intent newIntent(Context context) {
Log.i("Trigger" , "newIntent");
return new Intent(context, NotificationService.class);
}
public static void setNotificationServiceAlarm(Context context,
boolean isNotificationEnable) {
Log.i("In" , "Notification Service Alarm");
Intent intent = NotificationService.newIntent(context);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
long intervalMillis = AlarmManager.INTERVAL_HOUR;
if (alarmManager != null)
if (isNotificationEnable) {
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(),
intervalMillis,
pendingIntent);
} else {
alarmManager.cancel(pendingIntent);
pendingIntent.cancel();
}
}
private void weatherNotification(WeatherInfo weather) {
Intent intent = new Intent(this, WeatherActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
...
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert notificationManager != null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String id = "w01", name = getString(R.string.weather_notification_title);
int importance = NotificationManager.IMPORTANCE_MIN;
String desc = getString(R.string.weather_notification_description);
NotificationChannel channel = new NotificationChannel(id, name, importance);
channel.setDescription(desc);
notificationManager.createNotificationChannel(channel);
builder = new Notification.Builder(this , id);
}
else
builder = new Notification.Builder(this);
...
Notification notification = builder.build();
notificationManager.notify(0 , notification);
}
}
The problem is that NotificationService as such works on its own, but this does not get called when the app is upgraded or the phone is rebooted. 问题在于,NotificationService本身可以工作,但是在升级应用程序或重新启动手机后,NotificationService不会被调用。 The fact is this is happening on Android O. As far as I remember, this used to work on Android 7.1 before I upgraded to Android 8.
事实上,这是在Android O上发生的。据我所记得,在我升级到Android 8之前,它曾经在Android 7.1上运行。
EDIT 1: After trying JobIntentService, here is how my code looks now: 编辑1:在尝试JobIntentService之后,这是我的代码现在的样子:
UPdated Manifest: 更新的清单:
...
<service android:name=".service.ReactivationService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
...
Reactivation Service: 重新激活服务:
public class ReactivationService extends JobIntentService {
public static final int JOB_ID = 0x01;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, ReactivationService.class, JOB_ID, work);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
Log.i("In" , "onHandleWork()");
....
NotificationService.setNotificationServiceAlarm(this, new Prefs(this).getNotifs());
}
}
Startup Receiver: 启动接收器:
public class StartupReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Log.i("In" , "getAction()");
ReactivationService.enqueueWork(context, intent);
}
else
Log.i("No" , "Boot");
}
}
Upgrade Receiver: 升级接收器:
public class UpgradeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_MY_PACKAGE_REPLACED)) {
Log.i("In" , "getAction()");
ReactivationService.enqueueWork(context, intent);
}
else
Log.i("No" , "Upgrade");
}
}
Now my problem is, the ACTION_MY_PACKAGE_REPLACED works fine and shows up the notification, but ACTION_BOOT_COMPLETED is not showing up the notification. 现在我的问题是,ACTION_MY_PACKAGE_REPLACED可以正常工作并显示通知,但是ACTION_BOOT_COMPLETED没有显示通知。 What could be the reason, as I am using the same Service for both the receivers.
原因可能是因为我在两个接收器上都使用了相同的服务。
Starting from Android O, you can not start a service from a background app without getting an exception: 从Android O开始,您不能在没有异常的情况下从后台应用程序启动服务:
java.lang.IllegalStateException: Not allowed to start service Intent (my_service) : app is in background
java.lang.IllegalStateException:不允许启动服务意图(my_service):应用程序在后台
If you still need to launch a service at device start up, you can now use the new JobIntentService . 如果仍然需要在设备启动时启动服务,则现在可以使用新的JobIntentService 。
Change your IntentService
to a JobIntentService
: 将您的
IntentService
更改为JobIntentService
:
public class ReactivationService extends JobIntentService {
public static final int JOB_ID = 0x01;
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, ReactivationService.class, JOB_ID, work);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
// do your stuff here
}
}
Use it as follow in your StartupReceiver
: 在
StartupReceiver
按以下方式使用它:
public class StartupReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
ReactivationService.enqueueWork(context, new Intent());
}
}
}
Declare your service inside the manifest: 在清单中声明您的服务:
<service android:name=".ReactivationService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
And that's it. 就是这样。 This will either directly start the service (when running on pre-O platforms) or enqueue work for it as a job (when running on O and later).
这将直接启动服务(在O之前的平台上运行时)或将其排队作为工作(在O或更高版本上运行时)。 No matter what the platform is, everything you pass in
enqueueWork
will ultimately appears in onHandleWork
. 无论平台是什么,您在
enqueueWork
传递的enqueueWork
内容最终都会出现在onHandleWork
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.