I'm wondering how to create a notification in android with action icons that allowed me to call a method in the main activity.
just like the one in this image : Notification icon exemple
First Welcome to stackoverflow. I'd like to remind you this is not a website to learn how to program but a website to ask questions with actual problems that can help the community. Your questions have to be detailed and specific with your code or attempt as well as the error log.
That being said, here is the best way to create a notification:
Step 1 - Create Notification Builder
First step is to create a notification builder using NotificationCompat.Builder.build(). You can use Notification Builder to set various Notification properties (small icons, large icons, title, priority etc)
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
Step 2 - Setting Notification Properties
Once you have Builder object, you can set its Notification properties using Builder object as per your requirement. But this is mandatory to set at least following −
A small icon, set by setSmallIcon()
A title, set by setContentTitle()
Detail text, set by setContentText()
mBuilder.setSmallIcon(R.drawable.notification_icon);
mBuilder.setContentTitle("I'm a notification alert, Click Me!");
mBuilder.setContentText("Hi, This is Android Notification Detail!");
Step 3 - Attach Actions
This is optional and only required if you want to attach an action with the notification. An action will allows users to go directly from the notification to an Activity in your application (where they can look at one or more events or do further work).
The action is defined by a PendingIntent containing an Intent that starts an Activity in your application. To associate the PendingIntent with a gesture, call the appropriate method of NotificationCompat.Builder.
For example, if you want to start Activity when the user clicks the notification text in the notification drawer, you add the PendingIntent by calling setContentIntent().
A PendingIntent object helps you to perform an action on your application's behalf, often at a later time, regardless whether or not your application is running.
Also there's the stackBuilder object which will contain an artificial back stack for the started Activity. This ensures that navigating backward from the Activity leads out of your application to the Home screen.
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Step 4 - Issue the notification
Finally, you pass the Notification object to the system by calling NotificationManager.notify() to send your notification. Make sure you call NotificationCompat.Builder.build() method on builder object before notifying it. This method combines all of the options that have been set and return a new Notification object.
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// notificationID allows you to update the notification later on.
mNotificationManager.notify(notificationID, mBuilder.build());
I hope this answers your question.
Related
I am displaying a notification from my application and this notification has an action in it, when user clicks on the action, the corresponding action class is called with the intent I set. Now, I want to perform a particular action but before that the user needs to unlock the screen if it is pin/pattern protected. I am not able to ask user to unlock device, i.e open up the unlock keypad/pattern on lock screen.
Below is the code I have,
//HandleAction is a java class that extends IntentService
Intent intent = new Intent(context, HandleAction.class);
intent.putExtra(key, "my_value"); //Used to send information to action class
PendingIntent pi = PendingIntent.getService(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notification = new NotificationCompat.Builder(mContext);
//set the title, icon etc for builder and add action as below
notification.addAction(icon, "my_label", pi);
When user clicks on the notification action, I get the control to onHandleIntent in MyAction.java
In here, I want to request user to unlock device if password protected and then perform an action.
How can I request user to unlock device in onHandleIntent?
I came across using KeyguardManager and KeyguardLock to acheive this but keyguardManager.newKeyguardLock is deprecated method and I want to avoid this. So, the next was using "FLAG_TURN_SCREEN_ON" and "FLAG_KEEP_SCREEN_ON" but I am unable to figure out how to use them in this context. I don't launch any window from my action class, it is just an operation like incrementing my counter. After clicking it the notification should disappear, perform my action and thats it.
I found a similar question Unlock phone , but the way it was did is by launching a dummy/empty activity.
Thanks in advance for any help, suggestions :)
In the Activity you are opening (that is behind the lock screen) you should tell system to lift the keyguard (e.g. in onCreate())
For API >= 26
KeyguardManager km = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
km.requestDismissKeyguard(this, null); // you may add callback listener here
For API < 26:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
If device is not locked securely it would unlock it immediately, and if it is locked, it will ask user to do it.
Use Activity intent in pending intent insted of Service
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra(key, "my_value"); //Used to send information to action class
PendingIntent pi = PendingIntent.getActivity(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
My Activityhosts 3 tabs and each tab is a Fragment.
I also have a Service which query a database perdiodically. Depending on the result of the query, I raise a Notification (from the Service).
When I click on the Notification, is it possible to launch a specific fragment? If yes, how can I do so?
Here is what I've done so far, in my Service class:
// When notification is clicked, go back to TabOperations Fragment
Intent i = new Intent(this, TabOperations.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, i,PendingIntent.FLAG_UPDATE_CURRENT); // Give the phone access to the app
notification.setContentIntent(pi);
// Issue notification
NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
nm.notify(UNIQUE_ID, notification.build());
Of course, this does not work.
Any advice?
Instead of the Service sending a Notification, perhaps you would be better off with a different messaging system. For example, you can utilize the Observer pattern (or third-party libraries like EventBus) to send a message from the Service to the Activity that cares about such events. The activity can then use the event to start and attach the Fragment as necessary.
I am able to create notifications. Currently when a user gets a friend request, it says "New friend request from someUsername". However, if the user receives multiple friend requests, I want to update the text to say "New friend requests."
From my understanding, I just have to change the text using the same Builder object I used to create the initial notification.
My idea was to create a HashMap mapping all the IDs used in NotificationManager's notify( int id, Builder builder ) to the Builder objects.
When a notification is clicked, the notification disappears (due to my use of setAutoCancel(true) ), however, I don't know how to detect this so I can remove the Builder object from the HashMap as well.
The reason I would like to remove the Builder object is because when the HashMap's get(id) method returns null, I'll know to display "New friend request from " instead of "New friend requests".
If my algorithm is over-complicated, by all means correct me. Otherwise, how can I detect when a notification is canceled?
Side note: I plan on doing this same thing for messages and possibly other kinds of notifications.
In case it's needed, this is my function that creates the notifications (the id is hardcoded for now):
private void triggerNotification(String content, Context context) {
Log.i("Thread", "notification triggered");
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Anime Chatter")
.setContentText( content );
builder.setAutoCancel( true );
Intent i = new Intent(context, Friends.class);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, i, 0);
builder.setContentIntent(contentIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE );
mNotificationManager.notify( 1010, builder.build());
}
The most solid way to go at this is to create a dedicated table to deal with notifications.
That may be too much work, but it's how the biggest apps deal with notifications - which has been seen and which hasn't etc.
For a more simple approach just add some code in your activity, when dealing with the intent, that tracks the last notification clicked in a persistent way (SharedPrefs?) so that whatever controller is dispatching the notifications knows if there should be more than one notification to be seen or not (for example if the user dismisses a notification without clicking on it, there is still more than one friend request he doesnt know about). This controller should also keep track of the last sent notification (SharedPrefs again). This way when the controller dispatches the notification it can compare the last sent and the last clicked and see if there is only one, or several.
Seems pretty straight forward to me. Can help you with code if needed.
What you're looking for is Notification.Builder#setDeleteIntent(PendingIntent).
The pending intent you set here (you should wrap a Broadcast Intent) will be fired when the notification is canceled by the user. You can respond to the broadcast and update your persistent storage (db, shared prefs, whatever) where you're keeping track of active notifications to determine what you should show when the next one comes in.
My application contains multiple activities. I have implemented push notifications and also shown the notification in bar. My issue is, when i click on notification is take me to the specific activity that i has specified.
Intent intent =new Intent(GcmService.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(GcmService.this, 0, intent, 0);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
getApplicationContext())
.setContentTitle(getResources().getString(R.string.app_name))
.setAutoCancel(true)
.setContentIntent(pendingIntent);
notificationBuilder.setContentIntent(pendingIntent);
mNotificationManager.notify((int) when, notificationBuilder.build());
I want if my activity is in background, and user click on the notification app resume the current activity that is in background and show dialog box.
And if my application is closed. open the Launching activity and then show the dialog box.
If you want to continue again when you click the notification(in this case your application still running on background) than you can using this method :
http://developer.android.com/training/basics/activity-lifecycle/stopping.html
I've tried it and it works.
You can link your notification to a DispatcherActivity.
If you have open Activities on the backstack, finish the DispatcherActivity suddenly in onCreate(). If not, forward to your launching activity and finish the DispatcherActivity too.
To track your active activities on backstack use this How to know Activity Count of my application? suggestions.
I don't have any device older than 4.1 to test on. I'm trying to test out pushing my notifications with the code below. It's mostly all taken from the Notification documentation. Would my code crash or does the NotificationCompat class handle all of this for me gracefully?
Under the "Handling Compatability" section it reads:
Handling compatibility
Not all notification features are available for a particular version,
even though the methods to set them are in the support library class
NotificationCompat.Builder. For example, action buttons, which depend
on expanded notifications, only appear on Android 4.1 and higher,
because expanded notifications themselves are only available on
Android 4.1 and higher.
To ensure the best compatibility, create notifications with
NotificationCompat and its subclasses, particularly
NotificationCompat.Builder. In addition, follow this process when you
implement a notification:
...
So does this mean that if I use the NotificationCompat class it will handle all of the compatibility for me?
My code that I'm worried about (because it uses BigTextStyle):
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(mContext).setSmallIcon(R.drawable.ic_launcher).setContentTitle("Title")
.setContentText(String.format("%s", message));
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(mContext, ActivityMain.class);
// The stack builder object will contain an artificial back stack for
// the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mContext);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
// Add max priority
mBuilder.setPriority(NotificationCompat.PRIORITY_MAX);
// Add bigTextStyle
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
bigTextStyle.bigText(String.format("%s", message));
mBuilder.setStyle(bigTextStyle);
mBuilder.setAutoCancel(true);
// mId allows you to update the notification later on.
mNotificationManager.notify(1, mBuilder.build());
You have nothing to worry about.
Helper class for generating large-format notifications that include a lot of text.
If the platform does not provide large-format notifications, this method has no effect. The user will always see the normal notification view.
(NotificationCompat.BigTextStyle)