前言
最近有项目过程中,有做app的同事反馈,三方应用无法监听关机广播。特地研究了下关机广播为啥监听不到。
1.原因:发送关机广播的类是ShutdownThread.java,添加了flag:Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY,表示只有在代码中动态注册,并且是前台服务和应用才能收到,所以在AndroidManifest.xml注册无法收到关机广播,后台服务中动态注册也无法收到。
2.前台服务注册关机广播。
(1).启动前台服务:
public class BootCompleteReceiver extends BroadcastReceiver {
private static final String TAG = "BootCompleteReceiver";
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
// ComponentName powerService = new ComponentName("com.android.mytest", "com.android.mytest.PowerService");
// Intent mIntent = new Intent();
// mIntent.setComponent(powerService);
Intent powerServiceIntent = new Intent(context, PowerService.class);
context.startForegroundService(powerServiceIntent);
Log.d(TAG, "startForegroundService");
}
}
}
}
(2)、添加前台服务权限,配置相关属性:
权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
服务配置:
<service
android:name=".PowerService"
android:foregroundServiceType="mediaPlayback"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="com.gwm.car.PowerService"/>
</intent-filter>
</service>
(3).注册关机广播:
package com.android.mytest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class PowerService extends Service {
private static final String TAG = "PowerService";
public ShutdownBroadcastReceiver mShutdownBroadcastReceiver;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
mShutdownBroadcastReceiver = new ShutdownBroadcastReceiver();
}
private Notification getNotification() {
NotificationChannel channel = new NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.createNotificationChannel(channel);
}
return new Notification.Builder(this, "channel_id")
.setContentTitle("shutdown")
.setContentText("Listening for shutdown")
// .setAutoCancel(true)
.setSmallIcon(R.mipmap.ic_launcher_round)
.build();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
startForeground(1, getNotification());
registerBroadcast();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
unregisterBroadcast();
stopForeground(true);
stopSelf();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void registerBroadcast() {
Log.d(TAG, "registerBroadcast");
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction((Intent.ACTION_SHUTDOWN));
registerReceiver(mShutdownBroadcastReceiver,intentFilter);
}
public void unregisterBroadcast() {
if (mShutdownBroadcastReceiver != null) {
unregisterReceiver(mShutdownBroadcastReceiver);
}
}
}
(4).关机广播实现
package com.android.mytest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ShutdownBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "ShutdownBroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "zjy onReceive intent:"+intent);
}
}
(5).本地验证: