Служба Android Останавливается, Когда Приложение Закрыто
Я запускаю сервис из моей основной деятельности Android следующим образом:
final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);
Когда я закрываю страницу активности, проводя ее из списка последних приложений, служба перестает работать и перезапускается через некоторое время. Я не могу использовать постоянные службы с уведомлениями из-за требований к приложению. Как сделать так, чтобы служба не перезапускалась и не выключалась, а просто продолжала работать при выходе из приложения?
13 ответов:
Я нахожусь в той же ситуации, до сих пор я узнал, когда приложение закрыто, сервис закрывается также потому, что они находятся в одном потоке, поэтому сервис должен быть в другом потоке, чтобы он не был закрыт, посмотрите на это и посмотрите, чтобы сохранить службу живой с alarm manager вот пример http://www.vogella.com/articles/AndroidServices/article.html таким образом, ваш сервис не будет отображаться в уведомлении.
Наконец, после всех исследований, которые я сделал, я прихожу к поймите, что лучший выбор для длительного обслуживания-это
startForeground()
, потому что она создана для этого, и система действительно хорошо справляется с вашим сервисом.
Это может вам помочь. Я могу ошибаться, но мне кажется, что это связано с возвращением
START_STICKY
в вашем методеonStartCommand()
. Вы можете избежать повторного вызова службы, вернув вместо этогоSTART_NOT_STICKY
.
Сделать вас обслуживание как это в вашем Манифеста
<service android:name=".sys.service.youservice" android:exported="true" android:process=":ServiceProcess" />
Тогда ваша служба будет работать на другом процессе с именем ServiceProcess
Если вы хотите, чтобы ваша служба никогда не умирала:
OnStartCommand () возвращает START_STICKY
OnDestroy () - > startself
Создайте службу Deamon
Jin - > создайте собственный процесс Deamon, вы можете найти некоторые проекты с открытым исходным кодом на github
Начальный план() , есть способ начать переднюю часть без уведомления, google it
Услуги иногда довольно сложны.
Когда вы запускаете службу из действия (или вашего процесса), служба по существу находится в том же самом процессе.
Цитирование из заметок разработчика
Большая путаница в отношении класса обслуживания на самом деле вращается вокруг того, чем он не является:
Служба-это не отдельный процесс. Сам объект сервиса не подразумевает, что он выполняется в собственном процессе; если не указано иное, он выполняется в том же процессе, что и объект сервиса. приложение, частью которого он является.
Служба-это не поток. Это не средство само по себе делать работу вне основного потока (чтобы избежать ошибок приложения, не отвечающего на запросы).
Итак, это означает, что если пользователь уберет приложение от недавних задач, он удалит ваш процесс (это включает все ваши действия и т. д.). Теперь давайте рассмотрим три сценария.
Первый где служба не имеет переднего плана уведомление.
В этом случае ваш процесс будет убит вместе с вашим сервисом.
второе где служба имеет уведомление переднего плана
В этом случае служба не убита, как и процесс
третий сценарий Если служба не имеет уведомления переднего плана, она все еще может продолжать работать, если приложение закрыто. Мы можем сделать это, заставив службу работать в другом процессе. (Однако, Я слышал, что некоторые люди говорят, что это может не сработать. предоставлено вам самому попробовать )
Вы можете создать сервис в отдельном процессе, включив следующий атрибут в вашем манифесте.
Android: process=": yourService "
Или
Android: process= "yourService" имя процесса должно начинаться со строчной буквы.
Цитирование из заметок разработчика
Если имя, присвоенное этому атрибуту, начинается с двоеточия ( ' :'), то процесс, закрытый для приложения, создается, когда это необходимо, и служба запускается в этом процессе. Если имя процесса начинается с символа в нижнем регистре , служба будет работать в глобальном процессе с таким именем, при условии, что у нее есть на это разрешение. Это позволяет компонентам в различных приложениях совместно использовать процесс, уменьшая потребление ресурсов.
Это то, что я собрал, если кто-то является экспертом, пожалуйста, поправьте меня, если я ошибаюсь :)
Попробуйте это, он будет держать службу работает в фоновом режиме.
Бэксервисы.класс
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 (в некоторых ОС ) убьет службу для оптимизации ресурсов, если вы не можете перезапустить службу, то вызовите аварийную кормушку, чтобы запустить ресивер, как это,вот весь код, этот код будет поддерживать жизнь службы ur.
Манифест есть,
<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>
В 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);
Это потребует ресивер и ресивер-это,
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; } }
И этот Аларам reciver звонит один раз, когда приложение для android открыто и когда приложение closed.SO служба такова,
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 для запуска службы. Создайте адаптер синхронизации и вызовите службу запуска их.. внутри метода onPerformSync. чтобы создать учетную запись синхронизации, перейдите по этой ссылке https://developer.android.com/training/sync-adapters/index.html
Почему Именно SyncAdapter? Ans: потому что раньше вы запускали службу, используя контекст приложения. поэтому всякий раз, когда ваш процесс приложения будет убит (когда вы удалите его из Диспетчера задач или ОС убьет его из-за отсутствия ресурсы) в это время ваш сервис также будет удален. 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" />
Вы должны добавить этот код в свой класс обслуживания, чтобы он обрабатывал случай, когда ваш процесс убивается
@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); }