I migrated to Firebase Cloud Messaging for push notifications. Every thing works great , I get notifications whenever the app is open or running in background , but when the app is closed and a message is sent from the server then you don't receive it in the device ( obviously ). Now when I reopen the app , I should get the pending notification ( the notification sent while the app was closed ) but I don't get the notification.
This is my FireBaseMessagingService class
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static String TAG="Firebase";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getData().get("message"));
notification(remoteMessage.getData().get("message"));
}
void notification(String s)
{
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.mipmap.logo);
mBuilder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
mBuilder.setContentTitle("App");
mBuilder.setContentText(s);
mBuilder.setAutoCancel(true);
Intent resultIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(101,mBuilder.build());
}
}
This is my FirebaseInstance class
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
public static String TAG="Firebase";
#Override
public void onTokenRefresh() {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
}
}
AndroidManifest.xml -
<service
android:name=".Helpers.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".Helpers.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Is it possible to get the Pending Notification when the app is relaunched ?
i think it is possible since you're using a service, but android won't let you receive it until you add some sort of permission. Research for what permission will make this condition possible, and please update us.
add the following permission, then u should be good.
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Related
I can receive push notification when my app is in foreground or background
I added FcmBroadcastReceiver extends WakefulBroadcastReceiver in order to get push
when I close my application.
But I continue without receiving notifications when the app is closed.
Thanks for your help.
manifest.xml
<pre>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="<package>.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.package.name.permission.C2D_MESSAGE" />
<receiver
android:name="<package>.Notification.FcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="<package>" />
</intent-filter>
</receiver>
<service android:name=".Notification.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
public class FcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("receiver","okey");
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
MyFirebaseMessagingService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
public class MyFirebaseMessagingService extends FirebaseMessagingService {
Intent i;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
System.out.println("******************** + getMessageType "+remoteMessage.getMessageType());
System.out.println("******************** + getFrom "+remoteMessage.getFrom());
System.out.println("******************** + getMessageId "+remoteMessage.getMessageId());
System.out.println("******************** + getTo "+remoteMessage.getTo());
System.out.println("******************** + getData "+remoteMessage.getData());
System.out.println("******************** + getData().get(message) "+remoteMessage.getData().get("message"));
System.out.println("******************** + getData().get(title) "+remoteMessage.getData().get("title"));
showNotification(remoteMessage.getData().get("type"),remoteMessage.getNotification().getTitle(),remoteMessage.getNotification().getBody());
}
private void showNotification(String to , String title, String message) {
i = new Intent(this,ProfileActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i, PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setContentTitle(title)
.setContentText(message)
.setSound(defaultSoundUri)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(0,builder.build());
}
}
<code>
The issue that I can see in your code is that you are implementing the FireBase push notification but you are trying to implement that in a way that was used to implement GCM. You don't need to set any Broadcast Receivers, Firebase is doing that by itself. You just have to run "FirebaseMessagingService". The services looks like this:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
// 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.
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
}
}
As you can see it has it's own "onMessageReceived" method that takes care of Broadcast Receiver's functionality.
Check this tutorial, it will help you to understand:
https://www.codementor.io/flame3/send-push-notifications-to-android-with-firebase-du10860kb
Note: If you want your app to work in each situation even app is in background, foreground or even closed then you need to send some data through payload in your notification.then it will work for all conditions. To do that you need your own server, Firebase doesn't facilitate for that.
My GCM Service is not working. I have declared a few things in my manifest file which looks something like:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.google.android.c2dm.permission.SEND"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<permission android:name="com.xxxx.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.xxxx.xxxxxx.permission.C2D_MESSAGE" />
<receiver android:name=".core.push.receiver.GCMBroadcastReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.SEND" />
<category android:name="com.xxxx.xxxxxx" />
</intent-filter>
</receiver>
<service android:name=".core.push.service.GCMIntentService" />
My Broadcast receiver code looks like:
public class GCMBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
ComponentName messageProcessingService = new ComponentName(context.getPackageName(), GCMIntentService.class.getName());
context.startService(intent.setComponent(messageProcessingService));
setResultCode(Activity.RESULT_OK);
}
}
My Intent Service:
public class GCMIntentService extends IntentService
{
private static final int NOTIFICATION_NEW_MESSAGE = 0;
public GCMIntentService()
{
super(GCMIntentService.class.getSimpleName());
}
#Override
protected void onHandleIntent(Intent intent)
{
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty())
{
if (!GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType))
{
return;
}
// TODO Make more efficient. Load message stream here, not in two places later!
int newUnreadCount = MessagingController.getInstance().getUnreadCount() + 1;
MessagingController.getInstance().prepareStream();
MessagingController.getInstance().setUnreadCount(newUnreadCount);
final boolean isUserAuthenticated = !TextUtils.isEmpty(AuthenticationController.getInstance().getAuthToken());
if (isUserAuthenticated)
{
new Handler(Looper.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
App.from(GCMIntentService.this).fire(MessagingEvent.NEW_MESSAGE);
}
});
}
else
{
displayNotification(newUnreadCount + " New Message" + (newUnreadCount > 1 ? "s" : ""), newUnreadCount);
}
}
}
private void displayNotification(CharSequence message, int eventCount)
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean shouldDisplayMessages = preferences.getBoolean("notifications_new_message", true);
if (!shouldDisplayMessages)
{
return;
}
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent openMessagingScreen = new Intent(this, LandingActivity.class);
openMessagingScreen.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
openMessagingScreen.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
preferences.edit().putBoolean(MessagingFragment.PREF_MESSAGE_WAITING, true).apply();
PendingIntent notificationAction = PendingIntent.getActivity(this, 0, openMessagingScreen, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setContentText(message)
.setAutoCancel(true)
.setContentIntent(notificationAction)
.setNumber(eventCount);
Notification notification = notificationBuilder.build();
notification.defaults |= Notification.DEFAULT_ALL;
try
{
notificationManager.notify(NOTIFICATION_NEW_MESSAGE, notification);
}
catch (SecurityException ex)
{
// This is required due to a bug in android
// http://stackoverflow.com/questions/13602190/java-lang-securityexception-requires-vibrate-permission-on-jelly-bean-4-2
Log.e("PPDirect", ex.getLocalizedMessage());
}
}
}
I had several questions regarding push notifications:
which call back function actually checks for arrived message and is called once push notification arrives?
Is it possible that since google have updated GCM to FCM I need to make updates to the key or migrate GCM to FCM?
Can there be some other reason?
Any help in the matter would be much appreciated.
1. which call back function actually checks for arrived message and is called once push notification arrives?
For Android, it's commonly received in onMessageReceived in the GcmListenerService. However, it may also depend whether or not the app is in background or foreground.
2. Is it possible that since google have updated GCM to FCM I need to make updates to the key or migrate GCM to FCM?
As per the note here:
Starting from Sept. 2016 new server key can only be created in the Firebase Console using the Cloud Messaging tab of the Settings panel. Existing projects that need to create a new server key can be imported in the Firebase console without affecting their existing configuration.
New users of GCM is in need of creating a Firebase projext, regardless if you are going to use FCM or not, in order to have a Server Key. For the migration steps, you can see my answer here.
3. Can there be some other reason?
This is too broad to answer. Maybe it's because of your payload structure or the implementation of your onMessageReceived(), etc.
I'm developing an app using Quickblox to create a chat with users. I've managed to get push services within the app, even when its in background but, once the app is force closed no push is received.
My android devices are registering on GMC QB services, the token appears and it registers with no problem.
Moreover I've even tried using the Push Admin on Quickblox but Push are not working either.
sourcecode:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<permission
android:name="com.myapp.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.myapp.app.permission.C2D_MESSAGE" />
<receiver
android:name="com.quickblox.chat.push.QBGcmBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.myapp.app" />
</intent-filter>
</receiver>
<service android:name="com.quickblox.chat.push.QBGcmIntentServiceNewVersion"/>
<!-- CUSTOM -->
<service
android:name="com.myapp.app.push.CPInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name="com.myapp.app.push.CPRegistrationIntentService"
android:exported="false" />
And my BroadcastReceiver:
public class QBGcmBroadcastReceiver extends WakefulBroadcastReceiver {
public static int QBNotificationID = 4444;
#Override
public void onReceive(Context context, Intent intentReceived) {
Log.e(CPApplication.TAG, "QBGcmBroadcastReceiver -> Push RECIBIDA");
Log.e(CPApplication.TAG, "APP is ON ?() -> " + CPApplication.appIsON);
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(), QBGcmIntentServiceNewVersion.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intentReceived.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
// App is not running
if (!CPApplication.appIsON) {
// Is New Message Push enabled ?
boolean isPushNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_PUSH_NEW_MESSAGE, true);
// Is the user registered
boolean rememberPassword = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_REMEMBER_PASSWORD, false);
if (rememberPassword && isPushNewMessage) {
// Notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(CPApplication.getInstance());
builder.setSmallIcon(R.drawable.push_icon)
.setTicker("Nuevo mensaje")
.setAutoCancel(true)
.setContentTitle(CPApplication.getInstance().getString(R.string.app_name))
.setContentText("Tiene un mensaje nuevo");
// Is New Message Sound enabled ?
boolean isSoundNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_SOUND_NEW_MESSAGE, true);
if (isSoundNewMessage) {
builder.setDefaults(Notification.DEFAULT_SOUND);
}
// Intent
Intent intent = new Intent(CPApplication.getInstance(), SplashActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(CPApplication.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Notification
Notification note = builder.build();
// Will show lights and make the notification disappear when the presses it
note.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
NotificationManager manager = (NotificationManager) CPApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(QBNotificationID, note);
}
}
}
}
I've also created an intent service class:
public class QBGcmIntentServiceNewVersion extends IntentService {
public static int QBNotificationID = 4444;
public QBGcmIntentServiceNewVersion() {
super(QBPushConstants.GCM_INTENT_SERVICE);
}
#Override
protected void onHandleIntent(Intent intentReceived) {
Log.i(CPApplication.TAG, "QBGcmIntentServiceNewVersion :: onHandleIntent");
// App is not running
// if (!CPApplication.appIsON) {
// Is New Message Push enabled ?
boolean isPushNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_PUSH_NEW_MESSAGE, true);
// Is the user registered
boolean rememberPassword = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_REMEMBER_PASSWORD, false);
if (rememberPassword && isPushNewMessage) {
// Notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(CPApplication.getInstance());
builder.setSmallIcon(R.drawable.push_icon)
.setTicker("Nuevo mensaje")
.setAutoCancel(true)
.setContentTitle(CPApplication.getInstance().getString(R.string.app_name))
.setContentText("Tiene un mensaje nuevo");
// Is New Message Sound enabled ?
boolean isSoundNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_SOUND_NEW_MESSAGE, true);
if (isSoundNewMessage) {
builder.setDefaults(Notification.DEFAULT_SOUND);
}
// Intent
Intent intent = new Intent(CPApplication.getInstance(), SplashActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(CPApplication.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Notification
Notification note = builder.build();
// Will show lights and make the notification disappear when the presses it
note.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
NotificationManager manager = (NotificationManager) CPApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(QBNotificationID, note);
}
// }
}
}
Thank you
Sorry, but I was putting the token instead of the deviceID, so it appears as a new registered device on QB admin, but with the wrong info, and that was the problem. I was using the new method from QB
new SendPushTokenToQBTask(token, deviceId).execute();
instead of
new SendPushTokenToQBTask(deviceId, token).execute()
Thank you anyways
Posting your permissions might also help but you didn't change the name in the receiver to your package name:
android:name="com.quickblox.chat.push.QBGcmBroadcastReceiver"
try changing it to:
android:name="com.myapp.app.QBGcmBroadcastReceiver"
if it doesn't work edit your question an add your permissions. Hope it helps.
I'm using the new GoogleCloudMessaging API (from Play Services library, because old Google cloud messaging for android was deprecated) in my project and I have some bugs. When I send messages from my server to all registered devices, my nexus 4 (android 4.4) receives the notification messages, but my Samsung Galaxy Ace doesn't receive them, That's strange, because there are no exceptions or crashes of my project.
Any ideas?
Thanks.
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="ru.test"
android:installLocation="preferExternal"
android:versionCode="1"
android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/MyTheme" >
<service android:name=".GcmIntentService" />
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>
<activity
android:name="ru.test.MainActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
GcmBroadcastReceiver.java
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String regId = intent.getExtras().getString("registration_id");
if(regId != null && !regId.equals("")) {
/* Do what ever you want with the regId eg. send it to your server */
Log.d(MainActivity.tag, "onReceive " + regId);
}
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
GcmIntentService.java
public class GcmIntentService extends IntentService {
public static int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
static final String TAG = "myLogs";
String title = "";
String message = "";
String subtext = "";
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
title = extras.getString("title");
message = extras.getString("message");
subtext = extras.getString("subtext");
/*
* 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)) {
message = "Send error";
sendNotification(title, message, subtext);
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_DELETED.equals(messageType)) {
message = "Deleted messages on server";
sendNotification(title, message, subtext);
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// Post notification of received message.
sendNotification(title, message, subtext);
Log.d(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(String title, String message, String subtext) {
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, SplashScreen.class), 0);
NotificationCompat.BigTextStyle bigxtstyle =
new NotificationCompat.BigTextStyle();
bigxtstyle.bigText(message);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_small)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_large))
.setTicker(message)
.setContentTitle(title)
.setDefaults(Notification.DEFAULT_ALL | Notification.FLAG_AUTO_CANCEL)
//.setContentInfo("Content info")
.setAutoCancel(true)
.setSubText(subtext)
.setWhen(System.currentTimeMillis())
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setContentText(message);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(++NOTIFICATION_ID, mBuilder.build());
}
}
Your main package name is ru.test, but in the GCM permissions you specified com.example.gcm as the package name. That's why it doesn't work in 2.x Android version (for some reason this mismatch doesn't affect 4.x versions).
The following changes will solve your problem:
<permission android:name="ru.test.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="ru.test.permission.C2D_MESSAGE" />
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="ru.test" />
</intent-filter>
</receiver>
I also suggest that you change your minSdkVersion from 7 to 8, since GCM is not supported in API level 7.
Your Google Play application is updated in Galaxy Ace? Probably this is the problem.
Another hypothesis would not be logged into any google account on the device. to receive notifications in versions prior to 4.0.4 is mandatory to be logged in at least one regard.
Does anybody can help me with a working example for receiving messages from gcm using Google Cloud Messaging for Android. I have tried both ways (helper library and GoogleCloudMessaging class) and nothing seems to work. I'm using a PHP script that shows the following:
Multicast ID: 5.2108110103215E+18
Number of messages processed successfully: 1
Number of messages with processing errors: 0
Canonical IDs: 0
So apparently everithing is OK. I could register the device in both ways, using the helper library (gcm.jar) and using GoogleCloudMessaging class. The problem is that there is no way the message I send via PHP arrives, or at least I don't know how to handle it correctly. Here are the permissions and the receiver from my manifest:
<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.gcm" />
</intent-filter>
</receiver>
<service android:name=".GCMIntentService" />
Finally here is the service class
public class GCMIntentService extends GCMBaseIntentService {
private static final String PROJECT_ID = "49XXXXXXXX6";
private static final String TAG = "GCM Intent Service";
public GCMIntentService()
{
super(PROJECT_ID);
Log.d(TAG, "GCMIntentService init");
}
#Override
protected void onError(Context ctx, String sError) {
Log.d(TAG, "Error: " + sError);
}
#Override
protected void onMessage(Context ctx, Intent intent) {
Log.d(TAG, "Message Received");
String message = intent.getStringExtra("message");
sendGCMIntent(ctx, message);
}
private void sendGCMIntent(Context ctx, String message) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("GCM_RECEIVED_ACTION");
broadcastIntent.putExtra("gcm", message);
ctx.sendBroadcast(broadcastIntent);
}
#Override
protected void onRegistered(Context ctx, String regId) {
Log.d(TAG, regId);
// Notify main UI to update registration status
Intent registrationIntent = new Intent();
registrationIntent.setAction("registered");
registrationIntent.putExtra("regId", regId);
sendBroadcast(registrationIntent);
}
#Override
protected void onUnregistered(Context ctx, String regId) {
//...
}
}
Here is the code when using the GoogleCloudMessaging class (I changed the manifest to use the custom receiver):
public class GCMBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "GCM Receiver";
public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
private Context ctx;
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Message received");
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
ctx = context;
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error: " + intent.getExtras().toString());
}
else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ intent.getExtras().toString());
}
else {
sendNotification("Received: " + intent.getExtras().toString());
}
setResultCode(Activity.RESULT_OK);
}
// Put the GCM message into a notification and post it.
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
new Intent(ctx, MainActivity.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
ctx).setSmallIcon(R.drawable.ic_launcher_temp)
.setContentTitle("GCM Notification")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
The thing is that everything seems to be ok, but the message never arrives. Any ideas??
Thanks in advance.
Add the following in your manifeast
<permission
android:name="PACKAGE_NAME.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="PACKAGE_NAME.permission.C2D_MESSAGE" />
<!-- App receives GCM messages. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
Your manifest is missing some permissions :
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
EDIT :
In your manifest you are using com.google.android.gcm.GCMBroadcastReceiver. That's a class from the old helper library (gcm.jar) which starts an intent service. If you want to use the helper library you should define the intent service in your manifest.
If you don't want to use the helper library, you should change the package of GCMBroadcastReceiver in the manifest to be the package of the GCMBroadcastReceiver class that you included in your question. Otherwise, that class won't be used.
After correcting the issues above still no push messages. The problem was the 403 error. Looks like that service is not available in Cuba, so the solution is to use a tool like "your freedom" or "thor", etc.
Don't forget to change 'com.example.gcm' to your package name e.g. 'com.yourdomain.yourapp'
You are using GCMBaseIntentService which has been deprecated by Google. (But it should be still working.) I followed the latest tutorial http://developer.android.com/google/gcm/client.html and did receive messages. You can try it too.
Another possible reason is you may have received a message but it was not shown in a notification successfully. Add this line in the method: sendNotification(String msg)
Log.i(TAG, msg);