GCM: onMessage() from GCMIntentService is called very few times - android

I am implementing GCM in my application. I have followed all the steps given in GCM tutorial from developer.android.com
My application's build target is pointing to Goolge API 8 (Android 2.2 version).
I am able to get the register ID from GCM successfully, and I am passing this ID to my application server. So the registration step is performed successfully.
Now when my application server sends a PUSH message to my device, the server gets the message as SUCCESS=1 FAILURE=0, etc., i.e. Server is sending message successfully, but my device never receives the message.
After searching alot about this, I came to know that GCM pushes messages on port number 5228, 5229 or 5230.
Initially, my device and laptop was restricted for some websites, but then I was granted all the permissions to access all websites, so I guess these port numbers are open for my device.
So my question is: Very few times, I am receiving PUSH message from GCM. Why Google is so uncertain in delivering messages?
What could be the reason?
Please see my following code and guide me accordingly:
I have declared following in my manifest:
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<permission
android:name="package.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<!-- App receives GCM messages. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- GCM connects to Google Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="package.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<receiver
android:name="com.google.android.gcm.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="packageName" />
</intent-filter>
</receiver>
<receiver
android:name=".ReceiveBroadcast"
android:exported="false" >
<intent-filter>
<action android:name="GCM_RECEIVED_ACTION" />
</intent-filter>
</receiver>
<service
android:name=".GCMIntentService"
/>
/**
* #author Shrikant.
*
*/
public class GCMIntentService extends GCMBaseIntentService {
/**
* The Sender ID used for GCM.
*/
public static final String SENDER_ID = "myProjectID";
/**
* This field is used to call Web-Service for GCM.
*/
SendUserCredentialsGCM sendUserCredentialsGCM = null;
public GCMIntentService() {
super(SENDER_ID);
sendUserCredentialsGCM = new SendUserCredentialsGCM();
}
#Override
protected void onRegistered(Context arg0, String registrationId) {
Log.i(TAG, "Device registered: regId = " + registrationId);
sendUserCredentialsGCM.sendRegistrationID(registrationId);
}
#Override
protected void onUnregistered(Context context, String arg1) {
Log.i(TAG, "unregistered = " + arg1);
sendUserCredentialsGCM
.unregisterFromGCM(LoginActivity.API_OR_BROWSER_KEY);
}
#Override
protected void onMessage(Context context, Intent intent) {
Log.e("GCM MESSAGE", "Message Recieved!!!");
String message = intent.getStringExtra("message");
if (message == null) {
Log.e("NULL MESSAGE", "Message Not Recieved!!!");
} else {
Log.i(TAG, "new message= " + message);
sendGCMIntent(context, message);
}
}
private void sendGCMIntent(Context context, String message) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("GCM_RECEIVED_ACTION");
broadcastIntent.putExtra("gcm", message);
context.sendBroadcast(broadcastIntent);
}
#Override
protected void onError(Context context, String errorId) {
Log.e(TAG, "Received error: " + errorId);
Toast.makeText(context, "PUSH Notification failed.", Toast.LENGTH_LONG)
.show();
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
return super.onRecoverableError(context, errorId);
}
}
Thanks.

Check whether the debug certificate is expired or not, If it is then create new certificate and generate new key.

Try to change your class names as full names with package names. Like:
<service android:name="com.xx.xx.xx" />
And dont forget to put your package name here:
<category android:name="packageName" />

Make sure your app name and the name you registered on the google console for getting api key are same name.Same name in the sense that exactly the same

Related

Android Push Notification service not start on Lollipop

I am facing an issue while start service for push notifications.
On Lollipop my app is crashing on start service for notifications receiver.
My start service code is.
Intent registrationIntent = new Intent(
"com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app",
PendingIntent.getBroadcast(this, 0, new Intent(), 0));
registrationIntent.putExtra("sender", "KEY");
SplashScreen.this.startService(registrationIntent);
Menifest.xml Code
<receiver
android:name="com.example.notifications.C2DMReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.app.example" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.app.example" />
</intent-filter>
</receiver>
I faced same problem in my app.
Follow this link
I hope you will solve this problem.
And little bit explanation regarding your issue.
Download and add gcm.jar in your project lib folder.
And Add below code in your java class where you want to register.
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
// Get GCM registration id
final String regId = GCMRegistrar.getRegistrationId(this);
// Check if regid already presents
if (regId.equals("")) {
// Register with GCM
GCMRegistrar.register(this, "SENDERKEY");
} else {
// Device is already registered on GCM Server
if (GCMRegistrar.isRegisteredOnServer(this)) {
String df = "dfd";
} else {
GCMRegistrar.register(this, "SENDERKEY");
}
}
Now you create a class GCMIntentService.java and below code in it.
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService ";
private static Context mContext;
public GCMIntentService() {
super("SENDERKEY");
}
#Override
protected void onRegistered(Context context, String registrationId) {
Debuger.e(TAG, "Device registered: regId = " + registrationId);
}
#Override
protected void onUnregistered(Context context, String registrationId) {
Debuger.e(TAG, "Device unregistered");
}
#Override
protected void onMessage(Context context, Intent intent) {
Debuger.e(TAG, "Received message");
mContext = context;
String message = intent.getExtras().getString("message");
if (message != null) {
Debuger.e(TAG + "onMessage", "message = " + message);
} else {
message = "";
}
}
#Override
protected void onDeletedMessages(Context context, int total) {
// Debuger.e(TAG, "Received deleted messages notification");
}
#Override
public void onError(Context context, String errorId) {
// Debuger.i(TAG, "Received error: " + errorId);
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
// log message
// Debuger.e(TAG, "Received recoverable error: " + errorId);
return super.onRecoverableError(context, errorId);
}
}
And in your AndroidMenifest.xml file add below
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<permission
android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<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="com.example.gcm.GCMIntentService" />

GCMRegistrar.getRegistrationId(this) always returns empty string (Android Push notification using GCM)

public void registerClient()
{
try
{
// Check that the device supports GCM (should be in a try / catch)
GCMRegistrar.checkDevice(this);
// Check the manifest to be sure this app has all the required
// permissions.
GCMRegistrar.checkManifest(this);
// Get the existing registration id, if it exists.
regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals(""))
{
// register this device for this project
GCMRegistrar.register(this, PROJECT_ID);
regId = GCMRegistrar.getRegistrationId(this);
regId = GCMRegistrar.getRegistrationId(this); always returns an empty string. Has GCMRegister class been deprecated?
I have added gcm jar from sdk/extras/google/gcm/gcm-client path.
i have also tried added google play service library and execute the code(removed gcm.jar) but it then says GCMRegistrar class not found exception
I have check all permissions and they seem to be right.
here is my manifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gcmclient"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="19" />
<!-- receives GCM messages -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- GCM connects to Google services -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<!-- wake the processor if a GCM message is received -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="com.example.gcmclient.permission.C2D_MESSAGE"
android:protectionLevel="signature" >
</permission>
<uses-permission android:name="com.example.gcmclient.permission.C2D_MESSAGE" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcmclient" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.gcmclient" />
</intent-filter>
</receiver>
<service android:name=".GCMIntentService" >
</service>
</application>
</manifest>
your code look like ok, but when you use GCM you must sync account from setting. follow the step.
GO To SETTING ---> Add Account--->google
They deprecated the old method of doing GCM too quickly after its introduction in my opinion.
However it appears that you are mixing up code from the old method and the new Play Services implementation. You are probably best advised to start again using this Play Services example GCM client as a starting point
I you are using GCM please put these check before calling GCM registration method :
A properly synced Google account is mandatory for Android 4.0.4 to register with GCM so you can write something like this
private boolean isGoogleAccountRequired=true;
private Account[] accounts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample);
String firmwareVersion=Build.VERSION.RELEASE;
String firmwareVersionsStrings[]=firmwareVersion.split("\\.");
int firstDigit=Integer.valueOf(firmwareVersionsStrings[0]);
int secondDigit=Integer.valueOf(firmwareVersionsStrings[1]);
int thirdDigit=0;
if(firmwareVersionsStrings.length>=3){
thirdDigit=Integer.valueOf(firmwareVersionsStrings[2]);
}
if(firstDigit>=4){
if(secondDigit>0){
isGoogleAccountRequired=false;
}else if(secondDigit==0){
if(thirdDigit>=4){
isGoogleAccountRequired=false;
}
}
}
if(isGoogleAccountRequired && !GCMRegistrar.isRegistered(this)){
boolean isGoogleAccountPresent=isGoogleAccountPresent(this);
// Check whether Google Account Present or not if not act accordingly
if(! isGoogleAccountPresent){
// Show Dialog to add google account and sync it
}else{
//Check if the account added is synced or not if not sync it programatically
boolean syncEnabled=false;
if(accounts.length>0){
syncEnabled = ContentResolver.getSyncAutomatically(accounts[0], ContactsContract.AUTHORITY);
}
if(!syncEnabled){
ContentResolver.setSyncAutomatically(accounts[0], ContactsContract.AUTHORITY, true);
}
GCMRegistrar.register(YourActivity.this,SENDER_ID);
}
}else if(!GCMRegistrar.isRegistered(this)){
GCMRegistrar.register(YourActivity.this,SENDER_ID);
}
}
Now in the GCMIntentService override these methods :
#Override
protected void onRegistered(Context arg0, String arg1) {
// TODO Auto-generated method stub
Log.i(TAG, "device is registered to GCM server with Reg ID In GCMINTENT::::"+ arg1);
}
protected void onMessage(Context context, Intent intent) {
}
#Override
public void onError(Context context, String errorId) {
Log.i(TAG, "Received error: " + errorId);
}
Please check the logs error ID in onError Message if you still not getting the Reg Id.
Add this permission for Writing sync Settings :
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>

don't receive notifications on android 2.2 using GoogleCloudMessaging

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.

Can't receive messages using Google Cloud Messaging for Android (not the helper library)

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);

GCM registration error in Samsung Galaxy ace2 but works in emulator

I am able to run my app in Samsung Galaxy ace2 in the first time. Now i am getting following error with failure to GCM registration. I works fine in emulator but not in that device. Following is the error and GCMIntentService.java.
Error:
03-21 09:25:33.110: V/GCMBaseIntentService(6018): Acquiring wakelock
03-21 09:25:33.120: V/GCMBaseIntentService(6018): Intent service name: GCMIntentService-1089764589011-11
03-21 09:25:33.130: D/GCMBaseIntentService(6018): handleRegistration: registrationId = null, error = SERVICE_NOT_AVAILABLE, unregistered = null
03-21 09:25:33.130: D/GCMBaseIntentService(6018): Registration error: SERVICE_NOT_AVAILABLE
03-21 09:25:33.130: I/GCMIntentService(6018): Received recoverable error: SERVICE_NOT_AVAILABLE
03-21 09:25:33.130: D/GCMBaseIntentService(6018): Scheduling registration retry, backoff = 98657 (96000)
03-21 09:25:33.200: V/GCMBaseIntentService(6018): Releasing wakelock
03-21 09:26:42.950: D/dalvikvm(6018): GC_CONCURRENT freed 354K, 48% free 3310K/6279K, external 630K/1286K, paused 7ms+9ms
03-21 09:27:11.800: V/GCMBroadcastReceiver(6018): onReceive: com.google.android.gcm.intent.RETRY
03-21 09:27:11.800: V/GCMBroadcastReceiver(6018): GCM IntentService class: com.dorji.finalproject.GCMIntentService
03-21 09:27:11.800: V/GCMBaseIntentService(6018): Acquiring wakelock
03-21 09:27:11.830: V/GCMBaseIntentService(6018): Intent service name: GCMIntentService-1089764589011-12
03-21 09:27:11.840: V/GCMRegistrar(6018): Registering app com.dorji.finalproject of senders 1089764589011
03-21 09:27:11.840: V/GCMBaseIntentService(6018): Releasing wakelock
03-21 09:27:12.010: V/GCMBroadcastReceiver(6018): onReceive: com.google.android.c2dm.intent.REGISTRATION
03-21 09:27:12.010: V/GCMBroadcastReceiver(6018): GCM IntentService class: com.dorji.finalproject.GCMIntentService
03-21 09:27:12.010: V/GCMBaseIntentService(6018): Acquiring wakelock
03-21 09:27:12.020: V/GCMBaseIntentService(6018): Intent service name: GCMIntentService-1089764589011-13
03-21 09:27:12.020: D/GCMBaseIntentService(6018): handleRegistration: registrationId = null, error = SERVICE_NOT_AVAILABLE, unregistered = null
03-21 09:27:12.020: D/GCMBaseIntentService(6018): Registration error: SERVICE_NOT_AVAILABLE
03-21 09:27:12.020: I/GCMIntentService(6018): Received recoverable error: SERVICE_NOT_AVAILABLE
03-21 09:27:12.020: D/GCMBaseIntentService(6018): Scheduling registration retry, backoff = 105051 (192000)
03-21 09:27:12.070: V/GCMBaseIntentService(6018): Releasing wakelock
GCMIntentService.java
package com.dorji.finalproject;
import static com.dorji.finalproject.CommonUtilities.SENDER_ID;
import static com.dorji.finalproject.CommonUtilities.displayMessage;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.dorji.finalproject.R;
import com.google.android.gcm.GCMBaseIntentService;
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService";
public GCMIntentService() {
super(SENDER_ID);
}
/**
* Method called on device registered
**/
#Override
protected void onRegistered(Context context, String registrationId) {
Log.i(TAG, "Device registered: regId = " + registrationId);
displayMessage(context, "Your device registred with GCM");
ServerUtilities.register(context, registrationId);
}
/**
* Method called on device un registred
* */
#Override
protected void onUnregistered(Context context, String registrationId) {
Log.i(TAG, "Device unregistered");
displayMessage(context, getString(R.string.gcm_unregistered));
ServerUtilities.unregister(context, registrationId);
}
/**
* Method called on Receiving a new message
* */
#Override
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String message = intent.getExtras().getString("message");
displayMessage(context, message);
// notifies user
generateNotification(context, message);
}
/**
* Method called on receiving a deleted message
* */
#Override
protected void onDeletedMessages(Context context, int total) {
Log.i(TAG, "Received deleted messages notification");
String message = getString(R.string.gcm_deleted, total);
displayMessage(context, message);
// notifies user
generateNotification(context, message);
}
/**
* Method called on Error
* */
#Override
public void onError(Context context, String errorId) {
Log.i(TAG, "Received error: " + errorId);
displayMessage(context, getString(R.string.gcm_error, errorId));
}
#Override
protected boolean onRecoverableError(Context context, String errorId) {
// log message
Log.i(TAG, "Received recoverable error: " + errorId);
displayMessage(context, getString(R.string.gcm_recoverable_error,
errorId));
return super.onRecoverableError(context, errorId);
}
/**
* Issues a notification to inform the user that server has sent a message.
*/
private static void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, MainActivity.class);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
// Play default notification sound
notification.defaults |= Notification.DEFAULT_SOUND;
//notification.sound = Uri.parse("android.resource://" + context.getPackageName() + "your_sound_file_name.mp3");
// Vibrate if vibrate is enabled
notification.defaults |= Notification.DEFAULT_VIBRATE;
notificationManager.notify(0, notification);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dorji.finalproject"
android:versionCode="1"
android:versionName="1.0" >
<!-- GCM requires Android SDK version 2.2 (API level 8) or above. -->
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<supports-screens android:largeScreens="true"
android:normalScreens="true" android:smallScreens="true"
android:resizeable="true" android:anyDensity="true" />
<!-- GCM connects to Internet Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
android:name="com.dorji.finalproject.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.dorji.finalproject.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<!-- Main activity. -->
<application
android:debuggable="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<!-- Register Activity -->
<activity
android:name="com.dorji.finalproject.LoginLayout"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Main Activity -->
<activity
android:name="com.dorji.finalproject.MainActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name" >
</activity>
<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.dorji.finalproject" />
</intent-filter>
</receiver>
<service android:name="com.dorji.finalproject.GCMIntentService" />
</application>
</manifest>
That error is defined in Google's GCM docs as follows:
public static final String ERROR_SERVICE_NOT_AVAILABLE
The device can't read the response, or there was a 500/503 from the
server that can be retried later. The application should use
exponential back off and retry.
So it seems as though it may be a temporary error, I would retry a few more times and see what happens.
Also ass #ol_v_er mentioned you need to ensure that your device meets the GCM requirements as listed in the GCM docs:
It requires devices running Android 2.2 or higher that also have the Google Play Store application installed, or or an emulator running Android 2.2 with Google APIs. However, you are not limited to deploying your Android applications through Google Play Store.
It uses an existing connection for Google services. For pre-3.0 devices, this requires users to set up their Google account on their mobile devices. A Google account is not a requirement on devices running Android 4.0.4 or higher.
If you get this message SERVICE_NOT_AVAILABLE for no reeason and none of the stackoverflow answers solve your problem read on as it may be that all that is required is patience. So selsine's answer worked for me.
After my app working fine on a nexus it suddenly started generating SERVICE_NOT_AVAILABLE messages and showing the registration id as null. I then tried the app on two different emulators and it worked fine on both.
I tried all the suggestions in the various stackoverflow postings to no avail. I left the app running on the device all evening and filled half a screen with SERVICE_NOT_AVAILABLE messages.
I uninstalled the app and switched off the device and retired to bed. The following morning, I switched on the nexus installed and ran the app again and it worked perfectly.
The strange thing is that the device was registered as a new one with the GCM server. My application server also notched up another device added. Unfortunately, my application server is a bare bones one, no persistence or logging so I'm unable to investigate further.
Has anyone else experienced this phenomenon?

Categories

Resources