取消在多任务面板中删除应用程序的通知

我从我的应用程序(而不是服务)pipe理一个正在进行的通知。

当我用“结束”button从任务pipe理器中终止应用程序时, 通知消失

当我从多任务pannel删除应用程序,应用程序被杀害,但通知仍然存在

我的问题是:

  • 如何抓住这个事件来清除通知?
  • 当应用程序从多任务pannel删除时会发生什么? 应用程序被破坏,但进程保持活着? 这是正常的吗?

作为更新:

我所有的活动扩展了MyActivity类(它扩展了活动)与方法:

@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类(扩展应用程序)的方法:

 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()方法中,如果我loggingdebugging消息,知道发生这样的事情:

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

less量的日志出现一次,而不是全部(例如:13/100)

所以,我明白,从多任务pannel力删除应用程序杀死应用程序而无需等待closures方法结束完成正确…但为什么不处理?

我如何强制终止正确?

杀死主应用程序时的通知。

由于您的通知和您的应用程序在不同的线程处理通过MultitaskManager杀死您的应用程序不会杀死您的通知。 正如你已经正确调查,你的应用程序甚至不会无意中导致onExit()callback。

那么解决scheme是什么?

你可以从你的活动开始一个服务。 专业服务有:自动重启自己,如果应用程序进程已被杀死出于某种原因。 所以你可以通过重新启动通知来重新使用自动重启。

第1步创build一个杀死简单的服务 。 它只是杀死一个创build通知,并有他的特殊粘结剂。

 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> 

第三步:在启动通知之前始终创build服务,并使用静态的notificationID。

 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秒)可能需要一点时间,但最终会启动并终止通知。

在冰淇淋三明治(API-14)中引入了将应用程序从最近的应用程序列表中滑出的function。

使用相同的Android版本,我们在“android.app.Service”中收到了一个特殊的方法“onTaskRemoved()”。 当应用程序从最近的应用程序列表中删除时,它被调用。

因此,只要覆盖“onTaskRemoved()”方法来实现您的要求,如果您有任何服务运行。

例如:

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

或者简单地写&开始特别服务pipe理相同。

你应该创build类扩展应用程序和注册活动callback,当你从多任务范围closures应用程序的调用。

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

}

我自己也有同样的问题,但我设法修复它

这就是我所做的

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

如果您按住home键2-3秒,那么当我们的活动目前处于暂停状态时,多面板会到达前台。 因此,我们需要先把它带到前台,然后删除应用程序通知,最后退出应用程序

destroyActivityCompletely函数将删除应用程序通知,然后杀死该活动。 如果活动是从多面板等激发的,这将工作。