简体   繁体   中英

Dismiss Ongoing Android Notification Via Action Button Without Opening App

I have an app that has an ongoing notification to help with memorization. I want to be able to dismiss this notification with one of the action button, but I don't want to open the app when the button is hit. I would prefer to use the built-in notification action buttons and not create a RemoteViews object to populate the notification. I saw one post mention using a BroadcastReceiver on this button which is received in my app, and though his tutorial was quite unhelpful, it sounds like this is headed in the right direction.

Intent resultIntent = new Intent(getBaseContext(), Dashboard.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(getBaseContext());
        stackBuilder.addParentStack(Dashboard.class);
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                    0,
                    PendingIntent.FLAG_UPDATE_CURRENT
                );
    Intent cancel = new Intent(getBaseContext(), CancelNotification.class);
        stackBuilder.addParentStack(Dashboard.class);
        stackBuilder.addNextIntent(cancel);
        PendingIntent pendingCancel =
                stackBuilder.getPendingIntent(
                    0,
                    PendingIntent.FLAG_UPDATE_CURRENT
                );

    NotificationCompat.Builder mb = new NotificationCompat.Builder(getBaseContext());
        mb.setSmallIcon(R.drawable.cross_icon);
        mb.setContentTitle(ref);
        mb.setContentText(ver);
        mb.setPriority(NotificationCompat.PRIORITY_LOW);
        mb.setOngoing(true);
        mb.setStyle(new NotificationCompat.BigTextStyle().bigText(ver));
        mb.setContentIntent(resultPendingIntent);
        mb.addAction(R.drawable.ic_cancel_dark, "Dismiss", pendingCancel);

    manager.notify(1, mb.build());  

Start with this:

int final NOTIFICATION_ID = 1;

//Create an Intent for the BroadcastReceiver
Intent buttonIntent = new Intent(context, ButtonReceiver.class);
buttonIntent.putExtra("notificationId",NOTIFICATION_ID);

//Create the PendingIntent
PendingIntent btPendingIntent = PendingIntent.getBroadcast(context, 0, buttonIntent,0);

//Pass this PendingIntent to addAction method of Intent Builder
NotificationCompat.Builder mb = new NotificationCompat.Builder(getBaseContext());
.....
.....
.....
mb.addAction(R.drawable.ic_Action, "My Action", btPendingIntent);
manager.notify(NOTIFICATION_ID, mb.build());  

Create the BroadcastReceiver:

public class ButtonReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        int notificationId = intent.getIntExtra("notificationId", 0);

        // Do what you want were.
        ..............
        ..............

        // if you want cancel notification
        NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        manager.cancel(notificationId);
    }
}  

If you don´t want show any activity when user click on notification, define the intent passed in setContentIntent in this way:

PendingIntent resultPendingIntent = PendingIntent.getActivity(context,  0, new Intent(), 0);
......
......
mb.setContentIntent(resultPendingIntent); 

To close notification tray when clicked, call setAutoCancel() with true when building the notification: mb.setAutoCancel(true);

The accepted solution is not working in Android 8.1 and onwards.

Follow the same steps as in the accepted answer, but update this line:

//Create the PendingIntent
PendingIntent btPendingIntent = PendingIntent.getBroadcast(context, 0, buttonIntent, PendingIntent.FLAG_UPDATE_CURRENT);

See also PendingIntent.FLAG_UPDATE_CURRENT

I have tried using answer from @ramaral , but it is not working as the notificationId at the onReceive method always -1 . I have found the solution for this problem by configuring

from

PendingIntent.getBroadcast(context, 0, approvedIntent, 0)

to

PendingIntent.getBroadcast(
    context,
    notificationId,
    approvedIntent,
    PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
)

Here is an example that you can follow.

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    super.onMessageReceived(remoteMessage)
    val notificationId = Random.nextInt()
    
    //Making Approve Intent for Button Action
    val approvedIntent = Intent(context, 
        BroadcastReceiverOuting::class.java).apply {
            action = ActionOuting.ACTION_APPROVED.name
            putExtra(
                Constant.NOTIFICATION_ID,
                notificationUid
            ) //Compulsory to dismiss this notification
            putExtra(Constant.STUDENT_IC, studentIc)
            putExtra(Constant.OUTING_ID, outingId)
        }
    val approvedPendingIntent: PendingIntent =
        PendingIntent.getBroadcast(
            context,
            notificationUid,
            approvedIntent,
            PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
        )
    val notification: Notification =
        notificationCompatBuilder
            .setStyle(bigTextStyle)
            .setContentTitle(title)
            .setContentText(description)
            .setSmallIcon(R.drawable.ic_logo_128)
            .setContentIntent(notifyPendingIntent)
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            .setAutoCancel(true)
            .addAction(
                R.drawable.ic_baseline_approve_check_24,
                context.getString(R.string.approve),
                approvedPendingIntent
            )
           .build()
    NotificationManagerCompat.from(context.applicationContext).apply {
       notify(notificationUid, notification)
    }
}

And then at the BroadcastReceiverOuting

override fun onReceive(context: Context?, intent: Intent?) {
    if (intent != null && intent.action != null) {
        val notificationUid = intent.getIntExtra(Constant.NOTIFICATION_ID, -1)
        val studentIC = intent.getStringExtra(Constant.STUDENT_IC)!!
        val outingID = intent.getStringExtra(Constant.OUTING_ID)!!

        //Do something...

        //To dismiss the notification
        val notificationManager =
            context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.cancel(notificationUid)
    }
}

Lastly, don't forget the AndroidManifest.xml .

<receiver
    android:name=".utils.BroadcastReceiverOuting"
    android:enabled="true"
    android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM