Подтвердить что ты не робот

Отмена уведомления об удалении приложения из многозадачной панели

Я управляю уведомлением ONGOING из моего приложения (не из службы).

Когда я удаляю приложение из диспетчера задач с помощью кнопки "Конец", уведомление исчезает.

Когда я удаляю приложение из многозадачной панели, приложение убивается, но уведомление остается.

Мои вопросы:

  • Как уловить это событие, чтобы очистить уведомление?
  • Что происходит, когда приложение удаляется из многозадачной панели? Приложение уничтожено, но процесс остается в живых? Это нормально?

Как обновление:

Все мои действия расширяют класс MyActivity (который расширяет Activity) с помощью методов:

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

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

И мое приложение расширяет класс MyApplication (который расширяет Application) с помощью методов:

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 - список всех запущенных действий

Это не самый простой механизм, но мне он нужен

Использовать ли я службу вместо?


Как новое обновление:

В моем методе onExit(), если я отлаживаю сообщение Log, чтобы узнать, что происходит следующим образом:

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

небольшое количество журналов появляется один раз на два, не все (например: 13/100)

Итак, я понимаю, что удалить приложение из многозадачной силы pannel для уничтожения приложения, не дожидаясь завершения методов close, закончить правильно... Но почему бы не обработать?!

Как я могу принудительно завершить работу?

4b9b3361

Ответ 1

Убивать уведомления, когда основное приложение было убито.

Поскольку ваше уведомление и ваше приложение обрабатываются в разных потоках, убийство вашего приложения через MultitaskManager не приведет к уничтожению вашего уведомления. Поскольку вы уже правильно исследовали убийство вашего приложения, это даже не обязательно приведет к обратному вызову onExit().

Итак, каковы решения?

Вы можете запустить сервис из своей деятельности. Специализированные службы: они автоматически перезапускаются автоматически, если по какой-то причине был убит процесс приложения. Таким образом, вы можете повторно использовать автоматический перезапуск, убив уведомление при перезагрузке.

Шаг 1 создайте службу, которая убивает Простой. Он просто убивает уведомление о создании и имеет свой специальный Binder.

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);
    }
}

Шаг 2: добавьте его в свой манифест: Добавьте его где-нибудь между вашим <application> теги.

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

Шаг 3. Всегда создавайте службу перед тем, как пропустить уведомление, и используйте статическое уведомление.

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);

Может потребоваться некоторое время, пока служба не будет перезапущена (1-5 секунд), но в конечном итоге она начнет и убьет уведомление.

Ответ 2

Возможность прокрутки приложений из списка последних приложений представлена ​​в Ice Cream Sandwich (API-14).

С той же версией Android мы получили специальный метод "onTaskRemoved()" в "android.app.Service". Он вызывается, когда приложение удаляется из списка последних приложений.

Итак, просто переопределите метод onTaskRemoved() для достижения ваших требований, если у вас есть какой-либо сервис.

например:.

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

Или просто напишите и запустите специальную службу для управления тем же.

Ответ 3

Вы создаете класс, который расширяет Application и регистрирует обратные вызовы активности, вызов которых при закрытии приложения из многозадачной панели.

    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);
            }
        }
    });
}

}

Ответ 4

У меня такая же проблема, но мне удалось ее исправить.

Это то, что я сделал

 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;
    }


}

Если вы удерживаете кнопку "Дом" в течение 2-3 секунд, мультипанель выходит на передний план, пока наша активность находится в состоянии паузы. Поэтому сначала нужно перенести его на первый план, а затем удалить уведомление о приложении и, наконец, выйти из приложения

Функция destroyActivityCompletely удалит уведомление приложения и затем уничтожит действие. Это будет работать, если активность возбуждается из multipane и т.д.

Ответ 5

Я хотел закрыть все уведомления приложения, удалить значки значков при выходе из системы, удалить из недавнего списка приложений. Таким образом, для

Xamarin.Android

запустить службу при запуске (я создаю уведомление отсюда) как

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

где PushNotificationService - это мой service Android, внутри которого у меня есть

[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)
            {
            }
        }
    }

эта строка в OnTaskRemoved(Intent rootIntent) сделала OnTaskRemoved(Intent rootIntent) дело

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

где 0 в notificationManager.Cancel(0); это локальный идентификатор уведомления, который мы указали во время создания уведомления.

Ответ 6

Я бы предложил Вам использовать решение Deepti (fooobar.com/questions/151285/...), которое было

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

Однако он забывает упомянуть одну вещь. Если ваше подключение к сервису было выполнено с помощью вызова bindService(), onTaskRemoved() не будет запущен. Для этого вы должны подключиться к сервису с помощью вызова startService() как в примере ниже:

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

Как только вы это называете, вы сможете поймать onTaskRemoved().

Ничто не bindService() вызвать оба метода startService() и куда-то еще bindService().


Я был основан на решении службы: onTaskRemoved не вызывается, если запущен с bindService

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

Ответ 7

Вопрос старый, но он может помочь другим.

Как отмечают другие, вы можете использовать onTaskRemoved(), но он не вызывается на многих устройствах, таких как Xiaomi, Oppo и других китайских производителей, если только приложение не добавлено в белый список.

Для поддержки этих устройств служба может быть запущена на переднем плане. Таким образом, уведомление прикрепляется к услуге. Таким образом, уведомление будет очищено, когда служба будет убита (путем переключения в панель многозадачности).