I want to get the values from extra key value which I am sending from urban air ship. Please help how to get those values. I am able to get the push notifications. But I don't know how to get the data from payload.
public class IntentReceiver extends BaseIntentReceiver {
private static final String TAG = "IntentReceiver";
private String video_id ="123456";
#Override
protected void onChannelRegistrationSucceeded(Context context, String channelId) {
Log.i(TAG, "Channel registration updated. Channel Id:" + channelId + ".");
// Broadcast that the channel updated. Used to refresh the channel ID on the main activity.
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(MainActivity.ACTION_UPDATE_CHANNEL));
}
#Override
protected void onChannelRegistrationFailed(Context context) {
Log.i(TAG, "Channel registration failed.");
}
#Override
protected void onPushReceived(Context context, PushMessage message, int notificationId) {
Log.i(TAG, "Received push notification. Alert: " + message.getTitle() + ". Notification ID: " + notificationId);
#Override
protected void onBackgroundPushReceived(Context context, PushMessage message) {
Log.i(TAG, "Received background push message: " + message);
}
#Override
protected boolean onNotificationOpened(Context context, PushMessage message, int notificationId) {
Intent launch = new Intent(Intent.ACTION_MAIN);
launch.setClass(UAirship.shared().getApplicationContext(),
MainActivity.class);
launch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
launch.putExtra("NotificationMessage", "rich push notification recieved");
context.startActivity(launch);
/*//pending intent
Intent notificationIntent = new Intent(context, MainActivity.class);
Notification notification = new Notification();
notificationIntent.putExtra("NotificationMessage", "rich push notification recieved");
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingNotificationIntent = PendingIntent.getActivity(context,0,notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(context, "", "", pendingNotificationIntent);*/
return false;
}
#Override
protected boolean onNotificationActionOpened(Context context, PushMessage message, int notificationId, String buttonId, boolean isForeground) {
Log.i(TAG, "User clicked notification button. Button ID: " + buttonId + " Alert: " + message.getAlert());
return false;
}
#Override
protected void onNotificationDismissed(Context context, PushMessage message, int notificationId) {
Log.i(TAG, "Notification dismissed. Alert: " + message.getAlert() + ". Notification ID: " + notificationId);
}
}
To get the extra data use the getPushBundle on the message. So if I have something called "action" it would be this.
Bundle pushBundle = message.getPushBundle();
String action = null;
if (pushBundle != null) {
action = pushBundle.get("action").toString();
}
You can get the bundle out of the PushMessage as rightly said by #Koppo
Bundle pushBundle = message.getPushBundle();
and iterate the bundle and get all the extras in it. then you can decide which one to handle further for your application
One more post available on this iteration logic. you can check this as well
https://stackoverflow.com/a/16782044/4781403
Related
Good day everyone.
I would like to make an application which replies to received SMS automatically.
For example.
Jon Doe sends me - "Hi", Application gets the message body, checks it with my database where I have a potential response:
ID | Text | Potential Answer
01 | Hi | Hello how are you?
and Application sends the Potential response.
So far what I have achieved -
App receives the Message, checks it with the database ( using Like '%') and gets the correct "Potential Answer" Column and passes it as message text body, but to send it I am using a button.
My Reciever is a sperate file class
public class MyReceiver extends BroadcastReceiver {
public static String textSmsbody="";
private static final String TAG=MyReceiver.class.getSimpleName();
public static final String pdu_type="pdus";
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onReceive(Context context, Intent intent) {
// Get the SMS message.
Bundle bundle = intent.getExtras();
SmsMessage[] msgs;
String strMessage = "";
String format = bundle.getString("format");
// Retrieve the SMS message received.
Object[] pdus = (Object[]) bundle.get(pdu_type);
if (pdus != null) {
// Check the Android version.
boolean isVersionM =
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
// Fill the msgs array.
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
// Check Android version and use appropriate createFromPdu.
if (isVersionM) {
// If Android version M or newer:
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format);
} else {
// If Android version L or older:
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
// Build the message to show.
String a=msgs[i].getMessageBody();
textSmsbody=msgs[i].getMessageBody();
if (a.contains("?")) {
strMessage=msgs[i].getOriginatingAddress();
// strMessage += " :" + msgs[i].getMessageBody() + "\n";
}
else {
strMessage=a;
// strMessage += "SMS from" + msgs[i].getOriginatingAddress();
// strMessage += "ELSE:" + msgs[i].getMessageBody() + "\n";
}
// Log and display the SMS message.
Log.d(TAG, "onReceive: " + strMessage);
Toast.makeText(context, strMessage, Toast.LENGTH_LONG).show();
}
}
}
}
Sending method is in my MainActivity.
public void smsSendMessage(View view) {
databaseSearch();
// Set the destination phone number to the string in editText.
String destinationAddress = "2020";
// Find the sms_message view.
// Get the text of the SMS message.
String smsMessage = sendingText;
// Set the service center address if needed, otherwise null.
String scAddress = null;
// Set pending intents to broadcast
// when message sent and when delivered, or set to null.
PendingIntent sentIntent = null, deliveryIntent = null;
// Use SmsManager.
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage
(destinationAddress, scAddress, smsMessage,
sentIntent, deliveryIntent);
}
In layout I have a button which calls smsSendMessage () ;
My question is how I can make it automatically without button.
When the phone receives a message, the app shall check it with the database and send it by itself.
Please tell me if you need to see my Manifest file, or databasehelper.
Using JobService should be a suitable option in your case.
Create a JobService class like that
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class ExampleJobService extends JobService {
#Override
public boolean onStartJob(JobParameters params) {
//send a message
return true;
}
#Override
public boolean onStopJob(JobParameters params) {
return true;
}
}
Also Declare In your Manifest
<service
android:name=".ExampleJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
Now in your Receiver, you can start it like that
ComponentName componentName = new ComponentName(context, ExampleJobService.class);
PersistableBundle bundle = new PersistableBundle();
bundle.putLong("lat", lat);
bundle.putLong("lon", lon);
JobInfo jobInfo = new JobInfo.Builder(0, componentName)
.setExtras(bundle)
.build();
For more details about JobServices https://www.vogella.com/tutorials/AndroidTaskScheduling/article.html
I'm building a VoIP app on React Native, which detects incoming calls using push notifications. I need to start the app and bring it to the foreground on receiving a push notification. I'm able to achieve that for the following scenarios:
When the device is unlocked and:
The app is minimized (is still in the background)
The app is not in the background (killed from multitasking view)
When the device is locked and:
The app is minimized (is still in the background)
The only scenario I'm not able to handle is when the device is locked and the app is killed. The app starts but does not show up over the lock screen. Instead, the user needs to unlock the phone to access the app.
Here's the piece of code that runs when a notification is received,
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Intent notificationIntent = new Intent(this, MainActivity.class);
// Check if app is running
if(MainActivity.isAppRunning) {
startActivity(notificationIntent);
Intent messagingEvent = new Intent(MESSAGE_EVENT);
messagingEvent.putExtra("message", remoteMessage);
// Broadcast it so it is only available to the RN Application
LocalBroadcastManager
.getInstance(this)
.sendBroadcast(messagingEvent);
} else {
startActivity(notificationIntent);
try {
// If the app is in the background we send it to the Headless JS Service
Intent headlessIntent = new Intent(
this.getApplicationContext(),
BackgroundListenService.class
);
headlessIntent.putExtra("message", remoteMessage);
this
.getApplicationContext()
.startService(headlessIntent);
Log.d(TAG, "message: " + remoteMessage);
HeadlessJsTaskService.acquireWakeLockNow(this.getApplicationContext());
} catch (IllegalStateException ex) {
Log.e(
TAG,
"Background messages will only work if the message priority is set to 'high'",
ex
);
}
}
}
And here's my MainActivity:
public class MainActivity extends NavigationActivity {
public static boolean isAppRunning;
private static boolean isMessageRecieved;
private class MessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
isMessageRecieved=true;
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
window.clearFlags(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this);
super.onCreate(savedInstanceState);
isAppRunning = true;
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
// Subscribe to message events
localBroadcastManager.registerReceiver(
new MainActivity.MessageReceiver(),
new IntentFilter(MyFirebaseMessagingService.MESSAGE_EVENT)
);
if(isMessageRecieved) {
Window window = getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
window.clearFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
window.clearFlags(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
}
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "1";
String channel2 = "2";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(channelId,
"Channel 1",NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription("This is BNT");
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setShowBadge(true);
notificationManager.createNotificationChannel(notificationChannel);
NotificationChannel notificationChannel2 = new NotificationChannel(channel2,
"Channel 2",NotificationManager.IMPORTANCE_MIN);
notificationChannel.setDescription("This is bTV");
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setShowBadge(true);
notificationManager.createNotificationChannel(notificationChannel2);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
isAppRunning = false;
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
}
How to get full content of notification in Lolipop or above devices.
I am unable to get notification detail like buttons and icons in notification with this.
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker ="";
if(sbn.getNotification().tickerText !=null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
Log.i("Package",pack);
Log.i("Ticker",ticker);
Log.i("Title",title);
Log.i("Text",text);
Intent msgs = new Intent("Msg");
msgs.putExtra("package", pack);
msgs.putExtra("ticker", ticker);
msgs.putExtra("title", title);
msgs.putExtra("text", text);
LocalBroadcastManager.getInstance(context).sendBroadcast(msgs);
}
As I have seen you did not create your notification. You need a notification builder just after your notification is received in your application.
Hence in the receiver of your broadcast, you need to create the notification to be shown in your status bar like the following.
// Inside your broadcast receiver
int notificationID = new Random().nextInt();
Intent intent = new Intent(mContext, YourHomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, notificationID, intent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext)
.addAction(R.drawable.ic_prev, "BUTTON 1", myIntentToButtonOneScreen)
.addAction(R.drawable.ic_pause, "BUTTON 2", myIntentToButtonTwoScreen) // #1
.addAction(R.drawable.ic_next, "BUTTON 3", myIntentToButtonThreeScreen)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
if (result != null)
notificationBuilder.setLargeIcon(result);
NotificationManager notificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationID, notificationBuilder.build());
This is just a sample code which might not work. But this is just to give you an idea. Please follow this developer documentation for better understanding.
Update
Based on the comment asking for the notification listener service, here's sample code on how you can listen to notification that was sent to your mobile. Considering you have used Firebase cloud messaging.
public class FCMListenerService extends FirebaseMessagingService {
private FCMNotificationResponse mFcmNotificationResponse;
private RemoteMessage.Notification notification;
private Map data;
private String from;
#Override
public void onMessageReceived(RemoteMessage message) {
parseRemoteMessage(message);
}
private void parseRemoteMessage(RemoteMessage message) {
from = message.getFrom();
data = message.getData();
notification = message.getNotification();
Logger.logD("Message", "From: " + from);
// Check if message contains a data payload.
if (data.size() > 0) {
Logger.logD("Data", "Message data payload: " + data.toString());
setNotificationResponseFromData(data);
}
createNotification(this, notification.getTitle(), notification.getBody(), mFcmNotificationResponse.getIcon());
}
// Here you parse the JSON body received from notification
private void setNotificationResponseFromData(Map data) {
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(data);
mFcmNotificationResponse = gson.fromJson(jsonElement, FCMNotificationResponse.class);
}
private void createNotification(Context context, String title, String message, String imageUrl) {
new CreateNotificationAsyncTask(context, title,
message, imageUrl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
onMessageReceived function is called when a notification is received. Then you need to parse your data and then create the notification accordingly.
The phone I am trying to receive the push notification from is not receiving it when the user is offline and comes online, the regId and the result is returned so not sure what is stopping it, not receiving an error either...
EDIT:
I have a user offline and then he would come online, and the message would not be pushed to him, only if the user is online at the time of the push...
Here is the code on server side:
// //BELOW FOR GCM
function notifyDetails(to, from, msg, itemId, itemName, fromName, type) {
User.findOne({_id: to}, function(err, results) {
if(err) {
throw err;
} else {
callNotify();
function callNotify() {
console.log("the from is " + results.reg_id);
if(results != null) {
request(
{ method: 'POST',
uri: 'https://android.googleapis.com/gcm/send',
headers: {
'Content-Type': 'application/json',
'Authorization': GOOGLE API KEY
},
"registration_ids": [results.reg_id],
"data": {
"notifyFromUserId": from,
"notifyMsg": msg,
"notifyItemId": itemId,
"notifyItemName": itemName,
"notifyFromName": fromName,
"notifyType": type
},
//default 4 weeks (this is in seconds)
//"time_to_live": 20000
})
}, function (error, response, body) {
if(error) {
throw error;
} else {
}
});
}
}
}
});
}
On android manifest file:
<receiver
android:name=".modular.MSGReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="package.com" />
</intent-filter>
</receiver>
<service android:name=".modular.MSGService" />
The MSGService file:
public class MSGService extends IntentService {
SharedPreferences prefs;
NotificationCompat.Builder notification;
NotificationManager manager;
public MSGService() {
super("MSGService");
}
String TAG = Constants.DEBUG;
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
prefs = getSharedPreferences("Chat", 0);
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.
MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
Log.d(TAG, "Error");
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_DELETED.equals(messageType)) {
Log.d(TAG, "Error");
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_MESSAGE.equals(messageType)) {
Log.d(TAG, "Received: " + extras.getString("notifyMsg"));
String notifyFromUserId, notifyMsg, notifyItemId, notifyItemName, notifyFromName;
int notifyType;
notifyFromUserId = extras.getString("notifyFromUserId");
notifyMsg = extras.getString("notifyMsg");
notifyItemId = extras.getString("notifyItemId");
notifyItemName = extras.getString("notifyItemName");
notifyFromName = extras.getString("notifyFromName");
notifyType = extras.getInt("notifyType");
sendNotification(notifyFromUserId, notifyMsg, notifyItemId, notifyItemName, notifyFromName, notifyType);
}
}
MSGReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String notifyFromUserId, String notifyMsg, String notifyItemId,
String notifyItemName, String notifyFromName, int notifyType) {
//the data that you want passed to the new class
Bundle data = new Bundle();
Intent newIntentMsg = new Intent();
data.putString("userId", notifyItemId);
Intent profileIntent = new Intent(this, ProfileActivity.class);
profileIntent.putExtras(data);
newIntentMsg = profileIntent;
notification = new NotificationCompat.Builder(this);
notification.setContentTitle(notifyItemName);
notification.setContentText(notifyMsg);
notification.setTicker("New Message !");
notification.setSmallIcon(R.drawable.ic_launcher);
PendingIntent contentIntent = PendingIntent.getActivity(this, 1000,
newIntentMsg, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setContentIntent(contentIntent);
notification.setAutoCancel(true);
manager =(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, notification.build());
}
}
The receiver file:
public class MSGReceiver extends WakefulBroadcastReceiver {
//Call a new intent and grab the data passed from the nodejs (extras)
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
Intent msgrcv = new Intent(context, MSGService.class);
msgrcv.putExtra("notifyFromUserId", extras.getString("notifyFromUserId"));
msgrcv.putExtra("notifyMsg", extras.getString("notifyMsg"));
msgrcv.putExtra("notifyItemId", extras.getString("notifyItemId"));
msgrcv.putExtra("notifyItemName", extras.getString("notifyItemName"));
msgrcv.putExtra("notifyFromName", extras.getString("notifyFromName"));
msgrcv.putExtra("notifyType", extras.getInt("notifyType"));
LocalBroadcastManager.getInstance(context).sendBroadcast(msgrcv);
startWakefulService(context,msgrcv);
setResultCode(Activity.RESULT_OK);
}
}
What response you receive from GCM server when try to send push message? Please post response here. Also you can diagnose where is your problem with my test push server help.
In MSGReceveier.onReceve you do unneceessary work when repack intent. Just set component for existing intent and pass it to your service:
onReceive(Context context, Intent intent) {
intent.setComponent(new ComponentName(context.getPackageName(),
MSGService.class.getName());
startWakefulService(context,msgrcv);
setResultCode(Activity.RESULT_OK);
}
In my Android app, I use the Mobile Backend Starter from Google. I'd like to get a notification when the CloudEntities on the server get updated, and this notification should contain some data from the updated Entity. It works when the app is running in the background, but when I close the app (by swiping it away in the multitasking view), I can't make such a notification because I haven't got access to the CloudBackendAsync in the GCMIntentService.
I already saw this question:
Mobile Backend handle continuous queries in background
But it doesn't have a solution for the problem of accessing the cloud data in the GCMIntentService.
EDIT: My current code in GCMIntentService.java
protected void onHandleIntent(Intent intent) {
//... (Check if the GCM Message is about an update of the Mobile Backend)
// dispatch message
if (GCM_TYPEID_QUERY.equals(typeId)) {
// Here, a broadcast is sent to the Main Activity of the app, which then downloads
// the new content and shows a notification in the CloudCallbackHandler. That
// only works when the Activity is running.
// So I would like to get access to the CloudBackendAsync instance from
// the app here to download data in the background and show a notification.
Intent messageIntent = new Intent(BROADCAST_ON_MESSAGE);
messageIntent.putExtras(intent);
messageIntent.putExtra("token", tokens[2]);
LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
}
//...
}
The Android client does not receive the message content through the push notification event from the backend (only the subId token is sent from the demo backend which is enough to notify the client that some new message has been received for the given topic and refresh it).
So as I understand, it is not possible to directly get the entity data within the client GCMIntentService.onHandleIntent() method unless we change the backend code. I have made the following changes in the backend class ProspectiveSearchServlet so that it includes as well the message content within the push notification:
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// Return if push notification is not enabled
if (!backendConfigManager.isPushEnabled()) {
log.info("ProspectiveSearchServlet: couldn't send push notification because it is disabled.");
return;
}
// dispatch GCM messages to each subscribers
String[] subIds = req.getParameterValues("id");
// Each subId has this format "<regId>:query:<clientSubId>"
for (String subId : subIds) {
String regId = SubscriptionUtility.extractRegId(subId);
if (isSubscriptionActive(regId)) {
Entity matchedEntity = ProspectiveSearchServiceFactory.getProspectiveSearchService().getDocument(req);
if(matchedEntity != null) {
log.info(String.format("ProspectiveSearchServlet: matchedEntity.toString: " + matchedEntity.toString()));
} else {
log.info(String.format("ProspectiveSearchServlet: matchedEntity is null."));
}
//Add the matchedEntity object.
sendPushNotification(regId, subId, matchedEntity);
} else {
SubscriptionUtility.clearSubscriptionAndDeviceEntity(Arrays.asList(regId));
}
}
}
private void sendPushNotification(String regId, String subId, Entity matchedEntity) throws IOException {
SubscriptionUtility.MobileType type = SubscriptionUtility.getMobileType(subId);
if (SubscriptionUtility.MobileType.ANDROID == type) {
sendGcmAlert(subId, regId, matchedEntity);
} else if (SubscriptionUtility.MobileType.IOS == type) {
sendIosAlert(subId, new String[] {regId}, matchedEntity);
}
}
private void sendGcmAlert(String subId, String regId, Entity matchedEntity)
throws IOException {
String gcmKey = backendConfigManager.getGcmKey();
boolean isGcmKeySet = !(gcmKey == null || gcmKey.trim().length() == 0);
// Only attempt to send GCM if GcmKey is available
if (isGcmKeySet) {
Sender sender = new Sender(gcmKey);
if(matchedEntity != null) {
Message message = new Message.Builder().addData(SubscriptionUtility.GCM_KEY_SUBID, subId)
//extra data.<key> elements can be added here
.addData("data.message", (String) matchedEntity.getProperty("message"))
.addData("data.updatedBy", (String) matchedEntity.getProperty("_updatedBy"))
.addData("data.owner", (String) matchedEntity.getProperty("_owner"))
.addData("data.kindName", (String) matchedEntity.getProperty("_kindName"))
.build();
Result r = sender.send(message, regId, GCM_SEND_RETRIES);
if (r.getMessageId() != null) {
log.info("ProspectiveSearchServlet: GCM sent: subId: " + subId);
} else {
log.warning("ProspectiveSearchServlet: GCM error for subId: " + subId +
", senderId: " + gcmKey + ", error: " + r.getErrorCodeName());
ArrayList<String> deviceIds = new ArrayList<String>();
deviceIds.add(regId);
SubscriptionUtility.clearSubscriptionAndDeviceEntity(deviceIds);
}
}
} else {
// Otherwise, just write a log entry
log.info(String.format("ProspectiveSearchServlet: GCM is not sent: GcmKey: %s ",
isGcmKeySet));
}
}
Now on the client side you can make the following changes in the GCMIntentService to display a proper push notification (with the message body and the user name):
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
/*
* Filter messages based on message type. Since it is likely that GCM will be
* extended in the future with new message types, just ignore any message types you're
* not interested in, or that you don't recognize.
*/
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
Log.i(Consts.TAG, "onHandleIntent: message error");
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
Log.i(Consts.TAG, "onHandleIntent: message deleted");
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
String subId = intent.getStringExtra(GCM_KEY_SUBID);
Log.i(Consts.TAG, "onHandleIntent: subId: " + subId);
String[] tokens = subId.split(":");
String typeId = tokens[1];
// dispatch message
if (GCM_TYPEID_QUERY.equals(typeId)) {
Intent messageIntent = new Intent(BROADCAST_ON_MESSAGE);
messageIntent.putExtras(intent);
messageIntent.putExtra("token", tokens[2]);
boolean isReceived = LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);
//Check if the broadcast has been handled, if not show the notification.
if (!isReceived) {
Log.i(Consts.TAG, "A message has been recieved but no broadcast was handled.");
generateNotification(this, intent, tokens[2]);
} else {
Log.i(Consts.TAG, "A message has been recieved, broadcasted and handled.");
}
}
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GCMBroadcastReceiver.completeWakefulIntent(intent);
}
public static void generateNotification(Context context, Intent intent, String message) {
//Event keys
HashMap data = new HashMap();
for (String key : intent.getExtras().keySet()) {
Log.d(Consts.TAG, "Message key: " + key + " value: " + intent.getExtras().getString(key));
String eventKey = key.startsWith("data.") ? key.substring(5) : key;
data.put(eventKey, intent.getExtras().getString(key));
}
CharSequence contentTitle = (CharSequence) data.get("updatedBy");
if (contentTitle == null) contentTitle = "New Message";
CharSequence contentText = (CharSequence) data.get("message");
if (contentText == null) contentText = "";
CharSequence userId = (CharSequence) data.get("updatedBy");
Bitmap iconBitmap = getUserIcon(context, userId.toString());
if (iconBitmap == null) iconBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
// Creates an Intent for the Activity
Intent resultIntent = new Intent(context, GuestbookActivity.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(context);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(IntroductionActivity.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);
Notification.Builder mBuilder = new Notification.Builder(context);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder
.setContentTitle(contentTitle)
.setContentText(contentText)
.setSmallIcon(R.drawable.notification_icon)
.setLargeIcon(iconBitmap)
.setTicker(contentTitle + ": " + contentText)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.build();
///Get the notification ID, /it allows to update the notification later on.
int notifyID = 1;
String contentID = (String) data.get("id");
if(contentID != null) {
notifyID = Integer.parseInt(contentID);
}
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(notifyID, notification);
}