Ich starte einen Dienst von meiner Hauptaktivität für Android aus 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 herauswische, wird der Dienst nicht mehr ausgeführt und nach einiger Zeit neu gestartet. Ich kann aufgrund meiner App-Anforderungen keine dauerhaften Dienste mit Benachrichtigungen verwenden. Wie kann ich den Dienst NICHT neu starten oder herunterfahren lassen und beim Beenden der App einfach weiterlaufen lassen?
Antworten:
Ich bin in der gleichen Situation, bis jetzt habe ich erfahren, dass der Dienst geschlossen wird, wenn die App geschlossen wird, auch weil sie sich in einem Thread befinden. Der Dienst sollte sich also in einem anderen Thread befinden, damit er nicht geschlossen wird und versuchen Sie, den Dienst mit dem Alarmmanager am Leben zu erhalten. Hier ein Beispiel: http://www.vogella.com/articles/AndroidServices/article.html Auf diese Weise wird Ihr Dienst nicht in der Benachrichtigung angezeigt.
Nach all den Recherchen, die ich durchgeführt habe, stelle ich schließlich fest, dass die beste Wahl für einen lang laufenden Dienst ist
startForeground()
, weil er dafür gemacht ist und das System tatsächlich gut mit Ihrem Dienst umgeht.quelle
notificationManager.notify(intent.getIntExtra("notification_Id", 0), builder.build());
sollte ich verwendenstartForeground(intent.getIntExtra("notification_Id, 0), builder.build());
? Ich benutze NotificationCompat.BuilderLassen Sie sich in Ihrem Mainifest so bedienen
<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:
onStartCommand () gibt START_STICKY zurück
onDestroy () -> startself
Erstellen Sie einen Deamon-Service
jin -> Erstelle einen Native Deamon-Prozess. Auf github findest du einige Open-Source-Projekte
startForeground () gibt es eine Möglichkeit ,Foreground ohne Benachrichtigung zu starten, googeln Sie es
quelle
Dies kann Ihnen helfen. Ich kann mich irren, aber es scheint mir, dass dies mit der Rückkehr
START_STICKY
in IhreonStartCommand()
Methode zusammenhängt. Sie können verhindern, dass der Dienst erneut aufgerufen wird, indem SieSTART_NOT_STICKY
stattdessen zurückkehren .quelle
Dienstleistungen sind manchmal ziemlich kompliziert.
Wenn Sie einen Dienst von einer Aktivität (oder Ihrem Prozess) aus starten, befindet sich der Dienst im Wesentlichen im selben Prozess.
Zitieren aus den Entwicklernotizen
Dies bedeutet also, dass der Benutzer Ihren Prozess löscht, wenn der Benutzer die App von den letzten Aufgaben entfernt (dies schließt alle Ihre Aktivitäten usw. ein). Nehmen wir nun drei Szenarien.
Erstens, wenn der Dienst keine Vordergrundbenachrichtigung hat.
In diesem Fall wird Ihr Prozess zusammen mit Ihrem Dienst beendet.
Zweitens , wo der Dienst hat eine Vordergrund Benachrichtigung
In diesem Fall wird der Dienst nicht beendet und der Prozess auch nicht
Drittes Szenario Wenn der Dienst keine Vordergrundbenachrichtigung hat, kann er weiterhin ausgeführt werden, wenn die App geschlossen wird. Wir können dies tun, indem wir den Service in einem anderen Prozess ausführen. (Ich habe jedoch einige Leute sagen hören, dass es möglicherweise nicht funktioniert. Es bleibt Ihnen überlassen, es selbst auszuprobieren. )
Sie können einen Service in einem separaten Prozess erstellen, indem Sie das folgende Attribut in Ihr Manifest aufnehmen.
android: process = ": yourService"
oder
android: process = "yourService" Prozessname muss mit Kleinbuchstaben beginnen.
Zitieren aus Entwicklernotizen
das habe ich gesammelt, wenn jemand ein Experte ist, korrigiere mich bitte, wenn ich falsch liege :)
quelle
Unter Android O können Sie die Dienste aus diesem Grund nicht für die lang laufenden Hintergrundvorgänge verwenden: https://developer.android.com/about/versions/oreo/background . Jobservice ist die bessere Option bei der Implementierung von Jobscheduler.
quelle
Das Hauptproblem besteht darin, dass der Dienst nicht gestartet werden kann, wenn die App geschlossen wird. Das Android-Betriebssystem ( in einigen Betriebssystemen ) beendet den Dienst für die Ressourcenoptimierung. Wenn Sie den Dienst nicht neu starten können, rufen Sie einen Alarmmanager an, um den Empfänger wie folgt zu starten. Hier ist der gesamte Code. Dieser Code wird Ihren Dienst am Leben erhalten.
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 Main Activty Start Alarm Manager 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 Empfänger nennen und Empfänger ist,
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-Empfänger ruft einmal an, wenn die Android-App geöffnet und die App geschlossen wird.
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"); } }
quelle
Versuchen Sie dies, der Dienst wird weiterhin 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(); } }
Lassen Sie in Ihrer MainActivity
onCreate
diese Codezeile fallenstartService(new Intent(getBaseContext(), BackServices.class));
Jetzt läuft der Dienst im Hintergrund weiter.
quelle
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 beim Neustart der Anwendung neu zu starten. Dies geschieht beispielsweise, wenn der Benutzer die Anwendung schließt, aber auch, wenn das System entscheidet um es aus Optimierungsgründen zu schließen. Sie können keinen Dienst haben, der ohne Unterbrechung dauerhaft ausgeführt wird. Dies ist beabsichtigt, Smartphones sind nicht dafür ausgelegt, über einen längeren Zeitraum kontinuierliche Prozesse auszuführen. Dies liegt an der Tatsache, dass die Batterielebensdauer die höchste Priorität hat. Sie müssen Ihren Service so gestalten, dass er jederzeit gestoppt werden kann.
quelle
Sie müssen diesen Code zu Ihrer Service-Klasse hinzufügen, damit er den Fall behandelt, in dem 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); }
quelle
Warum nicht einen IntentService nutzen?
IntentService öffnet einen neuen Thread neben dem Haupt-Thread und arbeitet dort. Auf diese Weise wird das Schließen der App nicht beeinflusst
Beachten Sie, dass IntentService onHandleIntent () ausführt. Wenn der Dienst abgeschlossen ist, prüfen Sie, ob er Ihren Anforderungen entspricht. http://developer.android.com/reference/android/app/IntentService.html
quelle
Die beste Lösung ist, den Synchronisierungsadapter in Android zu verwenden, um den Dienst zu starten. Erstellen Sie einen Synchronisierungsadapter und rufen Sie den Startdienst ihrer .. on onPerformSync-Methode auf. Informationen zum Erstellen eines Synchronisierungskontos finden Sie unter folgendem Link: https://developer.android.com/training/sync-adapters/index.html
Warum SyncAdapter? Antwort: Weil Sie den Dienst früher über Ihren App-Kontext gestartet haben. Wenn Ihr App-Prozess zu diesem Zeitpunkt beendet wird (wenn Sie ihn aus Task-Manager oder Betriebssystem entfernen, weil er nicht über ausreichende Ressourcen verfügt), wird zu diesem Zeitpunkt auch Ihr Dienst entfernt. SyncAdapter funktioniert nicht im Anwendungsthread. Wenn Sie also darin aufrufen, wird der Dienst nicht mehr entfernt. Es sei denn, Sie schreiben Code, um ihn zu entfernen.
quelle
<service android:name=".Service2" android:process="@string/app_name" android:exported="true" android:isolatedProcess="true" />
Erklären Sie dies in Ihrem Manifest. Geben Sie Ihrem Prozess einen benutzerdefinierten Namen und machen Sie diesen Prozess isoliert und exportiert.
quelle
Das Ausführen eines Intent-Dienstes ist einfacher. Dienst beim Erstellen eines Threads in der Anwendung, der sich jedoch noch in der Anwendung befindet.
quelle
Überschreiben Sie einfach die onDestroy-Methode in Ihrer ersten sichtbaren Aktivität, z. B. nach dem Splash haben Sie eine Homepage, und während Sie von Splash zu Homepage umleiten, haben Sie Splash bereits beendet. Also auf der Startseite zerstören. und beenden Sie den Dienst in dieser Methode.
quelle