it-swarm.com.de

Wie kann ein Dienst automatisch neu gestartet werden, selbst wenn der Benutzer das Schließen erzwingt?

Ich möchte, dass ein Dienst in meiner Anwendung ständig ausgeführt wird. Ich möchte es also neu starten, auch wenn es vom Benutzer zwangsweise geschlossen wird. Es gibt definitiv eine Möglichkeit, dies zu tun, da Apps wie Facebook dies tun.

Jede Hilfe wäre dankbar. Vielen Dank!

38
Vipul J

Zuallererst ist es wirklich sehr schlechtes Muster, den Dienst gewaltsam auszuführen gegen die Bereitschaft des Benutzers.

Sie können es jedoch neu starten, indem Sie ein BroadcastReceiver verwenden, das die von onDestroy() Ihres Dienstes gesendete Sendung verarbeitet.

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

    }

}

Deklarieren Sie die Komponenten im Manifest Datei:

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

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

Starten Sie StickyService in einer Komponente (d. H. Application, Activity, Fragment):

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

OR

sendBroadcast(new Intent("YouWillNeverKillMe"));
65
Mehul Joisar

Sie müssen eine sticky service Mit überschreibender onTaskRemoved Methode erstellen, in der Sie einen Alarmdienst einrichten können, um Ihren Code erneut auszulösen.

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

Auch in einigen Geräten wie Xiaomi, Huwaei, wird die App zwangsweise geschlossen, sobald sie aus den letzten Apps entfernt wird. Dies liegt daran, dass die Hersteller über Task-Manager-Funktionen verfügen, die die RAM-/Batterie-Leistung verbessern.

Sie können diesen Link für weitere Informationen überprüfen: https://stackoverflow.com/a/41360159/2798289

11
Govind

Immer wenn ein Dienst beendet wird, wird seine onDestroy -Methode aufgerufen. Es ist besser, einen BroadcastReceiver zu verwenden, um Ihren Dienst zu starten, wenn er beendet wird.

Hier ist ein Beispielcode, der die Implementierung veranschaulicht:

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

Dann registriere einen Empfänger in AndroidManifest.xml: -

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

Erstellen Sie zum Schluss ein BroadcastReceiver und starten Sie Ihren Dienst in der onReceive -Methode: -

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

Hoffe das hilft.

4
Atish Agrawal

Gemäß Dokument Android

Starting from Android 3.1, the system's 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's stopped state is not the same as an Activity's 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.

Wenn Sie das Beenden der App erzwingen, Android beenden Sie einfach die Prozess-ID. Keine Warnungen, Rückrufe werden zu Service/Aktivitäten gegeben. Gemäß dem Dokument Android besteht die Möglichkeit, dass die App beim Beenden onPause () aufruft.

Als ich es in meiner App versuchte, wurde auch onPause () nicht aufgerufen. Ich denke, der einzige Weg ist, das FLAG_INCLUDE_STOPPED_PACKAGES Absichtsflag zu verwenden und es von einer anderen App zu senden

4
Zohra Khan

geben Sie bei der startCommand-Methode des Dienstes START_STICKY zurück. Im Allgemeinen wird das Betriebssystem angewiesen, den Dienst zu starten, wenn er beendet wird.

3
Bijesh

Wenn ich das richtig verstehe, ist dies tatsächlich nicht möglich. Android) Die Funktion zum Erzwingen des Schließens einer Anwendung wurde entwickelt, um es dem Benutzer zu ermöglichen, unerwünschte Anwendungen zu entfernen, sodass keine Aktivitäten von ihr zugelassen werden, bis der Benutzer erneut startet eine seiner Aktivitäten.

Starten Sie den Dienst neu, auch wenn die App erzwungen wurde, und führen Sie den Dienst auch nach dem Schließen der App im Hintergrund aus. Wie?

2
marcinj

Wenn es die Situation erlaubt, 'root' zu verwenden, ist es normalerweise möglich, das Humpty-Dumpty-Paradigma zu implementieren.

Ihre Anwendung (1.) installiert eine andere Anwendung (2., nimmt APK von Assets) und führt den Dienst der 2. App aus. Der Dienst der 2. App wird an den Dienst der 1. App gebunden und beim Trennen erneut gebunden. Die 1. App macht das gleiche.

Sicher wird es nicht helfen, wenn alle Apps von einer kostenlosen RAM oder einer ähnlichen Anwendung getötet werden, aber wenn Android eine dieser beiden tötet, startet die andere neu Gegenstück.

2
OGP

Die einzige echte Lösung, um Dienste am Leben zu erhalten, besteht darin, Service.startForeground(...) mit einer bereitgestellten Benachrichtigung aufzurufen. Dies ist die einzig gültige Lösung. Jede andere ist stark davon abhängig, wie Google das Verhalten seines Systems ändert. Mit jedem API-Update könnte Google jeden anderen Hack verhindern.

Dadurch wird dem Benutzer auch bewusst, dass Ihre App eine Hintergrundaufgabe ausführt, die die App am Leben erhält, und der Benutzer muss dies beenden. Wenn Sie dem Benutzer die Möglichkeit geben, ihn zu stoppen, ist dies jedoch Teil Ihrer Anwendung.

Siehe Dokumentation:

void startForeground (int id, Notification notification)

Stellen Sie sicher, dass dieser Dienst im Vordergrund ausgeführt wird und die laufende Benachrichtigung dem Benutzer angezeigt wird, während er sich in diesem Status befindet. Standardmäßig handelt es sich bei Diensten um Hintergrunddienste, dh wenn das System sie beenden muss, um mehr Speicher freizugeben (z. B. um eine große Seite in einem Webbrowser anzuzeigen), können sie ohne großen Schaden beendet werden. Sie können dieses Flag setzen, wenn das Beenden Ihres Dienstes den Benutzer stören würde, z. B. wenn Ihr Dienst Hintergrundmusikwiedergabe ausführt, sodass der Benutzer feststellen würde, wenn die Musikwiedergabe gestoppt wird.

1
da_berni

Es gibt eine sehr hackige Lösung, um den Dienst auch dann am Laufen zu halten, wenn Sie es erzwingen, ihn zu stoppen. Ich empfehle das nicht, weil es gegen die Benutzerbereitschaft ist. Sie können einen Broadcast-Empfänger für den Empfang von Absichten mit der Aktion X definieren. Senden Sie bei StartCommand-Handler Ihres Dienstes X (wenn der Dienst noch nicht gestartet wurde). Starten Sie beim Empfang von X auf dem Rundfunkempfänger zuerst den Dienst, schlafen Sie dann einige Minuten und senden Sie X schließlich erneut.

0
Nami