Alle Antworten scheinen richtig zu sein, also werde ich weitermachen und eine vollständige geben hier Antwort geben.
Erstens ist der einfachste Weg, das zu tun, was Sie versuchen, eine Sendung in Android zu starten, wenn die App manuell beendet wird, und eine benutzerdefinierte zu definierenBroadcastReceiver
zu , um anschließend einen Neustart des Dienstes auszulösen.
Lassen Sie uns nun in den Code springen.
Erstellen Sie Ihren Service in YourService.java
Beachten Sie die onCreate()
Methode, bei der wir einen Vordergrunddienst für Build-Versionen, die größer als Android Oreo sind, anders starten . Dies liegt an den kürzlich eingeführten strengen Benachrichtigungsrichtlinien, bei denen wir unseren eigenen Benachrichtigungskanal definieren müssen , um sie korrekt anzuzeigen.
Die this.sendBroadcast(broadcastIntent);
in der onDestroy()
Methode ist die Anweisung, die asynchron eine Sendung mit dem Aktionsnamen sendet "restartservice"
. Wir werden dies später als Auslöser verwenden, um unseren Dienst neu zu starten.
Hier haben wir eine einfache Timer - Task definiert, der druckt einen Zählerwert jedes 1 Sekunde in die Log
während selbst druckt es jedes Mal erhöht wird .
public class YourService extends Service {
public int counter=0;
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
}
@RequiresApi(Build.VERSION_CODES.O)
private void startMyOwnForeground()
{
String NOTIFICATION_CHANNEL_ID = "example.permanence";
String channelName = "Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
stoptimertask();
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, Restarter.class);
this.sendBroadcast(broadcastIntent);
}
private Timer timer;
private TimerTask timerTask;
public void startTimer() {
timer = new Timer();
timerTask = new TimerTask() {
public void run() {
Log.i("Count", "========= "+ (counter++));
}
};
timer.schedule(timerTask, 1000, 1000);
}
public void stoptimertask() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Erstellen Sie einen Broadcast-Empfänger, um auf Ihre benutzerdefinierten Broadcasts in zu antworten Restarter.java
Die Sendung mit dem Aktionsnamen, "restartservice"
den Sie gerade definiert haben, YourService.java
soll nun eine Methode auslösen, mit der Ihr Dienst neu gestartet wird . Dies geschieht mitBroadcastReceiver
Android.
Wir überschreiben die integrierte onRecieve()
Methode BroadcastReceiver
, um die Anweisung hinzuzufügen, mit der der Dienst neu gestartet wird. Das startService()
wird nicht wie vorgesehen in und über Android Oreo 8.1, als strenge Hintergrund Politik wird in Kürze den Dienst nach dem Neustart beenden , sobald die App getötet wird. Daher verwenden wir die startForegroundService()
für höhere Versionen und zeigen eine fortlaufende Benachrichtigung an, um den Dienst am Laufen zu halten.
public class Restarter extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("Broadcast Listened", "Service tried to stop");
Toast.makeText(context, "Service restarted", Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context, YourService.class));
} else {
context.startService(new Intent(context, YourService.class));
}
}
}
Definieren Sie MainActivity.java
, dass Sie den Dienst beim Start der App aufrufen möchten.
Hier definieren wir eine separate isMyServiceRunning()
Methode, um den aktuellen Status des Hintergrunddienstes zu überprüfen. Wenn der Dienst nicht ausgeführt wird, starten wir ihn mitstartService()
.
Da die App bereits im Vordergrund ausgeführt wird, müssen wir den Dienst nicht als Vordergrunddienst starten , um zu verhindern, dass er selbst beendet wird.
Beachten Sie, dass onDestroy()
wir in dediziert aufrufen stopService()
, damit unsere überschriebene Methode aufgerufen wird. Wenn dies nicht getan worden wäre, hätte der Dienst automatisch beendet , nachdem die App beendet wurde, ohne unsere geänderte onDestroy()
Methode in aufzurufenYourService.java
public class MainActivity extends AppCompatActivity {
Intent mServiceIntent;
private YourService mYourService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mYourService = new YourService();
mServiceIntent = new Intent(this, mYourService.getClass());
if (!isMyServiceRunning(mYourService.getClass())) {
startService(mServiceIntent);
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Log.i ("Service status", "Running");
return true;
}
}
Log.i ("Service status", "Not running");
return false;
}
@Override
protected void onDestroy() {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, Restarter.class);
this.sendBroadcast(broadcastIntent);
super.onDestroy();
}
}
Registrieren Sie sie schließlich in Ihrem AndroidManifest.xml
Alle oben genannten drei Klassen müssen separat angemeldet werden AndroidManifest.xml
.
Beachten Sie, dass wir eine Definition intent-filter
mit dem Aktionsnamen wie , "restartservice"
wo der Restarter.java
als registriert ist receiver
. Dies stellt sicher, dass unser Benutzerdefiniert BroadcastReciever
aufgerufen wird, wenn das System auf eine Sendung mit dem angegebenen Aktionsnamen stößt .
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver
android:name="Restarter"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="restartservice" />
</intent-filter>
</receiver>
<activity android:name="MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="YourService"
android:enabled="true" >
</service>
</application>
Dies sollte Ihren Dienst jetzt erneut starten, wenn die App vom Task-Manager beendet wurde. Dieser Dienst wird im Hintergrund ausgeführt, solange der Benutzer Force Stop
die App nicht über die Anwendungseinstellungen verwendet .
UPDATE: Ein großes Lob an Dr. Jacky für den Hinweis. Der oben erwähnte Weg funktioniert nur, wenn der onDestroy()
Dienst aufgerufen wird, was zu bestimmten Zeiten, die mir nicht bekannt waren , möglicherweise nicht der Fall ist. Vielen Dank.