问题
I'm trying to build up a service which requests the device location every minute. I need this to work in background even when the application is closed. So far I managed to make it work on devices which has a pre-Oreo android OS but now I'm testing the service on android Oreo device and is not working when I close or put the application in background. In my research I found that for Oreo devices a Foreground Service with an ongoing notification should be used to achieve this so to start with I've implemented a simple Foreground Service like the below which while started it shows an ongoing notification and when stopped the notification is removed.
public class MyForegroundService extends Service {
private static String TAG = MyForegroundService.class.getSimpleName();
private static final String CHANNEL_ID = "channel_01";
private static final int NOTIFICATION_ID = 12345678;
private NotificationManager mNotificationManager;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
public MyForegroundService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Android O requires a Notification Channel.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.app_name);
// Create the channel for the notification
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);
// Set the Notification Channel for the Notification Manager.
mNotificationManager.createNotificationChannel(mChannel);
}
startForeground(NOTIFICATION_ID, getNotification());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
stopForeground(true);
}
private Notification getNotification() {
// Get the application name from the Settings
String appName = PrefApp.getSettings(getApplicationContext()).getAppConfigs().getAppName();
String applicationKey = PrefApp.getSettings(getApplicationContext()).getAppConfigs().getAppKey();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setContentTitle(appName)
.setContentText("Services are running")
.setOngoing(true)
.setPriority(Notification.PRIORITY_HIGH)
.setSmallIcon(R.mipmap.ic_notification)
.setWhen(System.currentTimeMillis());
// Set the Channel ID for Android O.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(CHANNEL_ID); // Channel ID
}
return builder.build();
}
}
I am starting and stopping the above service using the below functions.
public void startMyForegroundService() {
Log.d(TAG, "Start Foreground Service");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(getApplicationContext(), MyForegroundService.class));
} else {
startService(new Intent(getApplicationContext(), MyForegroundService.class));
}
}
public void stopMyForegroundService() {
Log.d(TAG, "Stop Foreground Service");
stopService(new Intent(getApplicationContext(), MyForegroundService.class));
}
I'm testing the above service and for some reason the service gets killed after about 30 mins from when I start it. Can anyone tell me if I'm doing something wrong or possibly guide me for a solution which can work for me?
Note: I've followed this tutorial and tested their application as well and that it still not working. The service is being killed after some time.
Basically my goal is to implement a service which can run in the background (even when the application is closed) and get location updates every minutes.
回答1:
You can use firebase job dispatcher for background service.
Code: Add this dependencies:
implementation 'com.firebase:firebase-jobdispatcher:0.8.5'
public class MyJobService extends JobService
{
private static final String TAG = MyJobService.class.getSimpleName();
@Override
public boolean onStartJob(JobParameters job)
{
Log.e(TAG, "onStartJob: my job service class is called.");
// enter the task you want to perform.
return false;
}
@Override
public boolean onStopJob(JobParameters job)
{
return false;
}
}
Create a job in the activity, you do it the way you used to do for background services.
/**
* 2018 September 27 - Thursday - 06:36 PM
* create job method
*
* this method will create job
**/
private static Job createJob(FirebaseJobDispatcher dispatcher)
{
return dispatcher.newJobBuilder()
//persist the task across boots
.setLifetime(Lifetime.FOREVER)
//.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
//call this service when the criteria are met.
.setService(MyJobService.class)
//unique id of the task
.setTag("TAGOFTHEJOB")
//don't overwrite an existing job with the same tag
.setReplaceCurrent(false)
// We are mentioning that the job is periodic.
.setRecurring(true)
// Run every 30 min from now. You can modify it to your use.
.setTrigger(Trigger.executionWindow(1800, 1800))
// retry with exponential backoff
.setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
//.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
//Run this job only when the network is available.
.setConstraints(Constraint.ON_ANY_NETWORK)
.build();
}
/**
* 2018 September 27 - Thursday - 06:42 PM
* cancel job method
*
* this method will cancel the job USE THIS WHEN YOU DON'T WANT TO USE THE SERVICE ANYMORE.
**/
private void cancelJob(Context context)
{
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
//Cancel all the jobs for this package
dispatcher.cancelAll();
// Cancel the job for this tag
dispatcher.cancel("TAGOFTHEJOB");
}
来源:https://stackoverflow.com/questions/52722211/foregroundservice-on-android-oreo-gets-killed