it-swarm.com.de

Benachrichtigung beim Entfernen der Anwendung aus dem Multitask-Fenster abbrechen

Ich verwalte eineLAUFENDEBenachrichtigung von meiner Anwendung (nicht von einem Dienst).

Wenn ich die Anwendung vom Task-Manager mit der Schaltfläche "Beenden" abschalte, verschwindet Benachrichtigung .

Wenn ich die Anwendung aus dem Multitask-Bereich entferne, wird die Anwendung abgebrochen, aber Benachrichtigung bleibt erhalten .

Meine Fragen sind:

  • Wie kann man dieses Ereignis abrufen, um die Benachrichtigung zu löschen?
  • Was passiert, wenn die Anwendung aus dem Multitask-Fenster entfernt wird? Die Anwendung wird zerstört, aber der Prozess bleibt am Leben? Es ist normal?

Als Update:

Alle meine Aktivitäten erweitern die MyActivity-Klasse (die Activity erweitert) um Methoden:

@Override protected void onCreate(Bundle state) {
    super.onCreate(state);
    ((MyApplication) getApplication()).onActivityCreate(this, state);
}

@Override protected void onDestroy() {
    super.onDestroy();
    ((MyApplication) getApplication()).onActivityDestroy(this);
}

Und meine Anwendung erweitert die MyApplication-Klasse (die die Anwendung erweitert) um Methoden:

private List<Activity> activities = new ArrayList<Activity>();

protected final void onActivityCreate(Activity activity, Bundle state) {
    if(activities.isEmpty() && state == null) {
        onStart();
    }
    activities.add(activity);
}

protected final void onActivityDestroy(Activity activity) {
    activities.remove(activity);
    if(activities.isEmpty() && activity.isFinishing()) {
        onExit();
    }
}

protected void onStart() {
    // some code
}

protected void onExit() {
    // some code
    notificationManager.cancel(NOTIFICATION_ID);
}

activities ist eine Liste aller laufenden Aktivitäten

Es ist nicht der einfachste Mechanismus, aber ich brauche ihn

Soll ich stattdessen einen Dienst nutzen?


Als neues Update:

Wenn ich in meiner onExit () -Methode eine Debug-Nachricht protokolliere, um zu wissen, was passiert, so:

public void onExit() {
    for(int i = 0; i < 100; i++) {
        Log.d(TAG, "onExit");
    }
}

eine kleine Menge Protokoll erscheint einmal auf zwei, nicht auf allen (Beispiel: 13/100)

Also, ich verstehe, dass die Anwendung aus dem Multitask-Bereich entfernt wird, um die Anwendung zu beenden, ohne zu warten, dass die Schließen-Methoden ordnungsgemäß beendet werden ... Aber warum nicht verarbeiten?

Wie kann ich eine ordentliche Beendigung erzwingen?

40
alex

Benachrichtigungen abbrechen, wenn die Hauptanwendung beendet wurde.

Da Ihre Benachrichtigung und Ihre App in verschiedenen Threads verarbeitet werden, wird das Beenden Ihrer App über MultitaskManager Ihre Benachrichtigung nicht beenden. Wie Sie bereits richtig untersucht haben, führt das Töten Ihrer App nicht unbedingt zu einem Aufruf von onExit ().

Was sind die Lösungen?

Sie können einen Dienst aus Ihrer Aktivität starten. Eine Spezialität hat Folgendes: Sie starten sich automatisch neu, wenn der App-Prozess aus irgendeinem Grund beendet wurde. So können Sie den automatischen Neustart wiederverwenden, indem Sie die Benachrichtigung beim Neustart abbrechen.

Schritt 1: Erstellen Sie einen Dienst, der .__ abtötet. Einfach. Es zerstört nur eine Benachrichtigung beim Erstellen und hat seine spezielle Sammelmappe.

public class KillNotificationsService extends Service {

    public class KillBinder extends Binder {
        public final Service service;

        public KillBinder(Service service) {
            this.service = service;
        }

    }

    public static int NOTIFICATION_ID = 666;
    private NotificationManager mNM;
    private final IBinder mBinder = new KillBinder(this);

    @Override
    public IBinder onBind(Intent intent) {
            return mBinder;
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
            return Service.START_STICKY;
    }
    @Override
    public void onCreate() {
            mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            mNM.cancel(NOTIFICATION_ID);
    }
}

Schritt2: Fügen Sie es Ihrem Manifest hinzu: Fügen Sie es irgendwo zwischen Ihren <application> -Tags ein.

<service Android:name="KillNotificationsService"></service>

Schritt 3: Erstellen Sie immer den Dienst, bevor Sie die Benachrichtigung auslösen, und verwenden Sie die statische Benachrichtigungs-ID.

ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className,
            IBinder binder) {
        ((KillBinder) binder).service.startService(new Intent(
                MainActivity.this, KillNotificationsService.class));
        Notification notification = new Notification(
                R.drawable.ic_launcher, "Text",
                System.currentTimeMillis());
        Intent notificationIntent = new Intent(MainActivity.this,
                Place.class);
        PendingIntent contentIntent = PendingIntent.getActivity(
                MainActivity.this, 0, notificationIntent, 0);
        notification.setLatestEventInfo(getApplicationContext(),
                "Text", "Text", contentIntent);
        NotificationManager mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mNM.notify(KillNotificationsService.NOTIFICATION_ID,
                notification);
    }

    public void onServiceDisconnected(ComponentName className) {
    }

};
bindService(new Intent(MainActivity.this,
        KillNotificationsService.class), mConnection,
        Context.BIND_AUTO_CREATE);

Es kann etwas dauern, bis der Dienst neu gestartet wird (1-5 Sek.), Aber es wird eventuell gestartet und die Benachrichtigung beendet.

40
AndacAydin

Die Möglichkeit, Apps aus der Liste der zuletzt verwendeten Apps herauszuziehen, wurde in Ice Cream Sandwich (API-14) eingeführt.

Mit derselben Android-Version haben wir in "Android.app.Service" eine spezielle Methode "onTaskRemoved ()" erhalten. Sie wird aufgerufen, wenn die App aus der Liste der letzten Apps entfernt wird.

Überschreiben Sie einfach die "onTaskRemoved ()" -Methode, um Ihre Anforderungen zu erfüllen, wenn ein Dienst ausgeführt wird.

Z.B.:

@Override
public void onTaskRemoved(Intent rootIntent) {
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.cancel(NOTIFICATION_ID);
}

Oder schreiben Sie einfach einen speziellen Service, um das gleiche zu verwalten.

33
Deepti

Sie sollten eine Klasse erstellen, die die Anwendung erweitert und Aktivitäts-Callbacks registriert. 

    public class MyApplication extends Application {



@Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle bundle) {
            }

        @Override
        public void onActivityStarted(Activity activity) {
        }

        @Override
        public void onActivityResumed(Activity activity) {
        }

        @Override
        public void onActivityPaused(Activity activity) {
        }

        @Override
        public void onActivityStopped(Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
            if (/*check is all your activities onStop state*/) {
                NotificationManager mNM = (NotificationManager)              getSystemService(NOTIFICATION_SERVICE);
                mNM.cancel(R.id.key_notification_id);
            }
        }
    });
}

}

12

Ich würde vorschlagen, dass Sie Deepti-Lösung ( https://stackoverflow.com/a/28584405/61967 ) verwenden, die war

@Override
public void onTaskRemoved(Intent rootIntent) {
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.cancel(NOTIFICATION_ID);
}

Er hat jedoch vergessen, eine Sache zu erwähnen. Wenn Ihre Verbindung zum Dienst per Anruf hergestellt wurde, wird bindService(), onTaskRemoved() nicht ausgelöst. Um dies zu handhaben, müssen Sie eine Verbindung mit dem Dienst herstellen, indem Sie startService() wie im folgenden Beispiel aufrufen:

startService(new Intent(context, CustomerService.class));

Sobald Sie es aufrufen, können Sie onTaskRemoved() fangen.

Beiden Methoden startService() und irgendwo weiteren bindService() steht nichts im Wege.


Ich basierte auf Lösung Service: onTaskRemoved nicht aufgerufen, wenn mit bindService gestartet

startService(new Intent(context, CustomerService.class)); // this will allow catch onTaskRemoved
// ...
bindService(new Intent(context, CustomerService.class),
                        mConnection, Context.BIND_AUTO_CREATE);
0
deadfish

Ich habe selbst das gleiche Problem, aber es ist mir gelungen, es zu beheben

Das habe ich getan

 public class Sample extends Activity {

 private static final String APP_NOTIFICATION_TAG = "sample";
 private static final int NOTIFICATION_ID = 24;
 private NotificationManager notificationManager;
 private Notification appNotification;

 private AppFinishedExecutingListener appFinishedExecutingListener;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // set the layout and other stuff goes here
    appFinishedExecutingListener.execute(this);
    new Thread() {
        @Override
        public void run() {
            try {
                appFinishedExecutingListener.get();
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        destroyActivityComponent();
                    }
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }.start();

    setupNotification();
 }

 /*
 * Setup this app 
 */
private void setupNotification() {

    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
    // make sure when the user click the notification, this will make sure it will resume the app
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

    // define the action should be performed if the user click the notification i.e. resume our app activity
    PendingIntent pIntent = PendingIntent.getActivity(getApplicationContext(), (int)System.currentTimeMillis(), intent, 0);

    // setup the look for this app on  a notification panel
    appNotification  = new NotificationCompat.Builder(this)
            .setContentTitle(getString(R.string.app_name))
            .setContentText("Currently listening to kiribati radio")
            .setSmallIcon(R.drawable.ic_notification_logo)
            .setContentIntent(pIntent)
            .setAutoCancel(true)
            .setOngoing(true).build()
            ;

    notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

}

/*
 * Will add app notification when this activity is paused so the user can   
 * quickly access it or resume this activity easily
 */
private void addAppToNotificationP() {
    notificationManager.notify(APP_NOTIFICATION_TAG, NOTIFICATION_ID,   appNotification);
}

/*
 * This will remove the notification if this activity is resumed
 */
private void removeAppFromNotificationP() {
    notificationManager.cancel(APP_NOTIFICATION_TAG,NOTIFICATION_ID);
}

@Override
protected void onPause() {
    super.onPause();
    addAppToNotificationP();
}

@Override
protected void onResume() {
    super.onResume();
    removeAppFromNotificationP();

}

private void destroyActivityCompletely() {
    onResume();
    finish();
}



}

public class AppFinishedExecutingListener extends AsyncTask<MainActivity, Void, Boolean> {

    private MainActivity main_activity;

    @Override
    protected Boolean doInBackground(MainActivity... params) {
        main_activity = params[0];

        while(!main_activity.isFinishing()) {
            try {
                Thread.sleep(100);
                //Log.i(main_activity.TAG,"listening");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //main_activity.finish();


        return true;
    }


}

Wenn Sie die Home-Taste für 2-3 Sekunden gedrückt halten, tritt der Multipane in den Vordergrund, während sich unsere Aktivität gerade im Pause-Zustand befindet. Deshalb müssen wir es zuerst in den Vordergrund bringen, dann die App-Benachrichtigung entfernen und die App schließlich beenden

die Funktion destroyActivityCompletely entfernt die App-Benachrichtigung und beendet dann die Aktivität. Dies funktioniert, wenn die Aktivität von Multipane usw. angeregt wird.

0

Die Frage ist alt, kann aber anderen helfen.

Wie bereits von anderen erwähnt, können Sie onTaskRemoved () verwenden, aber es wird auf vielen Geräten wie Xiaomi, Oppo und anderen chinesischen Herstellern nicht aufgerufen, es sei denn, die App wurde zur Whitelist hinzugefügt.

Um auch diese Geräte zu unterstützen, kann der Service im Vordergrund gestartet werden. Auf diese Weise wird eine Benachrichtigung an den Dienst angehängt. Die Benachrichtigung wird also gelöscht, wenn der Dienst beendet wird (durch Wischen im Multitask-Bereich).

0
rohitverma

Ich wollte alle App-Benachrichtigungen schließen, Badge-Symbole beim Abmelden entfernen und aus der Liste der letzten Apps entfernen. so für 

Xamarin.Android

dienst am Startprogramm starten (Ich erstelle hier eine Benachrichtigung) als 

Intent intent = new Intent(this, typeof(PushNotificationService));
this.StartService(intent);

wobei PushNotificationService mein Android service ist, in dem ich bin 

[Service]
    public class PushNotificationService : Service
        {
            public override IBinder OnBind(Intent intent)
            {
                return null;
            }

        public override void OnCreate()
        {
            base.OnCreate();
        }
        public override void OnTaskRemoved(Intent rootIntent)
        {
            try
            {
                var notificationManager = (NotificationManager)GetSystemService(NotificationService);
                notificationManager.Cancel(0);
                ME.Leolin.Shortcutbadger.ShortcutBadger.RemoveCount(Application.Context);
            }
            catch (System.Exception ex)
            {
            }
        }
    }

diese Zeile in OnTaskRemoved(Intent rootIntent) hat den Trick ausgeführt 

 var notificationManager = (NotificationManager)GetSystemService(NotificationService);
                notificationManager.Cancel(0);

dabei ist 0 in notificationManager.Cancel(0); die lokale Benachrichtigungs-ID, die wir zum Zeitpunkt der Erstellung der Benachrichtigung setzen. 

0
Annu