I've followed this tutorial to create a new GCM Listener service:
http://www.appifiedtech.net/2015/08/01/android-gcm-push-notification-example/
The code for the listener service:
#Override
public void onMessageReceived(String from, Bundle data) {
super.onMessageReceived(from, data);
String msg = data.getString("message");
Log.d(TAG,"GCM Message received is "+msg);
// Notifying to user code goes here
notifyUser(getApplicationContext(),msg);
}
public void notifyUser(Context context,String data){
Intent intent = new Intent(context, NotificationActivity.class);
intent.putExtra("data", data);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setAutoCancel(true);
builder.setContentTitle("New Notification");
builder.setContentIntent(pendingIntent);
builder.setContentText(data);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(uri);
notificationManager.notify(countNotification++, builder.build());
Log.v(TAG,"count "+countNotification);
}
When the app is running (foreground), this works fine and launches the Notification Activity as it should.
However, when it's running in background, I get the notification but the title and body are as defined in my server sender application, and tapping on it takes me to the Main Activity.
This essentially means that when it's running in the background something else handles the notification? Is there another handler I should implement to be able to manage that notification and send the user to the correct activity?
The screen does not wake when I receive this notification, nor does an LED light up on the phone as notifications from other applications do. How do you manage that?
(permissions, services and receiver are defined in the manifest as described in the tutorial)
In problem regarding when your apps running in the background something else handles the notification?
This SO question can help you in answering your question regarding the GCM Listener Service
In the problem regarding to the screen that doesn't wake when you receive notification.
Use ACQUIRE_CAUSES_WAKEUP
Normal wake locks don't actually turn on the illumination. Instead, they cause the illumination to remain on once it turns on (e.g. from user activity). This flag will force the screen and/or keyboard to turn on immediately, when the WakeLock is acquired. A typical use would be for notifications which are important for the user to see immediately.
You can visit this SO question in how to use it.
You remove
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
Using intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
In the NotificationActivity class , you need implement the onNewIntent() callback when you open NotificationActivity existed the stack.
Related
I have implemented firebasse notification functionality in my chat app and everything is running fine but now while testing in Android os 8.0 and 8.1 when app is in background and if user is getting 4 or more than 4 notification then its combined in group and when user click on group then not getting intent and app is restarted.
If user tap on single notification then I am able to send him in specific screen.
I want Notification data or chat id so I can send him in specific screen but not getting any data in intent.
I have searched similar kind of question in stackoverflow but still not getting proper result.
Android: Clicking Grouped Notifications Restarts App
How to open non-launcher activity on notification group click
You can use setContentIntent to set the value of Intent like below
Intent intent = new Intent(this, SecondActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.your_notification_icon)
.setContentTitle("Notification Title")
.setContentText("Notification ")
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, mBuilder.build());
It will open SecondActivity (Replace the SecondActivity with your own activity)
I am having the same issue causing app restart in Oreo, after many tries i noticed that if when creating the notification i call .setGroup(string) the system no longer groups the notifications.I am creating the notifications from a service. This is not a solution i know but not grouping is a lesser evil than app restart.
When the user drags down all notifications and then tap on my app notification, then the app opens.
However, if a fresh notification appears on top on device screen and the user taps it, it does not open.
What could be the issue?
Intent intent = Activity1.createIntent(app.getApplicationContext());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Activity2.createIntent(app.getApplicationContext(), new ArrayList<>(participants));
PendingIntent pendingIntent =
PendingIntent.getActivity(app.getApplicationContext(), 1000, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Bitmap bm = BitmapFactory.decodeResource(app.getResources(), R.mipmap.appiconmain);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(app.getApplicationContext())
.setSmallIcon(R.drawable.new_item_arrival, Notification.PRIORITY_HIGH)
.setLargeIcon(bm)
.setContentTitle(displayNotificationData.getTitle())
.setContentText(displayNotificationData.getSubTitle())
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setPriority(Notification.PRIORITY_HIGH)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
You need to look at overriding Activity's onNewIntent(Intent intent) event handler, on this method you should be able to perform whatever tasks you need
Additionally, according to the official docs you can still get the original intent through via getIntent(), therefore still inside onNewIntent() you should consider using setIntent (Intent newIntent) so you can use this new intent anywhere in the activity
Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.
Take a look at this quote from a precise and concise answer:
For managing if the activity is already running you have two ways:
Add FLAG_ACTIVITY_SINGLE_TOP flag to the Intent when launching the
activity, and then in the activity class implement onNewIntent(Intent
intent) event handler, that way you can access the new intent that was
called for the activity (which is not the same as just calling
getIntent(), this will always return the first Intent that launched
your activity.
Same as number one, but instead of adding a flag to the
Intent you must add "singleTop" in your activity AndroidManifest.xml.
If you use intent extras, remeber to call PendingIntent.getActivity()
with the flag PendingIntent.FLAG_UPDATE_CURRENT, otherwise the same
extras will be reused for every notification.
I hope this helps
Use this :-
PendingIntent pendingIntent =
PendingIntent.getActivity(app.getApplicationContext(), 1000, intent, PendingIntent.FLAG_UPDATE_CURRENT);
and overrride onNewIntent method in your MainActivity.
My Android application receives push notification with some text messages.If I tap a push it redirects me to desired activity with latest push message (intent message) but I want to show my desired activity with corresponding push messages.
For example If I receives 10 push notifications and I tap 3rd notification, my code redirects me to the specified activity with 10th push notification's message, but I want to show 3rd intent push notification's message.
I know PendingIntent.FLAG_UPDATE_CURRENT replace the intent message, how can I redirect with corresponding message instead last message?
I have tried the following:
Intent intent = new Intent(this, TestActivity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra("uid", uid);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
getApplicationContext());
Notification notification = mBuilder
.setSmallIcon(R.drawable.ic_launcher)
.setTicker(textMsg)
.setWhen(0)
.setAutoCancel(true)
.setContentTitle(textMsg)
.setStyle(
new NotificationCompat.BigTextStyle().bigText(textMsg))
.setContentIntent(resultPendingIntent).setContentText(textMsg)
.build();
NotificationManager notificationManager = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) System.currentTimeMillis(),
notification);
Use FLAG_ONE_SHOT instead and change the second parameter in getActivity which is set to 0. This answer will make it clear.
You should Change the pendingIntend's content for Different Messages.
Here is the snippet from PendingIntent document.
"A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags), it will receive a PendingIntent representing the same token if that is still valid, and can thus call cancel() to remove it."
In simple words...try passing different id(Something like currentEpochTime) for each pendingIntent.
I am able to generate and display multiple notifications, all starting the same activity but displaying different information depending on the extra that is attached to the intent that starts up the Activity. When I am within my application, all the notifications are able to start the Activity, but when I am outside of the application, only one is able to start the Activity (the first that I click on), the rest do nothing once clicked on (except disappear). This is my code for generating the notifications. The "reqCode" represents unique numbers.
Resources r = getResources();
Intent i = new Intent(this, DisplaySearchTickerAlert_Activity.class);
i.putExtra(NewArticleNotification_Service.QUERY_TICKER, searchQuery);
PendingIntent pi = PendingIntent.getActivity(this, reqCode, i, 0);
Notification notification = new NotificationCompat.Builder(this)
.setTicker(r.getString(R.string.ticker_alert))
.setSmallIcon(android.R.drawable.ic_menu_call)
.setContentTitle(r.getString(R.string.ticker_alert))
.setContentText("Newly published for search term: " + "\""
+ searchQuery + "\"").setContentIntent(pi).setAutoCancel(true).build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(reqCode, notification);
That is because your activity is already being displayed. Only the first notification will bring it to the foreground. The rest of notifications will dispatch a new intent that depending on your activity android:launchMode you might be able to catch on the onNewIntent callback.
My question is a bit complicated so I am going to describe it briefly what I want to achieve. My application receives messages from GCM without any issue. When application is running and is visible to the user I am not displaying notification in Action Bar, I am displaying this message in dialog alert. I use BroadcastReceiver to achieve this.
The main issue is that, when app gets a few notifications in no time. When main activity is visible to the user, the first notification will be shown in dialog alert. And next will be placed in Action Bar as usual Android notifications. And at this moment user disposes the dialog alert and is going to choose a next notification from Action Bar. At this moment I am using in my CloudService (extends IntentService) intent with flag Intent.FLAG_ACTIVITY_CLEAR_TOP and also PendingIntent.FLAG_UPDATE_CURRENT flag for pendingIntent. PendingIntent is just the contentIntent for my NotificationCompat.Builder.
It works in this way that for each user click on the notification from Action Bar, my activity is refreshing (floats to the lower device edge and then floats from the upper edge with dialog alert with message - I am getting the extras from the intent in onResume method). This action is quite OK. Activity has only one instance in that case - I don't have to break through the few instances of the same activity while I have opened few notifications. But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.
There are two methods in CloudService which handle cloud messages:
private void showNotification(Bundle extras) {
notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
String message = extras.getString(CloudMetaData.MESSAGE);
if (App.isMyActivityVisible() && !CloudMessageDialogFragment.isAttached()) {
sendBroadcast(message, NOTIFICATION_ID);
} else {
Intent intent = new Intent(this, MyParentActivity.class);
intent.putExtra(CloudMetaData.MESSAGE, message);
intent.putExtra(CloudMetaData.NOTIFICATION_ID, NOTIFICATION_ID);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle(getString(R.string.app_name));
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(alert));
builder.setContentText(alert);
builder.setAutoCancel(true);
builder.setDefaults(Notification.DEFAULT_SOUND);
builder.setContentIntent(contentIntent);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
NOTIFICATION_ID++;
}
And method which send broadcast is just like that:
private void sendBroadcast(String message, int notificationId) {
Intent intent = new Intent();
intent.setAction(ACTION_FROM_CLOUD_SERVICE);
intent.putExtra(CloudMetaData.MESSAGE, message);
intent.putExtra(CloudMetaData.NOTIFICATION_ID, notificationId);
sendBroadcast(intent);
}
In which way can I achieve similar solution? But it is important for user of course to open notification from Action Bar and shown him its correct message.
EDIT
I have switched my dialog alert into the dialog activity. This is its definition in AndroidManifest:
<activity
android:name="com.myapp.activity.CloudMessageDialogActivity"
android:theme="#android:style/Theme.Dialog"
android:parentActivityName="com.myapp.activity.MyParentActivity"/>
But the result is still the same - when app receives a few notifications, clicking on one of them will open the dialog with the intent for the last received notification.
But the big problem is that when user chooses any of the notifications in each case the last one will open in dialog alert. Activity seems to has the same intent despite of PendingIntent.FLAG_UPDATE_CURRENT.
That's because you are using the same request code (i.e., 0) for all PendingIntents here:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
By doing so, you are ultimately receiving the same intent, because the platform is failing to see the difference between the intents and delivering the same object everytime:
... it is important to know when two Intents are considered to be the same for purposes of retrieving a PendingIntent. A common mistake people make is to create multiple PendingIntent objects with Intents that only vary in their "extra" contents, expecting to get a different PendingIntent each time. This does not happen. The parts of the Intent that are used for matching are the same ones defined by Intent.filterEquals. If you use two Intent objects that are equivalent as per Intent.filterEquals, then you will get the same PendingIntent for both of them.
So, instead of a constant value, please use a unique request code. For e.g. change the above line with:
PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
Hope this helps.