2016-06-02 6 views
1

Meine Android-Audioplayer-App richtet während des Abspielens einen gebundenen Dienst ein, um sicherzustellen, dass sie vom System nicht beendet wird. Die App verwendet den System Media Player. Der Dienst erstellt ein Benachrichtigungssymbol in der Systemleiste.Wie kann ich feststellen, ob meine App vom App-Switcher kopiert wurde?

Wenn ich die App aus der Liste der zuletzt verwendeten Apps wische, wird die App deaktiviert. ABER: Der Media Player spielt weiter und die Benachrichtigung bleibt in der Systemleiste.

Wenn ich die Benachrichtigung oder das App-Symbol wähle, wird eine neue Instanz der App gestartet, die laufende Instanz ist nicht erreichbar. Sie kann nur gestoppt werden, indem Sie in den Systemeinstellungen für Apps Force-Stopp auswählen. Wenn ich die App nicht von der Liste wische, komme ich immer wieder auf die spielende Instanz zurück.

Wenn nur meine App erkennen könnte, wenn sie von der Liste geklaut wird, könnte sie alles korrekt stoppen. OnDestroy() wird jedoch nicht garantiert aufgerufen - und wird nicht z. in CM12. onStop() oder onPause() ist für mich nicht vadlid, weil das Audio nicht aufhören soll, wenn die App gerade in den Hintergrund geht.

Also, wie ist es möglich zu erkennen, wenn die App aus der Liste geklaut wird?

Dies ist der Service. Kann hier etwas gemacht werden?

public class myService extends Service { 
... 

@Override 
public void onCreate() { 
    mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); 
    showNotification(); 
} 

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

@Override 
public void onDestroy() { 
    mNM.cancel(NOTIFICATION); 
    stopForeground(true); 
} 

@Override 
public IBinder onBind(Intent intent) { 
    return mBinder; 
} 
... 

private void showNotification() { 
    Notification notification = new Notification(R.drawable.icon, "Hello", 0); 
    Intent intent = new Intent(this, myActivity.class); 
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
    PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intent, 0); 
    notification.setLatestEventInfo(this, "AppName", "Hello", pendIntent); 
    notification.flags |= Notification.FLAG_NO_CLEAR; 
    startForeground(FOREGROUNDID, notification); 
    } 
} 

Dies ist, wie mein Dienst gebunden ist:

für jede Hilfe
private static ServiceConnection mConnection = new ServiceConnection() { 
    public void onServiceConnected(ComponentName className, IBinder service) { 
      // Not used 
    } 

    public void onServiceDisconnected(ComponentName className) { 
      // Not used 
    } 
}; 

private static void doBindService() { 
    context.bindService(
     new Intent(context, myService.class), 
     mConnection, Context.BIND_AUTO_CREATE); 
} 

Dank.

+0

Android kann mehrere Instanzen der gleichen Anwendung nicht starten. Was meinen Sie mit "die laufende Instanz ist nicht erreichbar"? Ich sehe den Media Player nicht im Dienst. Erwarten Sie, dass die _Aktivität_ nicht zerstört wird? – StenSoft

+0

Ich erwarte, dass die Aktivität, der Dienst und der Media Player zerstört werden. Wenn der Media Player weiter läuft und das Symbol in der Systemleiste bleibt, wird nur die Aktivität durch Wischen gelöscht, aber nicht der Dienst. So wurde "laufende Instanz" in der Tat falsch beschrieben. Der Media Player wird innerhalb der Aktivität behandelt, der Service ist nur verpflichtet, zu verhindern, dass die App vom System getötet wird und das Symbol zeigt. Dies ist ein gültiges Verfahren, wie ich irgendwo gelesen habe. – Mapeman

+0

Ja, es ist ein gültiges Verfahren. In diesem Fall sollte sich der Media Player-Controller jedoch im Dienst befinden, damit die neu gestartete Aktivität eine Verbindung zu ihm herstellen und die laufende Wiedergabe steuern kann. – StenSoft

Antwort

0

Die Service hat eine onTaskRemoved() Methode, die in diesem Szenario ausgelöst wird. Sie können den Dienst beenden es:

/** 
* This is called if the service is currently running and the user has 
* removed a task that comes from the service's application. If you have 
* set ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK} 
* then you will not receive this callback; instead, the service will simply 
* be stopped. 
* 
* @param rootIntent The original root Intent that was used to launch 
*     the task that is being removed. 
*/ 
@Override 
public void onTaskRemoved(Intent rootIntent) { 
    super.onTaskRemoved(rootIntent); 

    stopSelf(); 
} 

Und denken Sie daran, die Service vom Activity in onStop() oder onDestroy() zu entbinden. (Was auch immer im Einklang mit Ihrer Bindungsstrategie steht.)

+0

Es klingt komisch, aber ohne irgendwelche Änderungen zu machen, funktioniert es wie erwartet. Ich habe versucht, aufTaskRemoved hinzuzufügen, wie Sie vorgeschlagen haben, aber einen @Override-Fehler erhalten. Ich habe auch den "android: stopWithTask" Schalter für den Dienst im Manifest ausprobiert, der auch für meine 2.2 Umgebung nicht funktionierte. Jetzt sehe ich keinen Unterschied zur vorherigen Version des Codes, aber das Wischen stoppt den Media Player und den Dienst. – Mapeman