49

(サービスからではなく) アプリケーションからの進行中の通知を管理します。

「終了」ボタンでタスクマネージャーからアプリケーションを終了すると、通知が消えます。

マルチタスク パネルからアプリケーションを削除すると、アプリケーションは強制終了されますが、通知は残ります。

私の質問は次のとおりです。

  • このイベントをキャッチして通知をクリアする方法は?
  • アプリケーションがマルチタスク パネルから削除されるとどうなりますか? アプリケーションは破棄されますが、プロセスは生き続けますか? それは正常ですか?

アップデートとして:

私のすべてのアクティビティは、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 クラス (アプリケーションを拡張する) をメソッドで拡張します:

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() メソッドで、次のように何が起こるかを知るためにデバッグ メッセージをログに記録すると:

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

すべてではなく、少量のログが 2 回に 1 回表示されます (例: 13/100)

したがって、マルチタスクパネルからアプリケーションを削除すると、クローズメソッドが適切に終了するのを待たずにアプリケーションを強制終了することを理解しています...しかし、なぜ処理しないのですか?!

どうすれば適切に強制終了できますか?

4

8 に答える 8

46

メインアプリが強制終了されたときの通知の強制終了。

通知とアプリは異なるスレッドで処理されるため、MultitaskManager を介してアプリを強制終了しても、通知は強制終了されません。すでに正しく調査したように、アプリを強制終了しても必ずしも onExit() コールバックが発生することはありません。

それで、解決策は何ですか?

アクティビティからサービスを開始できます。特殊なサービスには次のものがあります。アプリプロセスが何らかの理由で強制終了された場合、それらは自動的に再起動します。したがって、再起動時に通知を強制終了することで、自動再起動を再利用できます。

ステップ 1シンプルなものを殺すサービスを作成します。作成時に通知を殺すだけで、彼の特別なバインダーがあります。

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: 通知を起動する前に常にサービスを作成し、静的な 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 秒) が、最終的には開始され、通知が強制終了されます。

于 2013-01-17T08:20:40.927 に答える
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);
}

または、同じものを管理するための特別なサービスを作成して開始するだけです。

于 2015-02-18T13:06:48.383 に答える
12

アプリケーションを拡張するクラスを作成し、マルチタスク パネルからアプリケーションを閉じるときに呼び出されるアクティビティ コールバックを登録する必要があります。

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

}

于 2013-01-25T09:12:29.307 に答える
0

私自身も同じ問題を抱えていますが、なんとか修正できました

これは私がしたことです

 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 秒間押し続けると、現在アクティビティが一時停止状態にあるときにマルチペインが前面に表示されます。したがって、最初にフォアグラウンドに移動してからアプリの通知を削除し、最後にアプリを終了する必要があります

destroyActivityComplety 関数は、アプリの通知を削除してから、アクティビティを強制終了します。これは、アクティビティがマルチペインなどから興奮している場合に機能します。

于 2015-11-26T00:32:08.840 に答える