Служба 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


Если вы хотите, чтобы ваш сервис никогда не умирал:

  1. onStartCommand () возвращает START_STICKY

  2. onDestroy() -> startself

  3. создать службу Deamon

  4. jin - > создайте собственный процесс Deamon, вы можете найти некоторые проекты с открытым исходным кодом на GitHub

  5. startForeground (), есть способ startForeground без уведомления, google it


услуги иногда довольно сложны.

когда вы запускаете службу из действия (или вашего процесса), служба по существу находится в том же процессе.

цитирование из примечаний разработчика

большая путаница в классе обслуживания фактически вращается вокруг того, что это не так:

служба не является отдельным процессом. Сам объект сервиса не означает, что он работает в своем собственном процессе; если не указано иное, он работает в том же процессе, что и приложение, частью которого он является.

сервис не поток. Это не само по себе средство для работы с основным потоком (чтобы избежать ошибок, не отвечающих приложению).

Итак, что это означает, если пользователь удаляет приложение от последних задач, он удалит ваш процесс(это включает в себя все ваши действия и т. д.). Теперь рассмотрим три сценария.

первый где служба нет уведомления переднем плане.

в этом случае ваш процесс будет убит вместе с вашим сервисом.

второй где служба и уведомление переднего плана

в этом случае служба не убита и не является процессом

третий сценарий Если служба не имеет уведомления переднего плана, она может продолжать работать, если приложение закрыто. Мы можем сделать это путем запуска услуги в другом процессе. (Тем не менее, я слышал, что некоторые люди говорят, что это может не сработать. оставил вам попробовать его самостоятельно)

вы можете создать службу в отдельном процессе, включив атрибут ниже в вашем манифесте.

android: process=": yourService"

или

android: process= "yourService" имя процесса должно начинаться с нижнего случай.

цитирование из заметок разработчика

Если имя, присвоенное этому атрибуту, начинается с двоеточия ( ' :'), новый процесс, закрытый для приложения, создается, когда это необходимо, и служба запускается в этом процессе. Если имя процесса начинается с строчные символ, служба будет работать в глобальном процессе с этим именем, при условии, что у нее есть разрешение на это. Это позволяет компонентам в различных приложениях совместно использовать процесс, сокращение использования ресурсов.

это то, что я собрал, если кто знаток, пожалуйста, поправьте меня, если я ошибаюсь :)


попробуйте это, он будет держать службу работает в фоновом режиме.

BackServices.класс!--7-->

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();
   }
}

в своем MainActivity onCreate брось эту строку кода

startService(new Intent(getBaseContext(), BackServices.class));

Теперь служба будет работать в фоновом режиме.


основная проблема в неспособности запустить службу, когда приложение закрыто, Android OS (в некоторых ОС) убьет службу для оптимизации ресурсов, если вы не можете перезапустить службу,то вызовите сигнализацию,чтобы запустить приемник, как это, вот весь код, этот код будет поддерживать службу 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>

в основной 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 есть

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 для запуска службы. Создайте адаптер синхронизации и вызовите службу start.. внутри метода onPerformSync. чтобы создать учетную запись синхронизации, обратитесь по этой ссылке https://developer.android.com/training/sync-adapters/index.html

Почему SyncAdapter? Ans: потому что ранее вы использовали для запуска службы, используя контекст приложения. поэтому всякий раз, когда ваш процесс приложения убивают (когда u удалить его из Диспетчера задач или ОС убить его из-за нехватки ресурсов ) в это время ваш сервис также будет удален. 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);
    }

запуск службы intent будет проще. Служба создания потока в приложении, но она все еще находится в приложении.


просто переопределите метод onDestroy в первом видимом действии, например, после всплеска у вас есть домашняя страница, и при перенаправлении с всплеска на домашнюю страницу вы уже закончили всплеск. поэтому поставьте на destroy на домашней странице. и остановите обслуживание в этом методе.