Служба Android останавливается, когда приложение закрывается
Я запускаю службу из своей основной деятельности Android следующим образом:
final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);
Когда я закрываю страницу активности, удаляя ее из списка последних приложений, служба перестает работать и перезапускается через некоторое время. Я не могу использовать постоянные службы с уведомлениями из-за требований моего приложения. Как сделать так, чтобы служба НЕ перезагружалась или не отключалась и просто продолжала работать при выходе из приложения?
13 ответов
Я нахожусь в той же ситуации, до сих пор я узнал, что когда приложение закрывается, служба закрывается еще и потому, что они находятся в одном потоке, поэтому служба должна быть в другом потоке, чтобы она не закрывалась. и посмотрите, как сохранить службу с помощью диспетчера аварийных сигналов, вот пример http://www.vogella.com/articles/AndroidServices/article.html так что ваша служба не будет отображаться в уведомлении.
наконец, после всех исследований, которые я провел, я понимаю, что лучший выбор для долгосрочного обслуживания startForeground()
потому что это сделано для этого, и система на самом деле хорошо работает с вашим сервисом.
Услуги довольно сложны иногда.
Когда вы запускаете сервис из действия (или из вашего процесса), сервис, по сути, находится в том же процессе.
цитирование из заметок разработчика
Большая путаница в классе Service на самом деле вращается вокруг того, чем он не является:
Сервис не является отдельным процессом. Сам объект Service не подразумевает, что он работает в своем собственном процессе; если не указано иное, он выполняется в том же процессе, что и приложение, частью которого он является.
Сервис это не нить. Это не средство само по себе выполнять работу из основного потока (во избежание ошибок Application Not Responding).
Таким образом, это означает, что если пользователь удалит приложение от последних задач, он удалит ваш процесс (включая все ваши действия и т. Д.). Теперь давайте рассмотрим три сценария.
Во-первых, когда служба не имеет уведомления переднего плана.
В этом случае ваш процесс уничтожается вместе с вашим сервисом.
Во-вторых, когда служба имеет уведомление переднего плана
В этом случае служба не убивается и не является процессом
Третий сценарий Если у службы нет уведомления переднего плана, она может продолжать работать, если приложение закрыто. Мы можем сделать это, запустив службу в другом процессе. (Тем не менее, я слышал, что некоторые люди говорят, что это может не сработать. Вам самим стоит попробовать)
вы можете создать службу в отдельном процессе, включив в манифест атрибут, указанный ниже.
Android: процесс =":yourService"
или же
android:process="yourService" имя процесса должно начинаться со строчной буквы.
цитирование из заметок разработчика
Если имя, назначенное этому атрибуту, начинается с двоеточия (':'), новый процесс, частный для приложения, создается, когда это необходимо, и служба запускается в этом процессе. Если имя процесса начинается со строчной буквы, служба будет запускаться в глобальном процессе с таким именем, если у него есть разрешение на это. Это позволяет компонентам в разных приложениях совместно использовать процесс, сокращая использование ресурсов.
это то, что я собрал, если кто-то является экспертом, пожалуйста, поправьте меня, если я ошибаюсь:)
Сделать так, чтобы вы служили в своем Mainifest
<service
android:name=".sys.service.youservice"
android:exported="true"
android:process=":ServiceProcess" />
тогда ваш сервис будет работать на другом процессе с именем ServiceProcess
если вы хотите, чтобы ваш сервис никогда не умирал
onStartCommand () return START_STICKY
onDestroy () -> начать себя
создать сервис Deamon
jin -> создать процесс Native Deamon, вы можете найти несколько проектов с открытым исходным кодом на github
startForeground (), есть способ запустить Foreground без уведомлений, Google
Это может помочь вам. Я могу ошибаться, но мне кажется, что это связано с возвращением START_STICKY
в вашем onStartCommand()
метод. Вы можете избежать повторного вызова службы, вернувшись START_NOT_STICKY
вместо.
Основная проблема в том, что невозможно запустить службу, когда приложение закрыто, ОС Android (в некоторых ОС) убивает службу для оптимизации ресурсов. Если вы не можете перезапустить службу, затем вызовите диспетчер аварийных сигналов, чтобы запустить такой приемник, как здесь, здесь это весь код, этот код будет поддерживать ваш сервис.
Манифест есть,
<service
android:name=".BackgroundService"
android:description="@string/app_name"
android:enabled="true"
android:label="Notification" />
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="REFRESH_THIS" />
</intent-filter>
</receiver>
IN Main Activty запускает систему управления тревогами таким образом,
String alarm = Context.ALARM_SERVICE;
AlarmManager am = (AlarmManager) getSystemService(alarm);
Intent intent = new Intent("REFRESH_THIS");
PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0);
int type = AlarmManager.RTC_WAKEUP;
long interval = 1000 * 50;
am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi);
это вызовет reciver и reciver is,
public class AlarmReceiver extends BroadcastReceiver {
Context context;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
System.out.println("Alarma Reciver Called");
if (isMyServiceRunning(this.context, BackgroundService.class)) {
System.out.println("alredy running no need to start again");
} else {
Intent background = new Intent(context, BackgroundService.class);
context.startService(background);
}
}
public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
if (services != null) {
for (int i = 0; i < services.size(); i++) {
if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) {
return true;
}
}
}
return false;
}
}
И этот Alaram Reciver вызывает один раз, когда Android-приложение открыто и когда приложение закрыто. Так что сервис такой,
public class BackgroundService extends Service {
private String LOG_TAG = null;
@Override
public void onCreate() {
super.onCreate();
LOG_TAG = "app_name";
Log.i(LOG_TAG, "service created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "In onStartCommand");
//ur actual code
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// Wont be called as service is not bound
Log.i(LOG_TAG, "In onBind");
return null;
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i(LOG_TAG, "In onTaskRemoved");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroyed");
}
}
В Android O вы не можете использовать сервисы для длительных фоновых операций из-за этого, https://developer.android.com/about/versions/oreo/background. Jobservice будет лучшим вариантом с реализацией Jobscheduler.
Вы должны добавить этот код в свой класс Service, чтобы он обрабатывал случай, когда ваш процесс был убит
@Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
Попробуйте это, он будет работать в фоновом режиме.
BackServices.class
public class BackServices extends Service{
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
в вашей основной деятельности onCreate
бросьте эту строку кода
startService(new Intent(getBaseContext(), BackServices.class));
Теперь сервис будет работать в фоновом режиме.
Лучшее решение - использовать адаптер синхронизации в Android для запуска сервиса. Создайте адаптер синхронизации и вызовите службу запуска их.. внутри метода onPerformSync. Чтобы создать синхронизированную учетную запись, перейдите по этой ссылке https://developer.android.com/training/sync-adapters/index.html
Почему SyncAdapter? Ответ: Потому что раньше вы использовали для запуска службы, используя контекст вашего приложения. поэтому всякий раз, когда ваш процесс приложения будет уничтожен (когда вы удаляете его из диспетчера задач или ОС уничтожают его из-за недостатка ресурсов), в это время ваша служба также будет удалена. SyncAdapter не будет работать в потоке приложения... поэтому, если вы позвоните в него.. сервис больше не будет удален... если вы не напишите код для его удаления.
Использование одного и того же процесса для службы и действия и START_STICKY или START_REDELIVER_INTENT в службе - это единственный способ перезапустить службу, когда приложение перезапускается, что происходит, например, когда пользователь закрывает приложение, но также и когда система решает закрыть его по причинам оптимизации. Вы НЕ МОЖЕТЕ иметь службу, которая будет работать постоянно без каких-либо перерывов. Это дизайн, смартфоны не предназначены для непрерывного запуска процессов в течение длительного периода времени. Это связано с тем, что срок службы батареи является наивысшим приоритетом. Вы должны разработать свой сервис так, чтобы он был остановлен в любой момент.
Запуск службы намерений будет проще. Служба в создании потока в приложении, но это все еще в приложении.
Почему бы не использовать IntentService?
IntentService открывает новый поток отдельно от основного потока и работает там, поэтому закрытие приложения не приведет к его изменению
Имейте в виду, что IntentService запускает onHandleIntent(), и когда это будет сделано, служба закрывается, проверьте, соответствует ли она вашим потребностям. http://developer.android.com/reference/android/app/IntentService.html
<service android:name=".Service2"
android:process="@string/app_name"
android:exported="true"
android:isolatedProcess="true"
/>
Объявите это в своем манифесте. Дайте собственное имя вашему процессу и сделайте его изолированным и экспортированным.
Просто переопределите метод onDestroy в своем первом видимом действии, например, после всплеска у вас есть домашняя страница, и при перенаправлении с заставки на домашнюю страницу вы уже закончили всплеск. так что положить на уничтожить на домашней странице. и остановить службу в этом методе.