it-swarm.com.de

Android-Dienst stoppt, wenn die App geschlossen ist

Ich starte einen Dienst aus meiner Android-Hauptaktivität wie folgt:

final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);

Wenn ich die Aktivitätsseite schließe, indem ich sie aus der Liste der zuletzt verwendeten Apps auswische, wird der Dienst nicht mehr ausgeführt und startet nach einiger Zeit neu. Aufgrund meiner App-Anforderungen kann ich keine permanenten Dienste mit Benachrichtigungen verwenden. Wie kann ich den Dienst NICHT neu starten oder herunterfahren lassen und einfach beim Beenden der App weiterlaufen?

66
Bam

Ich bin in der gleichen Situation, soweit ich erfuhr, wenn die App geschlossen ist, wird der Dienst geschlossen, da sie sich in einem Thread befinden. Der Dienst sollte sich also in einem anderen Thread befinden, damit er nicht geschlossen wird und schauen Sie sich an, wie Sie den Dienst mit dem Alarmmanager am Leben erhalten. http://www.vogella.com/articles/AndroidServices/article.html Auf diese Weise wird Ihr Dienst nicht in der Benachrichtigung angezeigt.

nach all den Nachforschungen, die ich durchgeführt habe, werde ich feststellen, dass startForeground() die beste Wahl für einen lang laufenden Service ist, weil er dafür gemacht wurde und das System tatsächlich mit Ihrem Service gut umgeht.

38
aljuaid86

Das kann dir helfen. Ich kann falsch sein, aber es scheint mir, dass dies mit der Rückgabe von START_STICKY in Ihrer onStartCommand()-Methode zusammenhängt. Sie können verhindern, dass der Dienst erneut aufgerufen wird, indem Sie stattdessen START_NOT_STICKY zurückgeben.

12
artex

machen Sie Ihren Dienst so in Ihrem Mainifest 

 <service
            Android:name=".sys.service.youservice"
            Android:exported="true"
        Android:process=":ServiceProcess" />

dann wird Ihr Dienst auf einem anderen Prozess namens ServiceProcess ausgeführt


wenn du willst, dass dein Dienst niemals stirbt:

  1. onStartCommand () gibt START_STICKY zurück

  2. onDestroy () -> selbst starten

  3. erstellen Sie einen Deamon-Service 

  4. jin -> Erstellen Sie einen Native Deamon-Prozess. Auf github finden Sie einige Open-Source-Projekte

  5. startForeground (), gibt es eine Möglichkeit, ForForeground ohne Benachrichtigung zu starten, google es

12
alanban

Dienstleistungen sind manchmal ziemlich kompliziert.

Wenn Sie einen Dienst aus einer Aktivität (oder Ihrem Prozess) starten, befindet sich der Dienst im Wesentlichen im selben Prozess.

zitate aus den Entwicklerhinweisen

Die meisten Verwirrungen über die Service-Klasse beziehen sich tatsächlich auf das, was es nicht ist:

Ein Service ist kein separater Prozess. Das Service-Objekt selbst bedeutet nicht, dass es in einem eigenen Prozess ausgeführt wird. Sofern nicht anders angegeben, wird es in demselben Prozess ausgeführt wie die Anwendung, zu der es gehört.

Ein Service ist kein Thread. Es ist kein Mittel selbst, um vom Hauptthread aus zu arbeiten (um Fehler bei der Anwendung nicht zu reagieren).

Dies bedeutet also, wenn der Benutzer die App von den letzten Aufgaben entfernt, wird er Ihren Prozess löschen (dies schließt alle Ihre Aktivitäten usw. ein). Nun nehmen wir drei Szenarien. 

First wo der Dienst nicht eine Vordergrundbenachrichtigung hat.

In diesem Fall wird Ihr Prozess zusammen mit Ihrem Service beendet.

Second wo der Dienst hat eine Vordergrundbenachrichtigung

In diesem Fall wird der Dienst nicht beendet und der Prozess auch nicht

Third Szenario Wenn der Dienst keine Vordergrundbenachrichtigung hat, kann er weiterhin ausgeführt werden, wenn die App geschlossen wird. Wir können dies tun, indem der Dienst in einem anderen Prozess ausgeführt wird. .__ ((Ich habe jedoch gehört, dass einige Leute sagen, dass es möglicherweise nicht funktioniert. Ihnen überlassen, es selbst auszuprobieren)

sie können einen Service in einem separaten Prozess erstellen, indem Sie das folgende Attribut unten in Ihr Manifest einfügen.

Android: process = ": yourService"

oder

Android: process = "yourService" Prozessname muss mit Kleinbuchstaben beginnen.

zitat aus den Entwicklernotizen

Wenn der diesem Attribut zugewiesene Name mit einem Doppelpunkt (':') beginnt, wird bei Bedarf ein neuer, für die Anwendung privater Prozess erstellt, und der Dienst wird in diesem Prozess ausgeführt. Wenn der Prozessname mit einem Kleinbuchstaben -Zeichen beginnt, wird der Dienst in einem globalen Prozess mit diesem Namen ausgeführt, sofern er dazu berechtigt ist. Dadurch können Komponenten in verschiedenen Anwendungen einen Prozess gemeinsam nutzen, wodurch der Ressourcenverbrauch reduziert wird.

das ist, was ich gesammelt habe, wenn jemand ein Experte ist, korrigieren Sie mich bitte, wenn ich falsch liege :)

3
mmmcho

Das Hauptproblem, dass der Dienst nicht gestartet werden kann, wenn die App geschlossen wird, beendet Android OS ( In einigen OS ) den Dienst für die Ressourcenoptimierung Hier ist der gesamte Code. Dieser Code hält Ihren Dienst am Leben.

Manifest ist,

         <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 der Hauptaktivität starten Sie den Alarmmanager auf diese Weise.

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

dies wird Reciver und Reciver anrufen,

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

Und dieser Alaram Reciver ruft einmal an, wenn die Android-App geöffnet ist und wenn die App geschlossen ist. So ist der Dienst 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");
    }
}
2
Ajith K P

probieren Sie dies aus, der Dienst wird im Hintergrund ausgeführt.

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

in Ihrer MainActivity onCreate lassen Sie diese Codezeile fallen 

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

Jetzt läuft der Dienst im Hintergrund weiter.

2

Von Android O aus können Sie die Dienste nicht für lang andauernde Hintergrundoperationen verwenden, https://developer.Android.com/about/versions/oreo/background . Jobservice wird mit der Implementierung von Jobscheduler die bessere Option sein.

1
abhi.nalwade

Die Verwendung des gleichen Prozesses für den Dienst und die Aktivität und START_STICKY oder START_REDELIVER_INTENT im Dienst ist die einzige Möglichkeit, den Dienst neu starten zu können, wenn die Anwendung neu gestartet wird. Dies geschieht beispielsweise, wenn der Benutzer die Anwendung schließt, aber auch, wenn das System entscheidet aus Optimierungsgründen zu schließen. Sie können KEINEN Dienst haben, der dauerhaft ohne Unterbrechung ausgeführt wird. Dies ist beabsichtigt, Smartphones sind nicht dazu gedacht, über längere Zeit kontinuierliche Prozesse auszuführen. Dies liegt daran, dass die Akkulaufzeit höchste Priorität hat. Sie müssen Ihren Dienst so gestalten, dass er jederzeit angehalten werden kann.

1
stef

Die beste Lösung ist, den Sync-Adapter in Android zu verwenden, um den Dienst zu starten. Erstellen Sie einen Synchronisationsadapter, und rufen Sie den Startdienst in der Methode onPerformSync auf. Um einen Sync Account zu erstellen, verweisen Sie bitte auf diesen Link https://developer.Android.com/training/sync-adapters/index.html

Warum SyncAdapter? Antwort: Weil Sie früher den Dienst mit Ihrem App-Kontext gestartet haben. Wenn also Ihr App-Prozess beendet wird (wenn Sie ihn aus dem Task-Manager entfernen oder das Betriebssystem aufgrund mangelnder Ressourcen töten), wird Ihr Dienst zu diesem Zeitpunkt ebenfalls entfernt. SyncAdapter funktioniert nicht im Anwendungsthread. Wenn Sie also einen Aufruf aufrufen, wird der Dienst nicht mehr entfernt. Es sei denn, Sie schreiben Code, um ihn zu entfernen. 

1
Nishanth S Babu

Sie müssen diesen Code Ihrer Service-Klasse hinzufügen, damit der Fall bearbeitet wird, wenn Ihr Prozess beendet wird 

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

Das Ausführen eines absichtlichen Dienstes wird einfacher. Dienst beim Erstellen eines Threads in der Anwendung, der sich jedoch noch in der Anwendung befindet. 

0
Seb
<service Android:name=".Service2"
            Android:process="@string/app_name"
            Android:exported="true"
            Android:isolatedProcess="true"
            />

Erkläre dies in deinem Manifest. Geben Sie Ihrem Prozess einen benutzerdefinierten Namen und machen Sie diesen Prozess isoliert und exportieren. 

0
Nishanth S Babu

Warum nicht einen IntentService nutzen?

IntentService öffnet einen neuen Thread neben dem Haupt-Thread und funktioniert dort. Auf diese Weise wird die App nicht geschlossen

Beachten Sie, dass IntentService onHandleIntent () ausführt. Wenn der Dienst beendet ist, prüfen Sie, ob er Ihren Anforderungen entspricht. http://developer.Android.com/reference/Android/app/IntentService.html

0
sharon gur