Подтвердить что ты не робот

Как автоматически перезапустить службу, даже если пользователь закроет ее?

Я хочу, чтобы служба выполнялась все время в моем приложении. Поэтому я хочу перезапустить его, даже если он закрыт пользователем. Существует определенно способ сделать это, поскольку такие приложения, как facebook, делают это. (Его не делают с помощью push-уведомления, facebook перезапускает свою службу, даже если интернет выключен).

Любая помощь будет оценена по достоинству. Спасибо!

4b9b3361

Ответ 1

Прежде всего, это действительно очень плохой шаблон, чтобы выполнить сервис сильным против готовности пользователя.

В любом случае вы можете перезапустить его, используя BroadcastReceiver, который обрабатывает широковещательную рассылку, отправленную из onDestroy() вашей службы.

StickyService.java

public class StickyService extends Service
{
    private static final String TAG = "StickyService";


    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        sendBroadcast(new Intent("YouWillNeverKillMe"));
    }

}

RestartServiceReceiver.java

public class RestartServiceReceiver extends BroadcastReceiver
{

    private static final String TAG = "RestartServiceReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(TAG, "onReceive");
    context.startService(new Intent(context.getApplicationContext(), StickyService.class));

    }

}

Объявить компоненты в манифесте:

    <service android:name=".StickyService" >
    </service>

    <receiver android:name=".RestartServiceReceiver" >
        <intent-filter>
            <action android:name="YouWillNeverKillMe" >
            </action>
        </intent-filter>
    </receiver>

Запустите StickyService в компоненте (т.е. Application, Activity, Fragment):

startService(new Intent(this, StickyService.class));

ИЛИ

sendBroadcast(new Intent("YouWillNeverKillMe"));

Ответ 2

Вы должны создать sticky service с переопределением метода onTaskRemoved, где вы можете настроить службу будильника для повторного запуска кода.

public class BackgroundService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        //create an intent that you want to start again.
        Intent intent = new Intent(getApplicationContext(), BackgroundService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
        super.onTaskRemoved(rootIntent);
    }
}

Также в некоторых устройствах, таких как Xiaomi, Huwaei, приложение закрывает силу после удаления из последних приложений. Это связано с тем, что у производителей есть функции диспетчера задач, которые улучшают производительность плунжера/батареи.

Вы можете проверить эту ссылку для получения дополнительной информации: fooobar.com/questions/182739/...

Ответ 3

Всякий раз, когда служба убивается, всегда вызывается метод onDestroy. Лучше использовать BroadcastReceiver, чтобы начать службу, когда она будет убита.

Вот пример кода, иллюстрирующий его реализацию: -

@Override
public void onDestroy() {
Intent in = new Intent();
in.setAction("StartkilledService");
sendBroadcast(in);
Log.d("debug", "Service Killed");
}

Затем зарегистрируйте приемник в AndroidManifest.xml: -

<receiver android:name=".app.ServiceDestroyReceiver" >
    <intent-filter>
        <action android:name="StartKilledService" >
        </action>
    </intent-filter>
</receiver>

Наконец, создайте BroadcastReceiver и запустите службу в методе onReceive: -

@Override
public void onReceive(Context context, Intent intent) {
Log.d("debug", "ServeiceDestroy onReceive...");
Log.d("debug", "action:" + intent.getAction());
Log.d("debug", "Starting Service");
ServiceManager.startService();
}

Надеюсь, что это поможет.

Ответ 4

в сервисе startCommand метод возвращает START_STICKY. обычно он сообщает ОС, чтобы начать службу, когда она будет убита.

Ответ 5

В соответствии с документом Android

Starting from Android 3.1, the system package manager keeps track of applications 
that are in a stopped state and provides a means of controlling their launch from 
background processes and other applications.

Note that an application stopped state is not the same as an Activity stopped
state. The system manages those two stopped states separately.
FLAG_INCLUDE_STOPPED_PACKAGES — Include intent filters of stopped applications in the
list of potential targets to resolve against.

FLAG_EXCLUDE_STOPPED_PACKAGES — Exclude intent filters of stopped applications from the
list of potential targets.

When neither or both of these flags is defined in an intent, the default behavior is to
include filters of stopped applications in the list of potential targets. 

Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents.
It does this to prevent broadcasts from background services from inadvertently or
unnecessarily launching components of stopped applications. A background service 
or application can override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES
flag to broadcast intents that should be allowed to activate stopped applications.

В Force Force приложения Android просто уничтожит идентификатор процесса. Никаких предупреждений, обратных вызовов не предоставляется службам/действиям. Согласно документу Android, когда приложение убито, есть вероятность, что он вызывает onPause().

Когда я попытался в своем приложении, даже onPause() не вызывался. Я думаю, что единственный способ использовать флаг FLAG_INCLUDE_STOPPED_PACKAGES намерения и отправить его из другого приложения

Ответ 6

Если я правильно понимаю, то на самом деле это невозможно, функция Android для принудительного закрытия приложения была разработана, чтобы позволить пользователю избавиться от нежелательных приложений, поэтому он запрещает любые действия от него до тех пор, пока пользователь снова не начнет любое из своих действий.

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

Ответ 7

Если ситуация позволяет использовать "корень", то обычно можно реализовать парадигму Шалтай-Болти.

Ваше приложение (1-е) устанавливает другое приложение (второе, беря APK из активов) и запускает сервис второго приложения. Служба 2-го приложения привязывается к службе 1-го приложения и восстанавливается при отключении. Первое приложение делает то же самое.

Конечно, это не поможет, когда все приложения будут убиты какой-либо свободной оперативной памятью или аналогичным приложением, но когда Android убьет любого из этих двух, другой перезапустит свою копию.

Ответ 8

Существует очень хакерское решение, позволяющее поддерживать работу даже в случае ее остановки. Я не рекомендую это, потому что это против желания пользователей. Вы можете определить широковещательный приемник для получения намерения с действием X. onStartCommand обработчик вашей службы, трансляция X (если служба еще не запущена). на широковещательном приемнике после получения X, сначала запустите службу, затем, спать в течение нескольких минут и, наконец, перепрограммировать X.

Ответ 9

Я думаю, что единственное надежное решение здесь состоит в том, чтобы иметь 2 службы в отдельных процессах (android:process="somecustomprocessname" в манифесте, в записи службы), которые одновременно слушают трансляции и перезапускают друг друга, поскольку в настоящее время пользовательский интерфейс не позволяет пользователям убивать несколько процессов в одном действии. Затем вы можете настроить поток нити в каждой службе, которая проверяет, работает ли другая служба каждые 100 миллисекунд или нет, а если нет, пытается ее перезапустить. Но это начинает все больше напоминать вредоносное ПО...

Ответ 10

Единственное реальное решение для сохранения сервисов - это вызов Service.startForeground(...) с предоставленным уведомлением. Это будет единственным действительным решением, и каждый другой будет очень зависеть от того, как Google изменит поведение системы. С каждым обновлением API Google может предотвратить любой другой взлом.

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

См. документацию:

void startForeground (int id, Notification notification)

Сделать этот сервис запущенным на переднем плане, предоставляя текущее уведомление пользователю, пока оно находится в этом состоянии. По умолчанию службы являются фоном, а это означает, что если система должна убить их, чтобы вернуть больше памяти (например, чтобы отобразить большую страницу в веб-браузере), они могут быть убиты без особого вреда. Вы можете установить этот флаг, если убийство вашей службы будет разрушительным для пользователя, например, если ваша служба выполняет фоновое воспроизведение музыки, поэтому пользователь заметил бы, что их музыка перестала играть.