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)?
I'm trying to make a notification with 2 buttons on it:
Has anyone got an idea on how to catch the button click event (remember that the Activity is paused)?
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
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
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
}
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());
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>
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();
}
}