I am using FCM in my android project and is working fine when app is running. But when the app is killed or closed onReceiveMessage is not called. I have tried by sending message using only data playload also still it is not working. Is there any any solution. Thanks in advance
Try this code it will solve your problem. MyFirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Title: " + remoteMessage.getNotification().getTitle());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
sendNotification("", "");
}
// [END receive_message]
/**
* Create and show a simple notification containing the received FCM message.
*
* #param messageBody FCM message body received.
*/
private void sendNotification(String xyz, String abc) {
Intent intent = new Intent(this, MainActivity.class);
Bundle b = new Bundle();
b.putString("key", xyz);
b.putString("key", abc);
intent.putExtras(b);
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)
.setContentTitle("title")
.setContentText("body")
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
boolean useSilhouette = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
if (useSilhouette) {
try {
notificationBuilder.setSmallIcon(R.mipmap.ic_sillate);
} catch (Exception e) {
notificationBuilder.setSmallIcon(R.mipmap.ic_sillate);
}
} else {
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher);
}
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//Random id number for notification
Random random = new Random();
int m = random.nextInt(9999 - 1000) + 1000;
notificationManager.notify(m/* ID of notification */, notificationBuilder.build());
}
}
Get values via getIntent() in MainActivity and do what you want to do ;)
Related
This is my first question. I have connected my domain into firebase. The push notification is working when I update the post in my Wordpress Blog. Ok, thats good for now. But, i want to save all that notification in a Fragment, and can be clicked from there to start an activity for post id. How to save that Notification?
Here is my Firebase Messaging code:
private static int VIBRATION_TIME = 500; // in millisecond
private SharedPref sharedPref;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
sharedPref = new SharedPref(this);
if (sharedPref.getNotification()) {
// play vibration
if (sharedPref.getVibration()) {
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(VIBRATION_TIME);
}
RingtoneManager.getRingtone(this, Uri.parse(sharedPref.getRingtone())).play();
if (remoteMessage.getData().size() > 0) {
Map<String, String> data = remoteMessage.getData();
FcmNotif fcmNotif = new FcmNotif();
fcmNotif.setTitle(data.get("title"));
fcmNotif.setContent(data.get("content"));
fcmNotif.setPost_id(Integer.parseInt(data.get("post_id")));
displayNotificationIntent(fcmNotif);
}
}
}
private void displayNotificationIntent(FcmNotif fcmNotif) {
Intent intent = new Intent(this, ActivitySplash.class);
if (fcmNotif.getPost_id() != -1) {
intent = new Intent(this, ActivityPostDetails.class);
Post post = new Post();
post.title = fcmNotif.getTitle();
post.id = fcmNotif.getPost_id();
boolean from_notif = !ActivityMain.active;
intent.putExtra(ActivityPostDetails.EXTRA_OBJC, post);
intent.putExtra(ActivityPostDetails.EXTRA_NOTIF, from_notif);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(fcmNotif.getTitle());
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(fcmNotif.getContent()));
builder.setContentText(fcmNotif.getContent());
builder.setSmallIcon(R.drawable.ic_notification);
builder.setDefaults(Notification.DEFAULT_LIGHTS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder.setPriority(Notification.PRIORITY_HIGH);
}
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int unique_id = (int) System.currentTimeMillis();
notificationManager.notify(unique_id, builder.build());
}
}
yes you can store the your Notification payload in database and create list in fragment and show data from Database and click on any row start activity according to Post ID by getting post id by position
You can save notification message when the notificaton arrived inside
onMessageReceived(RemoteMessage remoteMessage)
method like this
A full example of a notification is like this..
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
// TODO(developer): Handle FCM messages here.
Map<String, String> data = remoteMessage.getData();
String value1 = data.get("key_1");
String value2 = data.get("key_2");
String title=data.get("title");
String msg=data.get("body");
Log.d("Backgraound", value1);
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
sendNotification(title,msg,value1,value2);
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
private void sendNotification(String title,String messageBody, String val1,String val2) {
try {
Intent intent = new Intent(this, Notification_activity.class);
//Bundle bundle = getApplicationContext().getExtras();
Bundle basket = new Bundle();
basket.putString("key_1", val1);
basket.putString("key_2", val2);
intent.putExtras(basket);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.spacebar_round)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setColor( getResources().getColor(R.color.colorPrimary))
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher));
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
}
I am developing an app that works with FirebaseMessagingService and NotificationCompat. My target API is 26. The problem I have is that notifications in android 7.1.1 appear and close at once, they are not kept in the notification bar. However, in Android 7.0 it works perfectly. I saw many tutorials and in all they do the same thing that I do. I would like to know what I may be missing.
My Services
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Map data = remoteMessage.getData();
if (SinchHelpers.isSinchPushPayload(data)) {
//comentario
} else {
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload => " + remoteMessage.getData());
Map<String, String> params = remoteMessage.getData();
JSONObject object = new JSONObject(params);
try {
sendNotification(object.get("message").toString(), object.get("chatId").toString(), object.get("user").toString());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG, "JSONException => " + e.getMessage());
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body => " + remoteMessage.getNotification().getBody());
}
}
}
}
private void sendNotification(String messageBody, String chatId, String userName) {
try {
Intent intent = new Intent(this, ChatActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXTRA_CHAT_ID", chatId);
intent.putExtra("EXTRA_USER", userName);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent, PendingIntent.FLAG_ONE_SHOT);
String channelId = "fcm_default_channel";
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher_foreground)
.setContentTitle(userName)
.setContentText(messageBody)
.setAutoCancel(true)
.setGroup(userName)
.setSound(defaultSoundUri)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
} catch (Exception e) {
Log.e(TAG, "userName => " + userName + " => " + e.getMessage());
}
}
Notification channels: Android 8.0 introduces notification channels that allow you to create a user-customizable channel for each type of notification you want to display.
Please have a look at the documentation.
Build a notification.
I am making a simple messaging app using firebase cloud messaging service but and I am using cloud functions to handle the notifications, however whenever I test it it always says successful in the logs but the devices receive nothing
Here is the cloud function used :
exports.sendNotifications = functions.database.ref('/meesages/{messageId}').onCreate(event => {
var eventSnapshot = event.data;
var str1 = "Sender : ";
var str = str1.concat(eventSnapshot.child("messageOwner").val());
console.log(str);
var topic = "Messaging";
var payload = {
notification: {
Message: eventSnapshot.child("messageText").val(),
Sender: eventSnapshot.child("messageOwner").val()
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(topic,payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
Here is the class responsible for handling the notifications part on the android device :
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
showNotification(remoteMessage.getData().get("Sender"), remoteMessage.getData().get("Message"));
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
#Override
public void onDeletedMessages() {
super.onDeletedMessages();
}
private void showNotification(String Message, String Sender) {
Intent intent = new Intent(this, MainActivity.class);
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 = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setContentTitle("New message : " + Message)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentText("By : " + Sender)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
and yes I made sure to add the topic subscription in the mainactivity class
FirebaseMessaging.getInstance().subscribeToTopic("Messaging");
so what is exactly wrong here ??
The code in onMessageReceived() expects the message to have a data payload. This is explained in the documentation, which includes three tabs, showing notification, data, and combined payloads. Change notification to data:
var payload = {
data: {
Message: eventSnapshot.child("messageText").val(),
Sender: eventSnapshot.child("messageOwner").val()
}
};
GcmListenerService is not called when application is in background or when phone is locked or in sleep mode but notification is fired. How this will be called
When App is in foreground its working ideally.
Code for GcmListenerService is following
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
LocalDataBaseManager mDbManager;
String message;
Random randomNumber;
long ID;
/**
* Called when message is received.
*
* #param from SenderID of the sender.
* #param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
#Override
public void onMessageReceived(String from, Bundle data) {
String message ;
String title;
// ID = Utils.getIDForPush("pushId",this);
// if(ID == 0){
// ID = 1;
// }else {
// ID += 1;
// }
// Utils.saveIDForPush("pushId",ID,this);
Bundle bundle = data.getBundle("notification");
if(bundle!= null){
message = bundle.getString("body");
title = bundle.getString("title");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);}
else {
message ="";
title = "NCMS";
}
mDbManager = LocalDataBaseManager.getInstance(this);
if (from.startsWith("/topics/")) {
Calendar c = Calendar.getInstance();
SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss");
String format = s.format(new Date());
ID = Long.parseLong(format);
String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date());
Warnings warnings = new Warnings();
warnings.setWARNING_ID(ID);
warnings.setWARNING_EN(message);
warnings.setWARNING_AR(message);
warnings.setSTART_DATE_TIME(date);
warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH));
warnings.setSEVERITY("");
warnings.setEND_DATE_TIME("");
warnings.setUPDATE_NO("");
mDbManager.insertNotificationInfo(warnings);
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
// KeyguardManager km = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE);
// boolean locked = km.inKeyguardRestrictedInputMode();
//
// String release = android.os.Build.VERSION.RELEASE;
//
//
// if (Integer.parseInt(String.valueOf(release.charAt(0))) < 5 && locked) {
//
// this.stopService(new Intent(this, NotificationService.class));
// Intent serviceIntent = new Intent(this, NotificationService.class);
// this.startService(serviceIntent);
//
// }
sendNotification(title,message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* #param message GCM message received.
*/
private void sendNotification(String title,String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("message",message);
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.drawable.ncms_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
Manifest info for this service is following
<service
android:name=".gcm.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
What I am missing here.
It appears the heart of this issue is actually a server-side issue. If the server is sending notification messages, onMessageReceived won't be called if the app is in the background. The server should actually be sending data messages.
GCM Docs discuss the difference.
Basically, the payload of the message should have a data key such as
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data" : {
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
},
}
and NOT a notification key such as
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon"
}
}
More specifically, the GCM Docs state that messages sent including both data and notification payloads will be treated differently depending on if the app is in the foreground or background:
App behavior when receiving messages that include both notification and data payloads depends on whether the app is in the background, or the foreground —essentially, whether or not it is active at the time of receipt.
When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
When in the foreground, your app receives a bundle with both payloads available.
This github thread also has a good explanation:
So there are two kinds of GCM messages:
Notification Messages - these are intended to generate a notification with no intermediate processing by the application. They only hit onMessageReceived if the app is running.
Data Messages - these are intended to silently pass data to the app's messaging service. They hit onMessageReceived even if the app is in the background. The service may then choose to generate a notification using the normal system notification APIs, or it may choose to handle the message silently.
The Issue I was facing was when Application is in background or force closed then notification is fired but not through GcmListenService but through GCMReceiver
So I extended GCMReceiver and made it something like this with this when application is in foreground or in background or force killed. it will be called
GCMListenerService after modification is as following
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
LocalDataBaseManager mDbManager;
String message;
Random randomNumber;
long ID;
/**
* Called when message is received.
*
* #param from SenderID of the sender.
* #param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
#Override
public void onMessageReceived(String from, Bundle data) {
String message ;
String title;
// ID = Utils.getIDForPush("pushId",this);
// if(ID == 0){
// ID = 1;
// }else {
// ID += 1;
// }
// Utils.saveIDForPush("pushId",ID,this);
Bundle bundle = data.getBundle("notification");
if(bundle!= null){
message = bundle.getString("body");
title = bundle.getString("title");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);}
else {
message ="";
title = "NCMS";
}
mDbManager = LocalDataBaseManager.getInstance(this);
if (from.startsWith("/topics/")) {
Calendar c = Calendar.getInstance();
SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss");
String format = s.format(new Date());
ID = Long.parseLong(format);
String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date());
Warnings warnings = new Warnings();
warnings.setWARNING_ID(ID);
warnings.setWARNING_EN(message);
warnings.setWARNING_AR(message);
warnings.setSTART_DATE_TIME(date);
warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH));
warnings.setSEVERITY("");
warnings.setEND_DATE_TIME("");
warnings.setUPDATE_NO("");
mDbManager.insertNotificationInfo(warnings);
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
// KeyguardManager km = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE);
// boolean locked = km.inKeyguardRestrictedInputMode();
//
// String release = android.os.Build.VERSION.RELEASE;
//
//
// if (Integer.parseInt(String.valueOf(release.charAt(0))) < 5 && locked) {
//
// this.stopService(new Intent(this, NotificationService.class));
// Intent serviceIntent = new Intent(this, NotificationService.class);
// this.startService(serviceIntent);
//
// }
sendNotification(title,message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* #param message GCM message received.
*/
private void sendNotification(String title,String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("message",message);
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.drawable.ncms_launcher)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
and GCM Receiver is as following
public class GcmBroadcastReceiver extends GcmReceiver {
LocalDataBaseManager mDbManager;
#Override
public void onReceive(Context context, Intent intent) {
mDbManager = LocalDataBaseManager.getInstance(context);
Bundle bundle = intent.getExtras();
bundle.keySet();
Set<String> keySet = bundle.keySet();
if(keySet != null && keySet.isEmpty() == false) {
Iterator<String> it = keySet.iterator();
int i = 0;
while(it.hasNext()){
String key = it.next();
String desc = bundle.getString(key);
Log.d("BroadCast Values",key +" "+desc);
}
}
Log.d("", "In Receive Method of Broadcast Receiver");
if (bundle != null && bundle.containsKey("gcm.notification.body")) {
String message = bundle.getString("gcm.notification.body","");
Long ID = new Date().getTime();
String date = new SimpleDateFormat("dd-MM-yyyy HH:mm", Locale.ENGLISH).format(new Date());
Warnings warnings = new Warnings();
warnings.setWARNING_ID(ID);
warnings.setWARNING_EN(message);
warnings.setWARNING_AR(message);
warnings.setSTART_DATE_TIME(date);
warnings.setNotification_type(String.valueOf(Constant.NotificationType.PUSH));
warnings.setSEVERITY("");
warnings.setEND_DATE_TIME("");
warnings.setUPDATE_NO("");
mDbManager.insertNotificationInfo(warnings);
// message received from some topic.
}
super.onReceive(context, intent);
// ComponentName cn = new ComponentName(context.getPackageName(), RegistrationIntentService.class.getName());
// startWakefulService(context, intent.setComponent(cn));
// setResultCode(Activity.RESULT_OK);
}
}
Manifest changes for GCMReceiver is following
<receiver
android:name=".gcm.GcmBroadcastReceiver"
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.uae.ncms" />
</intent-filter>
</receiver>
<service
android:name=".gcm.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
I implemented push notification in my application. They works well when the application is opened or it is in the background but when the the application is closed a pup up message on my screen is displayed saying that a problem occurred in the application.
here there is the piece of code that implements push notifications.
public class GcmIntentService extends IntentService {
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
FeedReaderDbHelperMessages mDbHelper;
/**
* Tag used on log messages.
*/
static final String TAG = "GCM Intent";
/**
* Db access object
* */
public GcmIntentService() {
super("GcmIntentService");
}
#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)) {
sendNotification(extras);
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification(extras);
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// Post notification of received message.
sendNotification(extras);
Intent i = new Intent("android.intent.action.MAIN").putExtras(extras);
this.sendBroadcast(i);
Log.i(TAG, "Received: " + extras.toString());
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
// Put the message into a notification and post it.
// This is just one simple example of what you might choose to do with
// a GCM message.
private void sendNotification(Bundle msg) {
FacebookSdk.sdkInitialize(getApplicationContext());
Profile userProfile = Profile.getCurrentProfile();
String user_id = userProfile.getId();
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent newIntent = new Intent(this, drawnerActivity.class);
newIntent.setAction("OPEN_NOTIFICATION");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,newIntent, 0);
mDbHelper = new FeedReaderDbHelperMessages(getApplicationContext());
UpdateMessages updateMessages = new UpdateMessages(mDbHelper);
if(msg.getString("notificationType").equals("question"))
{
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo_notifica_domanda_mini)
.setContentTitle("MyApp")
.setStyle(new NotificationCompat.BigTextStyle().bigText("New question"))
.setContentText("New question");
Vibrator v = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(400);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
updateMessages.update(user_id);
}
if(msg.getString("notificationType").equals("answer"))
{
Contact userAnswer = ContactListFragment.findContactById(msg.getString("friendId"));
Timestamp notificationTimestamp = Timestamp.valueOf(msg.getString("timestamp"));
Log.i(TAG, "Answer notification received from: "+ userAnswer.getName() + " timestamp: " + notificationTimestamp.toString());
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo_mini_dialog)
.setContentTitle("MyApp")
.setStyle(new NotificationCompat.BigTextStyle().bigText("New answer"))
.setContentText(userAnswer.getName() + " answered");
Vibrator v = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern = {
0, // Start immediately
100,
100,
100
};
v.vibrate(pattern, -1);
//updateMessages.updateRowWithAnswer(msg.getString("questionId"), msg.getString("answer"));
FeedReaderDbHelperNotification mDbHelperNotifications = new FeedReaderDbHelperNotification(getApplicationContext());
UpdateNotifications updateNotifications = new UpdateNotifications(mDbHelperNotifications, mDbHelper);
updateNotifications.update(user_id);
//NotificationFragment.addNotification(new NotificationImpl(notificationTimestamp, 1, 0, msg.getString("questionId"), ""), getApplication().getApplicationContext());
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
}
the problem is a NullPointerException here String user_id = userProfile.getId();. The userProfile cames from com.facebook.Profile class because I use facebook sdk to keep session. Why is it null?
here there is the stacktrace
java.lang.NullPointerException
at com.bellantoni.chetta.lieme.GcmIntentService.sendNotification(GcmIntentService.java:80)
at com.bellantoni.chetta.lieme.GcmIntentService.onHandleIntent(GcmIntentService.java:63)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.os.HandlerThread.run(HandlerThread.java:61)
If this code block is the first time you are calling FacebookSdk.sdkInitialize then the problem is likely that the user has not logged in yet, so there is no user profile, hence the NullPointerException. I had a similar problem a while back and this was the issue.
Make sure that you are calling the Login callback from the FacebookSDK. Hope this helps.