Je gère une notification EN COURS depuis mon application (et non depuis un service).
Lorsque je tue une application du gestionnaire de tâches avec le bouton "Terminer", notification disparaît.
Lorsque je supprime une application du panneau multitâche, l’application est supprimée, mais notification reste.
Mes questions sont:
Comme mise à jour:
Toutes mes activités étend la classe MyActivity (qui étend Activity) avec les méthodes suivantes:
@Override protected void onCreate(Bundle state) {
super.onCreate(state);
((MyApplication) getApplication()).onActivityCreate(this, state);
}
@Override protected void onDestroy() {
super.onDestroy();
((MyApplication) getApplication()).onActivityDestroy(this);
}
Et mon application étend la classe MyApplication (qui étend Application) avec les méthodes suivantes:
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
est une liste de toutes les activités en cours
Ce n'est pas le mécanisme le plus simple mais j'en ai besoin
Devrais-je utiliser un service à la place?
En tant que nouvelle mise à jour:
Dans ma méthode onExit (), si je me connecte un message de débogage pour savoir ce qui se passe comme ceci:
public void onExit() {
for(int i = 0; i < 100; i++) {
Log.d(TAG, "onExit");
}
}
une petite quantité de log apparaît une fois sur deux, pas toutes (ex: 13/100)
Donc, je comprends que supprimer l’application de la force du panneau multitâche pour tuer l’application sans attendre que les méthodes proches se terminent correctement… Mais pourquoi ne pas traiter?
Comment puis-je forcer à terminer correctement?
Tuer des notifications lorsque l'application principale a été tué.
Étant donné que votre notification et votre application sont traitées dans différents threads, tuer votre application via MultitaskManager ne tue pas votre notification. Comme vous avez déjà correctement enquêté, tuer votre application ne provoquera même pas nécessairement un rappel onExit ().
Alors, quelles sont les solutions?
Vous pouvez démarrer un service à partir de votre activité. Les services spécialisés ont: ils se redémarrent automatiquement si le processus d'application a été tué pour une raison quelconque. Vous pouvez donc réutiliser le redémarrage automatique en supprimant la notification au redémarrage.
Étape 1 créer un service qui tue Simple. Il tue simplement une notification sur create et possède son classeur spécial.
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);
}
}
Étape 2: Ajoutez-le à votre manifeste: .__ Ajoutez-le quelque part entre vos balises <application>.
<service Android:name="KillNotificationsService"></service>
Étape 3: Créez toujours le service avant de lancer la notification et utilisez le notid statique.
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);
Le redémarrage du service peut prendre un peu de temps (1 à 5 secondes), mais il finira par démarrer et tuer la notification.
La possibilité de faire glisser des applications de la liste des applications récentes est introduite dans Sandwich à la crème glacée (API-14).
Avec la même version Android, nous avons reçu une méthode spéciale "onTaskRemoved ()" dans "Android.app.Service". Il est appelé lorsque l'application est supprimée de la liste des applications récentes.
Donc, substituez simplement la méthode "onTaskRemoved ()" pour répondre à vos exigences si un service est en cours d'exécution.
Par exemple.:
@Override
public void onTaskRemoved(Intent rootIntent) {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(NOTIFICATION_ID);
}
Ou tout simplement écrire et démarrer un service spécial pour gérer les mêmes.
Vous devez créer la classe étend l'application et enregistrer les rappels d'activité, dont l'appel lorsque vous fermez l'application à partir du panneau multitâche.
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);
}
}
});
}
}
J'ai le même problème moi-même mais j'ai réussi à le résoudre
C'est ce que j'ai fait
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;
}
}
Si vous maintenez le bouton d'accueil enfoncé pendant 2 à 3 secondes, le multi-volet passe au premier plan alors que notre activité est actuellement en pause. Par conséquent, nous devons d'abord l'afficher au premier plan, puis supprimer la notification de l'application et enfin quitter l'application.
la fonction destroyActivityCompletely supprimera la notification de l'application, puis supprimera l'activité. Cela fonctionnera si l’activité est excitée à partir de plusieurs fenêtres, etc.
Je voulais fermer toutes les notifications de mon application, supprimer les icônes de badge sur Déconnexion, supprimées de la liste des applications récentes. donc pour
Xamarin.Android
démarrer le service à l'activité du lanceur (je crée une notification à partir d'ici) en tant que
Intent intent = new Intent(this, typeof(PushNotificationService));
this.StartService(intent);
où PushNotificationService
est mon Android service
à l'intérieur duquel j'ai
[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)
{
}
}
}
cette ligne dans OnTaskRemoved(Intent rootIntent)
a fait l'affaire
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Cancel(0);
où 0 dans notificationManager.Cancel(0);
est l'id de notifcation local que nous avons mis au moment de la notification de construction.