Implementation method and precautions of Android starting foreground service

Problem Description

The Android R platform radio starts the foreground service startForegroundService() and reports an error

E AndroidRuntime: android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{
    
    990dd99 u0 com.android.fmradio/.FmService}

problem analysis

In Android O, there is a new background restriction. When trying to start startService(), you will get IlleagalStateException, so startForegroundService() should be used now, but if you start the service via this new method, you will see a similar error in the screenshot. To avoid this exception, you need to have 5 seconds after startForegroundService() to create startForeground() to notify the user that you are working in the background. Otherwise it will crash with such a crash message.

Instructions

  1. permissions

To start the foreground service, you need to add the following permissions:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

This is a new permission introduced since Android 9.0 (API level 28) to ensure that applications do not create foreground services without the user's permission. If your application does not declare this permission and attempts to start a foreground service, a SecurityException may be thrown.

It should be noted that since Android O (API level 26), it is not enough to declare the permission in AndroidManifest.xml, and the permission must be requested in the code. Permissions can be checked and requested as follows:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.FOREGROUND_SERVICE)
        != PackageManager.PERMISSION_GRANTED) {
    
    
    // Permission not yet granted, request it
    ActivityCompat.requestPermissions(this,
            new String[]{
    
    Manifest.permission.FOREGROUND_SERVICE},
            MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE);
}
  1. start service

In Android 8.0 and above, in order to comply with the background restriction policy, the application must use the startForegroundService() method to start the foreground service instead of startService().

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    
    
    context.startForegroundService(intent);
} else {
    
    
    context.startService(intent);
}
  1. Notification in service service

In API 26 and above, you first need to create a NotificationChannel object and set some properties (such as sound, vibration, etc.) for it. Then use the Channel to create a Notification, and call the startForeground() method to assign it to the foreground service. This way, the service remains active even when the device is in Doze policy mode. In versions below API 26, the service can be started normally by directly calling the startService() method.

It is worth noting that in order to satisfy the requirements of the foreground service, the notification must be contained in the Notification object. Notifications provide information about the current state of the service and active instances so that users can view and monitor the health of the service at any time.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    
    
   // 创建一个 NotificationChannel  
   NotificationChannel channel = new NotificationChannel(channelId,channelName, NotificationManager.IMPORTANCE_DEFAULT); 
   // 自定义设置通知声音、震动等
   channel.enableVibration(true); 
   channel.setVibrationPattern(new long[]{
    
    100, 200}); 
   NotificationManager notificationManager = getSystemService(NotificationManager.class); 
   notificationManager.createNotificationChannel(channel);
   // 构建一个 Notification 
   Notification notification = new NotificationCompat.Builder(this, channelId) 
       .setContentTitle("Some Service") 
       .setContentText("服务正在运行...") 
       .setSmallIcon(R.drawable.ic_notification) 
       .build(); 
    // 启动前台服务 
    // 通知栏标识符 前台进程对象唯一SERVICE_ID
    startForeground(SERVICE_ID, notification);
} else {
    
    
    startService(intent); // API < 26 直接启动服务即可
}

Precautions

The things to do to start a foreground service are:

(1) Call ContextCompat.startForegroundService() to create a foreground service, which is equivalent to creating a background service and pushing it to the foreground;

(2) Create a user-visible Notification;

(3) The service method must be called within 5 seconds startForeground(int id, Notification notification) , otherwise the service will be stopped and android.app.RemoteServiceException:Context.startForegroundService() did not then call Service.startForeground()an exception will be thrown.

  • If startForeground() is not called within 5 seconds, timeout will trigger and ANR will be reported
  • Once the foreground service is started through startForegroundService(), there must be startForeground() in the service, otherwise ANR or crash will occur
  • The id and notification in startForeground() cannot be 0 and null

Related expansion

category the difference application
Reception The Notification of ONGOING will be displayed in the notification column. When the service is terminated, the Notification in the notification column will also disappear, which has a certain notification effect for users. Common such as music playback services
Background Services The default service is a background service, that is, the Notification of ONGOING will not be displayed in the notification column. When the service is terminated, the user cannot see the effect. Some services that do not need to run or terminate prompts, such as weather update, date synchronization, mail synchronization, etc.

startForegroundService()and startService()are two methods used to start a service in Android, the main differences between them are:

  1. API level: startForegroundService()The method was introduced in Android O (API level 26), and startService()the method is based on an earlier version of the API.

  2. Background restriction strategy: In order to avoid abuse of system and user resources, Android 8.0 (API level 26) and above have added some restriction strategies for background services. Under these restriction policies, applications must use startForegroundService()the method to start a foreground service and cannot startService().

  3. Foreground Notification: startForegroundService()method needs to startForeground()be used in conjunction with the method to create a foreground notification in the status bar. Foreground notifications let users know exactly what an app is doing and prevent the system from killing their process or service or putting it in Doze mode. does startService()not create a foreground notification, so the system may kill its process or service more easily.

Therefore, if you plan to start a long-running service or want to keep the service running even when the device goes to sleep, consider using the startForegroundService()and startForeground()methods. Use startService()the method if you are only starting a short-lived service and do not need the service to keep running when the device goes to sleep.

Note that even if you use startForegroundService()the method, the system will terminate its process or service if necessary. Therefore, when designing an application, it should be considered to design the service to consume as little system resources as possible, and release unnecessary resources in time to avoid problems such as excessive resource occupation.

Guess you like

Origin blog.csdn.net/weixin_44008788/article/details/122260752