Я пытаюсь создать службу, которая каждую минуту запрашивает местоположение устройства.
Мне нужно, чтобы это работало в фоновом режиме, даже когда приложение закрыто. Пока мне удалось заставить его работать на устройствах с ОС Android до Oreo, но теперь я тестирую службу на устройстве Android Oreo и не работает, когда я закрываю или помещаю приложение в фоновый режим.
В своем исследовании я обнаружил, что для устройств Oreo для этого должна использоваться служба переднего плана с текущим уведомлением, поэтому для начала я реализовал простую службу переднего плана, подобную приведенной ниже, которая показывает текущее уведомление, пока приложение запущено и работает. удаляется при остановке приложения.
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();
}
}
Я запускаю и останавливаю указанную выше службу, используя указанные ниже функции.
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));
}
Я тестирую вышеуказанный сервис, и по какой-то причине он прекращается примерно через 30 минут после запуска. Может ли кто-нибудь сказать мне, что я делаю что-то не так, или, возможно, помочь мне найти решение, которое может сработать для меня?
Примечание: я следил за этим руководство и также тестировал их приложение, но оно все еще не работает. Сервис убивается через какое-то время.
В основном моя цель - реализовать службу, которая может работать в фоновом режиме (даже когда приложение закрыто) и получать обновления местоположения каждую минуту.
Устройство будет подключено, и, согласно тому, что я прочитал в документации, если устройство заряжается, оно не должно переходить в режим дремоты. Кроме того, я постоянно слежу за ним, поэтому пользуюсь устройством. К сожалению, когда служба останавливается, logcat очищается автоматически, поэтому я не вижу никаких журналов.
«... logcat очищается автоматически ...» Сначала я решил бы эту проблему. logcat нужен, чтобы помочь вам понять, что произошло, а не уничтожать информацию, когда она вам больше всего нужна. Рассмотрите возможность настройки фильтров на панели logcat Android Studio, чтобы вы могли видеть все журналы.
Вы можете использовать диспетчер заданий firebase для фоновой службы.
Код: Добавьте эти зависимости:
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;
}
}
Создайте задание в действии, вы делаете это так же, как раньше для фоновых служб.
/**
* 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");
}
это также сработает на телефонах Android любого SDK в режиме ожидания?
Его убивают, только если вы не использую устройство в течение 30 минут? Возможно, Дремать мешает работе вашей службы и вызывает неожиданный сбой. Есть ли соответствующий логарифм с момента смерти приложения?