从多任务面板取消关于删除应用程序的通知

ale*_*lex 43 android android-notifications

我从我的应用程序(而不是服务)管理ONGOING通知.

当我用任务管理器用"结束"按钮终止应用程序时,通知消失.

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

我的问题是:

  • 如何捕捉此事件以清除通知?
  • 从多任务面板中删除应用程序时会发生什么?应用程序被破坏但进程仍然活着?这是正常的吗?

作为更新:

我的所有活动都使用以下方法扩展了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);
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序使用以下方法扩展了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);
}
Run Code Online (Sandbox Code Playgroud)

activities 是所有正在运行的活动的列表

这不是最简单的机制,但我需要它

我应该使用服务吗?


作为新的更新:

在我的onExit()方法中,如果我记录调试消息,知道会发生什么,如下所示:

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

少量日志出现在两个,而不是全部(例如:13/100)

所以,我明白从多任务pannel强制删除应用程序杀死应用程序而不等待关闭方法结束正确完成...但为什么不处理?!

我该如何强制正确终止?

And*_*din 44

主应用程序被杀死时杀死通知.

由于您的通知和您的应用程序在不同的线程中处理,因此通过MultitaskManager杀死您的应用程序不会终止您的通知.正如你已经正确调查杀死你的应用程序甚至不会导致onExit()回调.

那么解决方案是什么?

您可以从您的活动中启动服务.专业服务有:如果app-process因某种原因被杀,他们会自动重启.因此,您可以通过在重新启动时终止通知来重用自动重启.

第1步创建一个杀死 Simple 的服务.它只会杀死一个关于创建的通知并拥有他特殊的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

第2步:将其添加到您的清单: 将其添加到<application>标记之间的某个位置.

<service android:name="KillNotificationsService"></service>
Run Code Online (Sandbox Code Playgroud)

步骤3:在发出通知之前始终创建服务,并使用静态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);
Run Code Online (Sandbox Code Playgroud)

服务重启(1-5秒)可能需要一些时间,但最终会启动并终止通知.

  • 使用`startForeground`的@alex也不起作用。如果服务被终止,正在进行的通知将保留。需要调用stopForeground(true)来取消通知,这在服务被终止时是不可能的。 (2认同)
  • @Terranology抱歉刚刚看到您的评论:当您显示粘性通知时,服务已启动.所以起初他们俩只是生活在一起并愉快地并肩而行.但随后该应用程序意外被杀.该服务也被杀死,但通知仍在那里.现在服务重新启动(Android-Service默认行为)并终止通知.这是解决方法. (2认同)

Dee*_*pti 36

Ice Cream Sandwich(API-14)引入了将应用程序从最近的应用程序列表中滑出的功能.

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

因此,如果您正在运行任何服务,只需覆盖"onTaskRemoved()"方法即可实现您的要求.

例如:

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

或者只需编写并启动特殊服务来管理相同的服务.


Rom*_*ets 12

你应该创建类扩展应用程序和注册活动回调,当你从多任务pannel关闭应用程序时调用它们.

    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);
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

}

  • 当用户从多任务窗口中终止应用程序时,不会调用onActivityDestroyed (2认同)