可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am using Service Class on the Android O OS.
I plan to use the Service in the background.
The Android recommendation states that startService should use startForegroundService.
If you use startForegroundService, the Service throws a Context.startForegroundService() did not then call Service.startForeground() error.
What's wrong with this?
回答1:
From Google's docs on Android 8.0 behavior changes:
The system allows apps to call Context.startForegroundService() even while the app is in the background. However, the app must call that service's startForeground() method within five seconds after the service is created.
Solution: Call startForeground in Oncreate() for the Service which you use Context.startForegroundService().
See also: Background Execution Limits for Android 8.0 (Oreo)
回答2:
I called ContextCompat.startForegroundService(this, intent) to start the service then
In service onCreate
@Override public void onCreate() { super.onCreate(); if (Build.VERSION.SDK_INT >= 26) { String CHANNEL_ID = "my_channel_01"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); } }
回答3:
https://developer.android.com/reference/android/content/Context.html#startForegroundService(android.content.Intent)
Similar to startService(Intent), but with an implicit promise that the Service will call startForeground(int, android.app.Notification) once it begins running. The service is given an amount of time comparable to the ANR interval to do this, otherwise the system will automatically stop the service and declare the app ANR.
Unlike the ordinary startService(Intent), this method can be used at any time, regardless of whether the app hosting the service is in a foreground state.
make sure you call the Service.startForeground(int, android.app.Notification) on the onCreate() so you ensure it will be called..if you have any condition that may prevent you from doing that, then you'd better off using the normal Context.startService(Intent) and call the Service.startForeground(int, android.app.Notification) yourself.
It seems that the Context.startForegroundService() adds a watchdog to make sure you called the Service.startForeground(int, android.app.Notification) before it was destroyed...
回答4:
Make sure that all code paths calls startForeground method , for example the code may generate an exception on the onCreate Method of your service that prevent the startForeground from being called
@Override public void onCreate() { try{ } catch(Exception e) { } finally{ startForeground(1, notificationbuilder.build()); } }
回答5:
You app will crash if you call Context.startForegroundService(...) and then call Context.stopService(...) before Service.startForeground(...) is called.
I have a clear repro at: https://github.com/paulpv/ForegroundServiceAPI26/blob/repro/app/src/main/java/com/github/paulpv/foregroundserviceapi26/MainService.kt#L28
I have opened a bug on this: https://issuetracker.google.com/issues/76112072
Several bugs on this have been opened and closed Won't Fix.
Hopefully mine with clear repro steps.
回答6:
I have researched on this for a couple of days and got the solution. Now in Android O you can set the background limitation as below
The service which is calling a service class
Intent serviceIntent = new Intent(SettingActivity.this,DetectedService.class); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){ SettingActivity.this.startForegroundService(serviceIntent); }else{ startService(serviceIntent); }
and the service class should be like
public class DetectedService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public void onCreate() { super.onCreate(); int NOTIFICATION_ID = (int) (System.currentTimeMillis()%10000); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForeground(NOTIFICATION_ID, new Notification.Builder(this).build()); } // Do whatever you want to do here } }
回答7:
I am facing same issue and after spending time found a solutons you can try below code. If your using Service then put this code in onCreate else your using Intent Service then put this code in onHandleIntent.
if (Build.VERSION.SDK_INT >= 26) { String CHANNEL_ID = "my_app"; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "MyApp", NotificationManager.IMPORTANCE_DEFAULT); ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("") .setContentText("").build(); startForeground(1, notification); }