简体   繁体   English

Android 8.0-重启后无法接收BroadcastReceiver

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM