質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.52%

Android Lolipop(5.0)以上の時のNotificationのAutoCancelについて

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 3,047

ykiyota

score 19

お世話になっております。

Push通知を受信した後、通知センターからのタップでアプリ起動の後、通知センターから該当通知を削除したいのですが、
Lolipop(5.0)以上だとNotificationのAutoCancelが動かずに困っております。

また、AutoCancelが効かなくても個別に削除できればと思い、
MainActivity側で削除しようとしたのですが削除できませんでした。

どのようにすれば通知の削除ができるのでしょうか?
情報をお持ちの方がいらっしゃいましたら、ご教示いただけますと有難いです。
よろしくお願いいたします。

以下、環境及びGCMIntentServiceとMainActivityの一部抜粋したものです。

環境:
Android Studio 1.5.1
buildToolsVersion "23.0.2"

■■■GCMIntentService

public class GcmIntentService extends IntentService {
    private static final String TAG = "GcmIntentService";
    private NotificationManager mNotificationManager;

    public GcmIntentService() {
        super("GcmIntentService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        String messageType = gcm.getMessageType(intent);

        if (!extras.isEmpty()) {
            if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
                Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
                Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                Log.d(TAG,"messageType: " + messageType + ",body:" + extras.toString());

                String mess = extras.getString("message");
                String push_type_str = extras.getString("type");
                int push_type = 0;
                push_type = Integer.parseInt(push_type_str);

                //通知バーに表示
                sendNotification(mess, push_type);

            }
        }
        GcmBroadcastReceiver.completeWakefulIntent(intent);
    }

    private void sendNotification(String msg, int push_type) {
        mNotificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);

        Intent main_intent = new Intent(this, MainActivity.class);

        // Push通知からの起動後に利用するパラメータ設定
        Bundle bundle = new Bundle();
        bundle.putString("message", msg);
        bundle.putInt("push_type", push_type);

        main_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        main_intent.putExtras(bundle);
        PendingIntent contentIntent;

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            contentIntent = PendingIntent.getActivity(this, push_type, main_intent, PendingIntent.FLAG_CANCEL_CURRENT);
        }
        else {
            TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(this);

            taskStackBuilder.addNextIntent(main_intent);
            contentIntent = taskStackBuilder.getPendingIntent(push_type, PendingIntent.FLAG_CANCEL_CURRENT);
        }

        int notification_id = push_type;

        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(this)
                        .setWhen(System.currentTimeMillis())
                        .setContentTitle("title")
                        .setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
                        .setContentText(msg);

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            mBuilder.setSmallIcon(R.drawable.app_icon); 
        }
        else {
            mBuilder.setSmallIcon(R.drawable.push_small_icon); // 白ベース画像
        }

        mBuilder.setContentIntent(contentIntent);
        mBuilder.setAutoCancel(true);
        // push_typeは3種類のタイプがあり、push_typeによりPush起動後の処理を変更する。
       //  push_type毎にpush通知を受けられるようにする
        mNotificationManager.notify(notification_id, mBuilder.build());
    }
}

■■■ MainActivity

public class MainActivity extends Activity {
       private static final String TAG = "MainActivity";
    private NotificationManager mNotificationManager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        Bundle bundle = getIntent().getExtras();
        if (bundle == null) {
            int flag = getIntent().getFlags();
            if ((flag & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
                finish();
                return;
            }
        }
        else {
            NotificationManager mNotificationManager = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);

            int push_type = bundle.getInt("push_type", -1);
            if (push_type != -1) {
                mNotificationManager.cancel(push_type); // ★★★通知が消えない!!!★★★ ※cancelAll()にしても消えない
            }
        }

/// いろいろな処理

    }
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Odacchi

    2016/03/18 18:20 編集

    ソースコードが見づらいため、下記のように囲っていただけないでしょうか?

    ```Java
    (ここにコードを書く)
    ```

    キャンセル

回答 2

+1

自己レスです。
とりあえず解決しました。

色々変更したので、どれが直接原因かがわかりませんが、
5.0になってからAutoCancelの処理を利かすためのタイミングが厳しくなったような印象です。
以下にやったことと、一部ソースの記載します。

・GCM2.0→GCM3.0
・SDK 23.2.0 →23.2.1
・スプラッシュ表示処理変更
修正前:MainActivityを非同期で1秒後に閉じて、DetailActivityをStartActivityする。 ←この処理があると通知が消えなかった…
修正後:Pushを受けた直後はBundleをそのままDetailActivityに渡してMainActivityはそのままFinish、DetailActivityの最初の処理でSplash表示を行なう。

■■■ MyGcmListenerService.java

public class MyGcmListenerService extends GcmListenerService {

    private static final String TAG = "MyGcmListenerService";
    public static final int UNKNOWN_NOTIFICATION_ID = 999;
    private static NotificationManager mNotificationManager;

    enum NotificationType {
        NOTIFICATION_TYPE_SINGLE,
        NOTIFICATION_TYPE_MULTI,
    }

    private  NotificationType notificationType = NotificationType.NOTIFICATION_TYPE_MULTI;

    @Override
    public void onMessageReceived(String from, Bundle data) {

        String mess = data.getString("message");
        String push_type_str = data.getString("push_type");
        int push_type = 0;
        if (MCSchemeUtility.sharedInstance().isCheck(push_type_str) == true) {
            push_type = Integer.parseInt(push_type_str);
        }

        //通知バーに表示
        sendNotification(mess, push_type);

    }


    private void sendNotification(String message, int push_type) {

        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        // Push通知からの起動後に利用するパラメータ設定
        Bundle bundle = new Bundle();
        bundle.putString("message", message);
        bundle.putInt("push_type", push_type);

        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.putExtras(bundle);

        PendingIntent pendingIntent;
        int icon;
        int noti_id;

        if (push_type < 0) {
            push_type = UNKNOWN_NOTIFICATION_ID;
        }

        if (notificationType == NotificationType.NOTIFICATION_TYPE_SINGLE) {
            // 1種類通知モード
            noti_id = 0;
        }
        else {
            // 複数通知モード
            noti_id = push_type;
        }

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            // Lollipop未満の時
            pendingIntent = PendingIntent.getActivity(this, noti_id /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);

            icon = R.drawable.app_icon;
        }
        else {
            // Lollipop以上の時
            TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(this);
            taskStackBuilder.addParentStack(MainActivity.class);
            taskStackBuilder.addNextIntent(intent);
            pendingIntent = taskStackBuilder.getPendingIntent(noti_id, PendingIntent.FLAG_UPDATE_CURRENT);

            icon = R.drawable.push_small_icon; // 白ベースアイコン
        }

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setContentTitle("タイトル")
                .setStyle(new NotificationCompat.BigTextStyle().bigText(message))
                .setSmallIcon(icon)
                .setAutoCancel(true)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        mNotificationManager.notify(noti_id /* ID of notification */, mBuilder.build());
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

AndroidのNotificationは、5.0以降大きく変わっていて、修正が大変だった記憶がたしかにあります。
ただ、1年以上前の記憶なので、即答ができませんが、参考になれば幸いです。

英語ですが、こちらに全く同様の現象が報告されていますね。
5.0.2で、正常に動作確認ができているソースコードも上がっているので、ヒントになるかもしれません。

また、Android5.0のNotificationの機能変更について、日本語のまとめ記事を見つけました。
参考までに。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/18 19:28

    ご回答ありがとうございます。

    紹介していただいたソースコードを元に修正してみましたが状況は変わらず…
    AutoCancelの設定自体が無いので、setAutoCancel(true)も付加してみましたが、
    それでもダメでした…

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる