目录

Android 前台服务和通知相关排查

  • content {:toc}

前台服务和通知相关排查

  • FloatWindowService.java 应用打开后,创建悬浮球依赖的前台服务,同时会在通知栏创建前台服务通知。
/**
* 没有开始录制则会开启foreground通知栏
*/
private void startForegroundServiceAndNotification() {
if (!Prefs.getIsRecordStart(getApplicationContext())) {
StartRecordNotifications notifications = new StartRecordNotifications(getApplicationContext());
if (Build.MANUFACTURER.equals("OPPO") || Build.BRAND.equalsIgnoreCase("Xiaomi")) {
//判断是否是oppo手机
//判断是否是小米手机
startForeground(StartRecordNotifications.NOTIFICATION_ID, notifications.getXiaoMiNotification());
} else {
startForeground(StartRecordNotifications.NOTIFICATION_ID, notifications.getNormalNotification());
}
}
}

因为是target 28,所有Manifest里配置了权限前台服务权限

  • StartRecorderService.java 该服务是录制时打开的后台服务,在Android P以下没有独立打开通知,不属于前台服务。
@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
if (intent != null) {
if (intent.getBooleanExtra(VIDEO_EXIT_APP, false)) {
//退出录制
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();//关闭所有通知
}
...
//关闭所有APP打开的任务
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
if (activityManager != null) {
List appTasks = activityManager.getAppTasks();
for (int i = 0; i < appTasks.size(); i++) {
appTasks.get(i).finishAndRemoveTask();
}
}
//关闭自身服务
stopSelf();
return START_NOT_STICKY;
}
  • StartRecordNotifications.java 录制通知栏专属类 创建该类的时候就一并创建通知渠道id和渠道名称
public StartRecordNotifications(Context context) {
this.context = context;
createNotificationChannel();
}

创建渠道id和名称

public static final String RECORD_CHANNEL_ID = "record_channel_id";
public static final String RECORD_CHANNEL = "record channel";
public static final String RECORD_NOTIFICATION_DESCRIPTION = "record notification";
private void createNotificationChannel() {
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(RECORD_CHANNEL_ID, RECORD_CHANNEL, importance);
channel.setDescription(RECORD_NOTIFICATION_DESCRIPTION);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
mNotificationManager.createNotificationChannel(channel);
}
mBuilder = new NotificationCompat.Builder(context.getApplicationContext(), RECORD_CHANNEL_ID);
//创建通知:
mBuilder.setOngoing(true)//设置是否常驻,true为常驻
.setContentTitle(context.getString(R.string.string_notification_start_recording))
// .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setSmallIcon(R.mipmap.ic_launcher_white)//设置小图标
.setCategory(NotificationCompat.CATEGORY_EVENT)
.setPriority(Notification.PRIORITY_LOW)//设置优先级
.setWhen(System.currentTimeMillis());//设置展示时间
}

Target 29(Android 10 )前台服务的升级

依然需要前台服务权限声明

开启前台服务时需要添加参数foregroundServiceType使用如下方法 startForeground(int id,Notification notification,int foregroundServiceType) VRecorder使用案例:在FloatWindowService.java和StartRecorderService.java里都需要调用

public static void startForegroundServiceAndNotification(Service service) {
...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {//Android 10
service.startForeground(StartRecordNotificationUtils.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION);
} else {//非Android10
service.startForeground(StartRecordNotificationUtils.NOTIFICATION_ID, notification);
}
}
}

FloatWindowService.java里退出APP时:

@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
if (intent == null) return START_REDELIVER_INTENT;
if (intent.getBooleanExtra(VIDEO_EXIT_APP, false)) {//退出录制
Prefs.setIsRecordStart(getApplicationContext(), false);
MyWindowManager.releaseFloatViews(this);
finishAllTaskAndActivity();//关闭所有activity task
stopRecorderServices();//关闭录制服务
stopForeground(true);//设置true,移除通知
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (manager != null) {
manager.cancelAll();
}
stopSelf();
return START_NOT_STICKY;
}
/**
*关闭录制服务
*/
private void stopRecorderServices() {
Intent name = new Intent(this, StartRecorderService.class);
name.putExtra(VIDEO_EXIT_APP, true);
stopService(name);
}