19

I'm trying to make a notification with 2 buttons on it:

  • one takes me back to the activity
  • the other closes it

Has anyone got an idea on how to catch the button click event (remember that the Activity is paused)?

2
  • To be honest i don't like the idea behind your efford, or i do not understand it. Normal notifications in android have the X on the right side and if you click on them you a redirected to the activity. Commented May 9, 2012 at 13:13
  • We teach them and show them the Android Developer Guidelines ;) Commented Apr 2, 2013 at 0:09

6 Answers 6

44

I am glad to post it! After working all night I found something. So, here we go!

1. Create an xml layout file for your notification.

2. Create the notification using the Notification.Builder. After adding everything you want (icons, sounds, etc) do this:

 //R.layout.notification_layout is from step 1 RemoteViews contentView=new RemoteViews(ctx.getPackageName(), R.layout.notification_layout); setListeners(contentView);//look at step 3 notification.contentView = contentView; 

3. Create a method setListeners. Inside this method you have to write this:

 //HelperActivity will be shown at step 4 Intent radio=new Intent(ctx, packagename.youractivity.class); radio.putExtra("AN_ACTION", "do");//if necessary PendingIntent pRadio = PendingIntent.getActivity(ctx, 0, radio, 0); //R.id.radio is a button from the layout which is created at step 2 view.setOnClickPendingIntent(R.id.radio, pRadio); //Follows exactly my code! Intent volume=new Intent(ctx, tsapalos11598712.bill3050.shortcuts.helper.HelperActivity.class); volume.putExtra("DO", "volume");</p> //HERE is the whole trick. Look at pVolume. I used 1 instead of 0. PendingIntent pVolume = PendingIntent.getActivity(ctx, 1, volume, 0); view.setOnClickPendingIntent(R.id.volume, pVolume); 

4. For my requirements I used a HelperActivity which responds to the intents. But for you I don't think it is necessary.

If you want the full source code you can browse it or download it from my git repo. The code is for personal use, so don't expect to read a gorgeous code with a lot of comments. https://github.com/BILLyTheLiTTle/AndroidProject_Shortcuts

ALL THE ABOVE, ANSWERS THE QUESTION OF CATCHING EVENT FROM DIFFERENT BUTTONS.

About canceling the notification I redirect you here

How to clear a notification in Android

Just remember to use the id you parsed at the notify method when you called the notification for fist time

Sign up to request clarification or add additional context in comments.

3 Comments

This works brilliantly on ICS 4.0.4! You should consider formatting your answer properly so that other users can have a good look at your answer.
You are right. I should have done it from the beggining. I hope that it is better now. Due to your comment I added the link to download the source code. All the readers from now on should thank you, not me. Happy ending year and Happiest new year
That's nice of you! Happy New Year!!
5

There is a full example for you here

 //Add this code to onCreate or some onclick Buttton NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()); long when = System.currentTimeMillis(); builder.setSmallIcon(R.drawable.ic_notification); Intent notificationIntent = new Intent(getApplicationContext(), notificationActivity.class).putExtra("notification", "1"); PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(contentIntent); Notification notification = builder.getNotification(); notification.when = when; RemoteViews remoteViews = new RemoteViews(getApplicationContext().getPackageName(), R.layout.notification_view); remoteViews.setTextViewText(R.id.tvName, "New Name"); listener(remoteViews,getApplicationContext()); notification.contentView = remoteViews; notification.flags |= Notification.FLAG_AUTO_CANCEL; manager.notify(1, notification); 

and then you can define listener method :

 public void listener(RemoteViews remoteViews, Context context) { // you have to make intetns for each action (your Buttons) Intent intent = new Intent("Accept"); Intent intent2 = new Intent("Reject"); PendingIntent pendingIntent = PendingIntent.getBroadcast(context,1,intent,0); PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context,1,intent2,0); // add actions here ! IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("Accept"); intentFilter.addAction("Reject"); BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals("Accept")){ Toast.makeText(context, "Accepted !!", Toast.LENGTH_SHORT).show(); } else if(intent.getAction().equals("Reject")) { Toast.makeText(context, "Rejected !!", Toast.LENGTH_SHORT).show(); } } }; context.registerReceiver(receiver,intentFilter); remoteViews.setOnClickPendingIntent(R.id.ivRequest,pendingIntent); remoteViews.setOnClickPendingIntent(R.id.ivReject,pendingIntent2); } 

and here is the notification_view layout to costumize your notification .

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="Request from " /> <TextView android:id="@+id/tvName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginStart="15dp" android:layout_toRightOf="@id/textView" android:text="Amin" /> <ImageView android:id="@+id/ivRequest" android:layout_width="30dp" android:layout_height="30dp" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:src="@drawable/notification" /> <ImageView android:id="@+id/ivReject" android:layout_width="30dp" android:layout_height="30dp" android:layout_marginEnd="10dp" android:layout_toLeftOf="@id/ivRequest" android:layout_centerVertical="true" android:src="@drawable/trash" /> </RelativeLayout> 

2 Comments

This example does what it claims with a copy & paste (after you add your drawables). However, builder.setCustomContentView(remoteViews); would be better than notification.contentView = remoteViews; and builder.build() is better than builder.getNotification() due to deprecations. (You have to rearrange the code a bit for these changes).
Yes, I copied the code from my own SimpleProject and Thanks for the updates :)
4

As for ICS, the question is simple to reply because the required behaviour reflects default notification: you can close a notification swiping it to the right, and you can define which activity to send the user to when he presses it simply using PendingIntent:

// The PendingIntent to launch our activity if the user selects this // notification. Note the use of FLAG_CANCEL_CURRENT so that, if there // is already an active matching pending intent, cancel it and replace // it with the new array of Intents. PendingIntent contentIntent = PendingIntent.getActivities(this, 0, makeMessageIntentStack(this, from, message), PendingIntent.FLAG_CANCEL_CURRENT); 

code taken from http://developer.android.com/guide/topics/ui/notifiers/notifications.html

1 Comment

thank you for your answer, although it's not what i asked.. What I wanna do is a notification with 2 buttons on it (already have the layout), but I'm having problems catching the onClick event, I want one of them to close the ACTIVITY and the other to make the default action of the notification.
3

If you want to assign specific intent to a button:

views.setOnClickPendingIntent(R.id.your_button_id, pendingIntent); 

I suppose that you need only one intent to be sent when the button is clicked, so you have to AVOID setting the main notification intent

notification.contentIntent = yourPendingIntent; 

Otherwise (if you set "notification.contentIntent = pendingIntent;" as usual) both intents will be called which might not be what you want/user expects.

If you still want pressing other parts of the notification invoke that general intent (or any other) you can use the same method of intent-per-view assignment as above. Don't forget to set

android:clickable="true" 

to any view you'd like to track onClick() for.

You can track these intents by their extras in the activity they are calling. If you are calling you main/launcher activity than you'll track them here (as it comes from javadoc for this method):

@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Bundle data = intent.getExtras(); if (data != null && data.containsKey(YOUR_INTENT_KEY_SOURCE_CONSTANT)) { // process your notification intent } // go on with smth else } 

Comments

3

You can simply add action Buttons in your Notification by setting action to your Notification.Builder and defining PendingIntent for each action

below is the sample code:

 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("My notification") .setContentText("Hello World!") .addAction(R.drawable.action_posetive,"posetive",PendingIntent.getActivity(0,intent,0)) .addAction(R.drawable.action_clear,"clear",PendingIntent.getActivity(0,intent,0)); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(0, mBuilder.build()); 

Comments

0

For me, this is working greatly.. I will write down the whole example.. This is for Notification create

public void createNotification2(String aMessage) { final int NOTIFY_ID = 11; String name = getString(R.string.app_name); String id = getString(R.string.app_name); // The user-visible name of the channel. String description = getString(R.string.app_name); // The user-visible description of the channel. NotificationCompat.Builder builder; if (notifManager == null) { notifManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel mChannel = notifManager.getNotificationChannel(id); if (mChannel == null) { mChannel = new NotificationChannel(id, name, importance); mChannel.setDescription(description); mChannel.enableVibration(true); mChannel.setLightColor(getColor(R.color.colorPrimaryDark)); mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); notifManager.createNotificationChannel(mChannel); } } else { } Intent Off_broadcastIntent = new Intent(this, Database_Update.class); Off_broadcastIntent.setAction("on"); Off_broadcastIntent.putExtra("toastMessage", "1"); PendingIntent Off_actionIntent = PendingIntent.getService(this, 0, Off_broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT); Intent on_broadcastIntent = new Intent(this, Database_Update.class); on_broadcastIntent.setAction("off"); on_broadcastIntent.putExtra("toastMessage", "0"); PendingIntent on_actionIntent = PendingIntent.getService(this, 0, on_broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT); Intent cancel_broadcastIntent = new Intent(this, Database_Update.class); cancel_broadcastIntent.setAction("cancel"); cancel_broadcastIntent.putExtra("toastMessage", "close"); PendingIntent cancel_actionIntent = PendingIntent.getService(this, 0, cancel_broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT); Intent content_intent = new Intent(this, Status_Page.class); content_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, content_intent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, id) .setSmallIcon(android.R.drawable.ic_popup_reminder) .setContentTitle(name) .setPriority(NotificationCompat.PRIORITY_HIGH) .setContentIntent(pendingIntent) .setAutoCancel(false) .setVibrate(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}) .addAction(R.drawable.block, "ON", Off_actionIntent) .addAction(R.drawable.notification, "OFF", on_actionIntent) .addAction(R.drawable.clear, "CLOSE", cancel_actionIntent); Notification notification = mBuilder.build(); notification.flags = Notification.FLAG_NO_CLEAR|Notification.FLAG_ONGOING_EVENT; notifManager.notify(11, notification); } 

In Android Menifest

<service android:name=".Database_Update"></service> 

This is service class

public class Database_Update extends Service { String result=""; Realm realm; BlockList blockList; @Override public void onCreate() { try { RealmConfiguration config = new RealmConfiguration.Builder() .name("notification.realm") .schemaVersion(1) .deleteRealmIfMigrationNeeded() .build(); realm = Realm.getInstance(config); } catch (Exception e) { Log.d("Error Line Number", Log.getStackTraceString(e)); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { //Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); Log.d("SERVICE","SERVICE CHECKING"); result=intent.getStringExtra("toastMessage"); Log.d("SERVICE",result); if (realm!=null){ Log.d("SERVICE","realm working"); }else { Log.d("SERVICE","Realm not working"); } blockList=realm.where(BlockList.class).equalTo("package_name", "BLOCK_ALL").findFirst(); try { Log.d("SERVICE",blockList.getStatus()); } catch (Exception e) { Log.d("Error Line Number", Log.getStackTraceString(e)); } realm.beginTransaction(); if (result.equals("1")){ if (blockList==null){ BlockList blockList_new=realm.createObject(BlockList.class); blockList_new.setPackage_name("BLOCK_ALL"); blockList_new.setStatus("yes"); }else { blockList.setStatus("yes"); } Log.d("SERVICE","BLOCKING NOTIFICATION"); Toast.makeText(this, "BLOCKING", Toast.LENGTH_SHORT).show(); }else if (result.equals("0")){ if (blockList==null){ BlockList blockList_new=realm.createObject(BlockList.class); blockList_new.setPackage_name("BLOCK_ALL"); blockList_new.setStatus("no"); }else { blockList.setStatus("no"); } Log.d("SERVICE","ALLOW NOTIFICATION"); Toast.makeText(this, "ALLOW NOTIFICATION", Toast.LENGTH_SHORT).show(); }else if (result.equals("close")){ NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); manager.cancel(11); Log.d("SERVICE","REMOVING"); Toast.makeText(this, "CLOSED", Toast.LENGTH_SHORT).show(); } realm.commitTransaction(); return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { if (realm!=null){ realm.close(); } Toast.makeText(this, "REMOVING", Toast.LENGTH_SHORT).show(); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.