I am trying to implement Deep linking through Localytics Push notification in Android.In the below code I am able to receive the key value pair which I send through Localytics dashboard while creating the Push notification.
However, my requirement is to open a specific activity based on the key/value pair I receive in Push Notification.
public class GCMReceiver extends BroadcastReceiver {
String deeplink_key = "KEY_DEEPLINK";
public static final String CUSTOM_INTENT ="com.mypackage.action.TEST";
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String deeplinkValues = extras.getString(deeplink_key);
Log.i("BASE", "deeplinkValues: " + deeplinkValues);
String action = intent.getAction();
Uri data = intent.getData();
Intent gotoOffersIntent = new Intent(context,OffersDisplayActivity.class);
gotoOffersIntent.putExtra(deeplink_key, deeplinkValues);
// gotoOffersIntent.setAction(CUSTOM_INTENT);
/*The below line opens the OffersDisplayActvity directly when Push notification is received*/
context.startActivity(gotoOffersIntent);
// context.sendOrderedBroadcast(gotoOffersIntent, null);
PushReceiver pushReceiver = new PushReceiver();
pushReceiver.onReceive(context, intent);
GCMBroadcastReceiver gcmBroadcastReceiver = new GCMBroadcastReceiver();
gcmBroadcastReceiver.onReceive(context, intent);
}
}
With the above code I am able to open OffersDisplayActivity on PushNotification received,But I want the OffersDisplayActivity to be opened when I click on the Push notification.
Please help me with this.Thank you!
You don't need deep linking for your requirement. Localytics guys sometimes misinforms developers by saying you need deeplinking for custom type of notifications.
We did same thing which you want to do in your app with localytics.
1)Receive Localytics information in your already implemented GCMBroadcastReciever.
2)In you message keep one field for identifying which Activity you want to open
If you added any extra Class for receiving intent with following action
com.google.android.c2dm.intent.RECEIVE
apart from your GCMReceiver then remove it..
In that way all notification either came from your server or localytics it will be received in onReceive method.
Here is complete example what we did for localytics and our own server..
Android Manifest.xml
<service
android:name=".gcm.CustomInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- for Gingerbread GSF backward compat -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.nearfox.android" />
</intent-filter>
</receiver>
<service android:name=".gcm.CustomGCMListenerService">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name=".gcm.RegistrationIntentService"
android:exported="false" />
in CustomGCMListenerService.java
public class CustomGCMListenerService extends GcmListenerService {
private static final String TAG = "CustomGCMListener";
public interface MESSAGE_TYPE {
String NOTIFICATION_NEWS = "news_notification";
String NOTIFICATION_EVENT = "event_notification";
}
#Override
public void onMessageReceived(String from, Bundle data) {
if (data.containsKey("msg_type") && data.getString("msg_type") != null) {
String messageType = data.getString("msg_type");
if (messageType.equals(MESSAGE_TYPE.NOTIFICATION_NEWS)) {
String newsJson = data.getString("news_body");
try {
JSONObject jsonObject = new JSONObject(newsJson).getJSONObject("message");
generateNotification(this, jsonObject.getString("title"), "", MESSAGE_TYPE.NOTIFICATION_NEWS, data);
} catch (JSONException e) {
e.printStackTrace();
Log.i(TAG, "Notification Parsing Error");
return;
}
} else if (messageType.equals(MESSAGE_TYPE.NOTIFICATION_EVENT)) {
String newsJson = data.getString("body");
try {
JSONObject jsonObject = new JSONObject(newsJson).getJSONObject("message");
generateNotification(this, jsonObject.getString("title"), "", MESSAGE_TYPE.NOTIFICATION_EVENT, data);
} catch (JSONException e) {
e.printStackTrace();
Log.i(TAG, "Notification Parsing Error");
return;
}
}
}
}
public static void generateNotification(Context context, String message, String ids, String messageType, Bundle data) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context);
notificationBuilder.setSmallIcon(R.drawable.small_notification_icon);
notificationBuilder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.app_icon));
String title = context.getString(R.string.app_name);
notificationBuilder.setContentTitle(title);
notificationBuilder.setContentText(message);
Notification notification ;
if (messageType.equals(MESSAGE_TYPE.NOTIFICATION_NEWS)) {
Intent notificationIntent = new Intent(context, SingleNewsActivity.class);
notificationIntent.putExtra("source", "notification");
notificationIntent.putExtra("news_title", message);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(intent);
} else if (messageType.equals(MESSAGE_TYPE.NOTIFICATION_EVENT)) {
Intent notificationIntent = new Intent(context, SingleEventActivity.class);
notificationIntent.putExtra("source", "notification");
notificationIntent.putExtra("event_title", data);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(intent);
}
notificationBuilder.setContentText(message);
notificationBuilder.setStyle(new android.support.v4.app.NotificationCompat.BigTextStyle().bigText(message));
notification = notificationBuilder.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, notification);
}
}
So here you can see if from localytics or from your own server you send GCM message which contains field "message_type"="news_notification" then user click on notification will open SingleNEwsActivity
and if "message_type"=event_notification" then it will open SingleEventActivity.. also here you can pass extra data with notificationIntent.putExtra()
Compare your key-value pair and based on it, call desire activity from Intent while generating push notification.
It will call it when user taps on notification.
// Set the action to take when a user taps the notification
Intent resultIntent = new Intent(context, LoginActivity.class);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if (notificationObj!=null) {
resultIntent.putExtra(UserDefault.pushJSONObj, notificationObj);
}
PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent, PendingIntent.FLAG_CANCEL_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Here notificationObj is if any parameter you want to pass to your activity.
Related
Someone please help to solve it.
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
displayFirebaseRegId();
System.out.println("If condition :" + Config.REGISTRATION_COMPLETE + "::" + Config.PUSH_NOTIFICATION);
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
String message = intent.getStringExtra("message");
showAlertDialog(MainActivity.this, "Alert", message, true);
txtMessage.setTextColor(Color.GREEN);
Picasso.with(context).load(message).into(iImageView);
// txtMessage.setText(message);
System.out.println("Else condition :" + Config.REGISTRATION_COMPLETE + "::" + Config.PUSH_NOTIFICATION);
}
}
};
This is the code written in main activity, if the app is in the foreground it goes to else if part, if the app is in the background, it does not even enter into onBroadcastReceiver method, then how can I handle background event?
You can use downstream service of FCM
public class FCMMessageHandler extends FirebaseMessagingService {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String from = remoteMessage.getFrom();
String title = data.get("title");
String content = data.get("content");
// here you need parse a message and ....
}
// Creates notification based on title and body received
private void createNotification(String title, String content, long id, Intent intent) {
Context context = getBaseContext();
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);
android.support.v4.app.NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher).setContentTitle(title)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setContentText(content);
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify((int) id, mBuilder.build());
}
}
Add to Manifest.xml
<service
android:name=".firebase.FCMMessageHandler"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/common_google_signin_btn_icon_dark" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
Able to handle push notifications foreground and background events , created a method for notification in Service class and in mainactivity added the below code
if (getIntent().getExtras() != null) {
System.out.println("Coming to if method");
String sMessage = getIntent().getStringExtra("message");
String sImageUrl = getIntent().getStringExtra("image");
String sPhoto = getIntent().getStringExtra("photo");
System.out.println("Result :" +sMessage + "::" + sImageUrl + "::" + getIntent().getStringExtra("is_background"));
for (String key : getIntent().getExtras().keySet()) {
String value = getIntent().getExtras().getString(key);
if (key.equals("is_background") && value.equalsIgnoreCase("True")) {
txtMessage.setText("Success :" + sMessage);
Picasso.with(this).load(sPhoto).into(imageView);
}
}
}
You can use
private void generateNotification(Context context, String message) {
int icon = R.mipmap.app_icon;
final int soundResId = R.raw.notification_sound;
try {
Intent intent = new Intent(this, TragetActivityName.class);
intent.putExtra("usedfor", "");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.driver_app_ico)
.setContentTitle("Application name")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager1 = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager1.notify(0 /* ID of notification */, notificationBuilder.build());
} catch (Exception e) {
}
}
So Inorder to change notification icon you add this in your android manifest.
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_ic_notification" />
Change icon form resources.
This is the simplest method to change notification icon.
You can change notification color by adding
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
and follow this answer in Stack Overflow to open particular activity on click of notification. Read fcm documentation Here
I have a problem with FCM, when I receive the notification, I want it to opens specific activity, by the default when I don't add click_action it opens the main activity of the app, but when I add click_action and click on the notification it doesn't perform any action.
Here's the JSON I use in the web service:
{
"registration_ids": [
"f4............LL"
],
"notification": {
"title": "Rebate Confirmation",
"text": "Please Confirm",
"sound": "default",
"click_action": ".Activities.CustomerRebateConfirmation"
},
"data": {
"merchant_id": "20",
"customer_id": "1",
"points": "10",
"totalpoints": "100",
"message": "Please Confirm",
"type": "customer_points_rebate_confirmation"
}
}
and this is my onMessageReceived method:
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "From: " + remoteMessage.getFrom());
customerRebateDetails = new String[5];
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Message data payload: " + remoteMessage.getData());
Log.e(TAG, "Message notification: " + remoteMessage.getNotification().getBody());
String type = remoteMessage.getData().get("type");
String message = remoteMessage.getData().get("message");
String text = remoteMessage.getNotification().getBody();
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
switch (type){
case "customer_points_rebate_confirmation":
customerRebateDetails[0] = remoteMessage.getData().get("customer_id");
customerRebateDetails[1] = remoteMessage.getData().get("merchant_id");
customerRebateDetails[2] = remoteMessage.getData().get("points");
customerRebateDetails[3] = remoteMessage.getData().get("totalpoints");
Intent customerRebate = new Intent(this, CustomerRebateConfirmation.class);
customerRebate.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
customerRebate.putExtra("customer_points_rebate_confirmation", customerRebateDetails);
PendingIntent customerRebatePendingIntent = PendingIntent.getActivity(this, 0, customerRebate,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder customerRebateBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(message)
.setContentText(text)
.setSound(defaultSoundUri)
.setAutoCancel(true)
.setContentIntent(customerRebatePendingIntent);
NotificationManager customerRebateManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
customerRebateManager.notify(0, customerRebateBuilder.build());
break;
}
Does anyone know what is the problem of the implementation?
Note that it works well when the app is in foreground but it's not working when the app is in background.
Make sure you have added this lines in your CustomerRebateConfirmation activity in Manifest file...
<intent-filter>
<action android:name=".Activities.CustomerRebateConfirmation" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
place intent filter in your Manifest inside activity tag which you want to use click performance in action you have to write same name which you had given in payload fiends.
<activity name="your activity name" >
<intent-filter>
<action android:name=".Activities.CustomerRebateConfirmation" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<activity>
try this in your MainActivity class.
#Override
public void onNewIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
if (extras.containsKey("type")) {
String type = extras.getString("type");
if (type.equals("test type")) {
Toast.makeText(this, extras.getString("message"), Toast.LENGTH_SHORT).show();
}
}
}
}
I have tried this when i am suffered from this issue. Hope this will be helpful to you.
MessagingServiceClass.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
int mNoti = 2019;
private final int NOTIFICATION_ID = 237;
private static int value = 0;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
String title = "0";
String type = "0";
String message = "0";
if (remoteMessage.getData().size() > 0) {
type = remoteMessage.getData().get("type");
title = remoteMessage.getData().get("title");
message = remoteMessage.getData().get("message");
sendNotification(type, title, message);
}
}
private void sendNotification(String type, String title, String message) {
Bitmap icon = BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher);
//AppMethod.setIntegerPreference(getApplicationContext(),NOTIFICATION_ID,)
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("type", type);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, value, intent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(icon)
.setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(value, notificationBuilder.build());
value++;
}
}
This question is 2 years old. But is still relevant. This is how you could do it with the firebase console (without `click_action).
When your app is in background onMessageReceived will not be called. But when you get a notification while your app is in background, you will get an Intent along with the custom data you specify in the firebase console.
So when the user taps the notification the intent will then be executed to open your launcher activity. You can check for the data by getIntent().hasExtra("key") in your launcher activity. Where the "key" is whatever key you specify in the console.
Check if you have that "key" then, you can make another Intent and call startActivity
Here is an implementation of mine,
On my SplashActivity > OnCreate (This method Looks best if you have a splash screen as the launcher activity):
if (getIntent().hasExtra("key")){
Intent intent = new Intent(this, TargetActivity.class);
startActivity(intent);
finish();
} else {
startActivity(new Intent(this, MainActivity.class));
finish();
}
This will just start the TargetActivity. You can add any functionality to this as per your wish :)
In your addFlags, try add Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK. It works for me.
in onMessageReceived() create
String click_action = remoteMessage.getNotification().getClickAction();
and replace your intent with this
Intent customerRebate = new Intent(click_action);
I have implemented gcm push notification in my application. Everything is working fine and i am getting notifications as well.
Problem:
When app is in background or terminated state i am getting 2 notifications at a time.
When app is in foreground getting only 1 notification as i want.
App should get only 1 notification as requirement but unfortunately facing undefined situation.
My code below:
GCMPushReceiverService class for receiving message.
public class GCMPushReceiverService extends GcmListenerService {
//This method will be called on every new message received
#Override
public void onMessageReceived(String from, Bundle data) {
//Getting the message from the bundle
String message = data.getString("message");
//Displaying a notiffication with the message
Log.e("MeSs",""+message);
sendNotification(this,message, "Traccar App");
sendNotification(message);
}
//This method is generating a notification and displaying the notification //When in front
private void sendNotification(Context context, String notificationText,
String notificationTitle) {
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "");
wakeLock.acquire();
Intent intent = new Intent(this, Home.class);
intent.putExtra("ChatFragment", "newChatFound");
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int requestCode = 0;
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
context)
.setSmallIcon(R.drawable.bug_log_two)
.setColor(Color.RED)
.setContentTitle(notificationTitle)
.setContentText(notificationText)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build()); //0 = ID of notification
wakeLock.release();
}
private void sendNotification(String message) {
Intent intent = new Intent(this, Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int requestCode = 0;
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(message)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, noBuilder.build()); //0 = ID of notification
}
}
manifest file code:
<!-- GCM -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.vk.trackeruser" />
</intent-filter>
</receiver>
<!-- GCM Receiver Service -->
<service
android:name=".Notification.GCMPushReceiverService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- GCM Registration Intent Service -->
<service
android:name=".Notification.GCMRegistrationIntentService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
GCMRegistrationIntentService class:
public class GCMRegistrationIntentService extends IntentService {
//Constants for success and errors
public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";
public static final String REGISTRATION_ERROR = "RegistrationError";
public static final String SenderId = "my id with numeric number ex 9897979";
//Class constructor
public GCMRegistrationIntentService() {
super("");
}
#Override
protected void onHandleIntent(Intent intent) {
//Registering gcm to the device
registerGCM();
}
private void registerGCM() {
//Registration complete intent initially null
Intent registrationComplete = null;
//Register token is also null
//we will get the token on successfull registration
String token = null;
try {
//Creating an instanceid
InstanceID instanceID = InstanceID.getInstance(getApplicationContext());
//Getting the token from the instance id
token = instanceID.getToken(SenderId, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
//Displaying the token in the log so that we can copy it to send push notification
//You can also extend the app by storing the token in to your server
Log.w("GCMRegIntentService", "token:" + token);
String tokan = token;
//on registration complete creating intent with success
registrationComplete = new Intent(REGISTRATION_SUCCESS);
//Putting the token to the intent
registrationComplete.putExtra("token", token);
} catch (Exception e) {
//If any error occurred
Log.w("GCMRegIntentService", "Registration error");
registrationComplete = new Intent(REGISTRATION_ERROR);
}
//Sending the broadcast that registration is completed
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
}
GCMTokenRefreshListenerService class:
public class GCMTokenRefreshListenerService extends InstanceIDListenerService{
//If the token is changed registering the device again
#Override
public void onTokenRefresh() {
Intent intent = new Intent(this, GCMRegistrationIntentService.class);
startService(intent);
}
}
Class for getting my GCM token:
in oncreate {
//Initializing our broadcast receiver
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
//When the broadcast received
//We are sending the broadcast from GCMRegistrationIntentService
#Override
public void onReceive(Context context, Intent intent) {
//If the broadcast has received with success
//that means device is registered successfully
if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_SUCCESS)){
//Getting the registration token from the intent
String token = intent.getStringExtra("token");
StaticContents.Gcm_token=token;
Log.e("Token",""+token);
//Displaying the token as toast
Toast.makeText(getApplicationContext(), "Registration token:" + token, Toast.LENGTH_LONG).show();
//if the intent is not with success then displaying error messages
} else if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_ERROR)){
// Toast.makeText(getApplicationContext(), "GCM registration error!", Toast.LENGTH_LONG).show();
} else {
// Toast.makeText(getApplicationContext(), "Error occurred", Toast.LENGTH_LONG).show();
}
}
};
//Checking play service is available or not
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
//if play service is not available
if(ConnectionResult.SUCCESS != resultCode) {
//If play service is supported but not installed
if(GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
//Displaying message that play service is not installed
// Toast.makeText(getApplicationContext(), "Google Play Service is not install/enabled in this device!", Toast.LENGTH_LONG).show();
GooglePlayServicesUtil.showErrorNotification(resultCode, getApplicationContext());
//If play service is not supported
//Displaying an error message
} else {
// Toast.makeText(getApplicationContext(), "This device does not support for Google Play Service!", Toast.LENGTH_LONG).show();
}
//If play service is available
} else {
//Starting intent to register device
Intent itent = new Intent(this, GCMRegistrationIntentService.class);
startService(itent);
}
}
//Registering receiver on activity resume
#Override
protected void onResume() {
super.onResume();
Log.w("MainActivity", "onResume");
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(GCMRegistrationIntentService.REGISTRATION_SUCCESS));
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(GCMRegistrationIntentService.REGISTRATION_ERROR));
}
//Unregistering receiver on activity paused
#Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
}
Output 1: When the app in visible (foreground) only one notification is received.
Output 2: When app is closed or app is in background Getting 2 notifications.
1. onMessageReceived function inside GCMPushReceiverService class is called once you receive a message from GCM.
Using this
String message = data.getString("message");
you are parsing and storing the message in a variable called message.
The problem is that you are passing message to two functions
sendNotification(this,message, "Traccar App");
sendNotification(message);
and both the functions are building a notification and are showing the message you are passing to these two functions as 2 separate notifications.
Just comment out either of these two functions and check.
2. And to avoid duplicate notification, there is a way we can handle it.
Try Changing this -
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
to
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
If the problem is still there, please post the payload you are getting. And I would suggest to use FCM instead of GCM
You can use FCM Downstream not Upstream
I'm trying to stack push notifications with Firebase Cloud Messaging and I'm facing a problem, I don't know how to detect that the push notification has been cleared (with a sweep or with the Clear all button).
I've tried almost every tutorial I've seen on Stackoverflow with no success, so I'm missing something.
This is what I have right now:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
final static String GROUP_KEY_EMAILS = "group_key_emails";
protected PendingIntent getContentIntent(String data)
{
Intent notificationIntent = new Intent(getApplicationContext(), SplashScreen.class);
notificationIntent.putExtra("custom", data);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
return PendingIntent.getActivity(getApplicationContext(), 1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
protected PendingIntent getDeleteIntent()
{
Intent intent = new Intent(getApplicationContext(), NotificationBroadcastReceiver.class);
intent.setAction("notification_cancelled");
return PendingIntent.getBroadcast(getApplicationContext(), 1, intent, PendingIntent.FLAG_CANCEL_CURRENT);
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if(remoteMessage.getNotification() != null)
{
try {
Map<String, String> data = remoteMessage.getData();
String customData = data.get("custom");
JSONObject customJSON = new JSONObject(customData);
final JSONObject pushData = customJSON.getJSONObject("custom data");
String message = remoteMessage.getNotification().getBody();
Notification notif1 = new android.support.v4.app.NotificationCompat.Builder(getApplicationContext())
.setContentTitle("My app")
.setContentText(message)
.setSmallIcon(R.drawable.icon)
.setAutoCancel(true)
.setGroup(GROUP_KEY_EMAILS)
.setContentIntent(getContentIntent(customData))
.setDeleteIntent(getDeleteIntent())
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(1, notif1);
AuxiliaryFunctions.addPushNotificationsMessage(getApplicationContext(), message);
int notifId = AuxiliaryFunctions.readPushNotificationsMessagesNum(getApplicationContext());
if(notifId > 1)
{
NotificationCompat.InboxStyle style = new android.support.v4.app.NotificationCompat.InboxStyle()
.setSummaryText(notifId + " new messages");
JSONArray messages = AuxiliaryFunctions.readPushNotificationsMessages(getApplicationContext());
for(int i = 0; i < messages.length(); i++)
{
String localmessage = messages.getString(i);
style.addLine(localmessage);
}
Notification summaryNotification = new android.support.v4.app.NotificationCompat.Builder(getApplicationContext())
.setContentTitle("My app "+notifId+" new messages")
.setSmallIcon(R.drawable.iconplus)
.setStyle(style)
.setGroup(GROUP_KEY_EMAILS)
.setGroupSummary(true)
.setAutoCancel(true)
.setContentIntent(getContentIntent(""))
.setDeleteIntent(getDeleteIntent())
.build();
notificationManager.notify(1, summaryNotification);
}
} catch (JSONException e) {
}
}
}
}
This is my Notification Broadcast Receiver:
public class NotificationBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.e("", "NotificationBroadcastReceiver:onReceive");
}
}
And finally I declare this in my manifest:
<receiver android:name="auxiliary.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="notification_cancelled"/>
</intent-filter>
</receiver>
Well, the notifications are shown correctly, they are being stacked if there are more than one notification and if the user clicks on the notification (summary or not) everything is going well and the notification is processed with no problem.
But if the user makes a sweep in the notification (summary or not) or clicks on the Clear all notifications button, the notification dissapears but the NotificationBroadcastReceiver is never called (the log NotificationBroadcastReceiver:onReceive is not shown in the console).
What am I missing??
I'm very ashamed! I've found out the reason of my problem and it was complete stupidity.
In my AndroidManifest I had this:
<receiver android:name="auxiliary.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="notification_cancelled"/>
</intent-filter>
</receiver>
I forgot the dot before auxiliary. Once I put it:
<receiver android:name=".auxiliary.NotificationBroadcastReceiver">
<intent-filter>
<action android:name="notification_cancelled"/>
</intent-filter>
</receiver>
the receiver callback was called.
What surprise me is that AndroidManifest gave no error resolving the wrong path.
How can one differentiate the Notifications and pass them to different activities?
In the below method the third parameter(String tag) value is retreived from onMessage() that contains a value.
According to that value i wanted to differentiate which URL to open e.g Google or Facebook.
The app terminates after i include the intent code in the "if" conditions below.
Please Help
private static void generateNotification(Context context, String message,
String tag) {
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.ic_launcher,
message, when);
String title = context.getString(R.string.app_name);
Log.d("GCM", "Tag Value " + tag);
if (tag.equals("one")) {
// pass to a different activity
notificationIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://www.google.com"));
}
if (tag.equals("two")) {
// pass to a different activity
notificationIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://www.facebook.com"));
}
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}
On Manifest create intent filter for activities,that you need launch like this
<activity
android:name=".activities.TabsActivity"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="com.dittoadvertising.push" >
</action>
<category android:name="android.intent.category.DEFAULT" >
</category>
</intent-filter>
when
Uri.parse("https://www.facebook.com") = action name in filter
and in your activities will be called method onNewIntent(Intent newIntent), then intent incoming
Change your code to something like :
if (tag.equals("one")) {
notificationIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://www.google.com"));
} else if (tag.equals("two")) {
notificationIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://www.facebook.com"));
}