web-dev-qa-db-ja.com

アクションがクリックされた後に通知を閉じる方法

APIレベル16(Jelly Bean)以降、通知にアクションを追加する可能性があります

builder.addAction(iconId, title, intent);

しかし、通知にアクションを追加してアクションが押された場合、通知は破棄されません。通知自体がクリックされている場合、それは

notification.flags = Notification.FLAG_AUTO_CANCEL;

または

builder.setAutoCancel(true);

しかし、明らかに、これは通知に関連付けられたアクションとは何の関係もありません。

ヒントはありますか?または、これはまだAPIの一部ではありませんか?何も見つかりませんでした。

129
endowzoner

通知マネージャーでnotifyを呼び出したときに、IDを指定しました。これは、後でアクセスするために使用できる一意のIDです(これは通知マネージャーからのものです。

notify(int id, Notification notification)

キャンセルするには、以下を呼び出します。

cancel(int id)

同じIDで。だから、基本的には、IDを追跡する必要があるか、可能であればIDをPendingIntent内のIntentに追加するバンドルに入れる必要がありますか?

140
Kaediil

LollipopのHeads Up Display通知を使用する場合、これが問題であることがわかりました。 設計ガイドライン を参照してください。実装する完全な(ish)コードを以下に示します。

今までは、「却下」ボタンを持つことはそれほど重要ではありませんでしたが、今ではあなたの顔により重要です。

heads up notification

通知の作成

int notificationId = new Random().nextInt(); // just use a counter in some util class...
PendingIntent dismissIntent = NotificationActivity.getDismissIntent(notificationId, context);

NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setPriority(NotificationCompat.PRIORITY_MAX) //HIGH, MAX, FULL_SCREEN and setDefaults(Notification.DEFAULT_ALL) will make it a Heads Up Display Style
        .setDefaults(Notification.DEFAULT_ALL) // also requires VIBRATE permission
        .setSmallIcon(R.drawable.ic_action_refresh) // Required!
        .setContentTitle("Message from test")
        .setContentText("message")
        .setAutoCancel(true)
        .addAction(R.drawable.ic_action_cancel, "Dismiss", dismissIntent)
        .addAction(R.drawable.ic_action_boom, "Action!", someOtherPendingIntent);

// Gets an instance of the NotificationManager service
NotificationManager notifyMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

// Builds the notification and issues it.
notifyMgr.notify(notificationId, builder.build());

NotificationActivity

public class NotificationActivity extends Activity {

    public static final String NOTIFICATION_ID = "NOTIFICATION_ID";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        manager.cancel(getIntent().getIntExtra(NOTIFICATION_ID, -1));
        finish(); // since finish() is called in onCreate(), onDestroy() will be called immediately
    }

    public static PendingIntent getDismissIntent(int notificationId, Context context) {
        Intent intent = new Intent(context, NotificationActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        intent.putExtra(NOTIFICATION_ID, notificationId);
        PendingIntent dismissIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        return dismissIntent;
    }

}

AndroidManifest.xml(SystemUIがバックスタックにフォーカスするのを防ぐために必要な属性)

<activity
    Android:name=".NotificationActivity"
    Android:taskAffinity=""
    Android:excludeFromRecents="true">
</activity>
61
aaronvargas

拡張された通知でアクションボタンを使用すると、余分なコードを記述する必要があり、より制約を受けることがわかりました。

ユーザーがアクションボタンをクリックすると、通知を手動でキャンセルする必要があります。通知は、デフォルトアクションに対してのみ自動的にキャンセルされます。

また、ボタンからブロードキャストレシーバーを起動した場合、通知ドロワーは閉じません。

これらの問題に対処するために、新しいNotificationActivityを作成することになりました。 UIのない​​この中間アクティビティは通知をキャンセルし、通知から本当に開始したいアクティビティを開始します。

関連する投稿にサンプルコードを投稿しました Android通知アクションをクリックしても通知ドロワーが閉じません

16
Vicki

私の意見では、BroadcastReceiverを使用することは、通知をキャンセルするよりクリーンな方法です。

AndroidManifest.xmlで:

<receiver 
    Android:name=.NotificationCancelReceiver" >
    <intent-filter Android:priority="999" >
         <action Android:name="com.example.cancel" />
    </intent-filter>
</receiver>

Javaファイル内:

Intent cancel = new Intent("com.example.cancel");
PendingIntent cancelP = PendingIntent.getBroadcast(context, 0, cancel, PendingIntent.FLAG_CANCEL_CURRENT);

NotificationCompat.Action actions[] = new NotificationCompat.Action[1];

NotificationCancelReceiver

public class NotificationCancelReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //Cancel your ongoing Notification
    };
}
6

アクションによって呼び出されているものから、常にcancel()Notificationできます(たとえば、onCreate()に提供するPendingIntentに関連付けられたアクティビティのaddAction()で) )。

5
CommonsWare

新しいAPIでは、TAGを忘れないでください:

notify(String tag, int id, Notification notification)

それに応じて

cancel(String tag, int id) 

の代わりに:

cancel(int id)

https://developer.Android.com/reference/Android/app/NotificationManager

3
Malachiasz

次の行を入力してください:

 builder.setAutoCancel(true);

完全なコードは次のとおりです。

NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
    builder.setSmallIcon(Android.R.drawable.ic_dialog_alert);
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.co.in/"));
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
    builder.setContentIntent(pendingIntent);
    builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.misti_ic));
    builder.setContentTitle("Notifications Title");
    builder.setContentText("Your notification content here.");
    builder.setSubText("Tap to view the website.");
    Toast.makeText(getApplicationContext(), "The notification has been created!!", Toast.LENGTH_LONG).show();

    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    builder.setAutoCancel(true);
    // Will display the notification in the notification bar
    notificationManager.notify(1, builder.build());
0
Hanisha