Although I try other answer about this problem, it can't be solved.
Sender ID is correct, permissions are added, API key is true.
I use this post for creating the project:
http://developer.android.com/guide/google/gcm/gs.html#server-app
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
GCMRegistrar.register(this, SENDER_ID);
regId = GCMRegistrar.getRegistrationId(this);
} else {
Log.v(TAG, "Already registered");
}
String did = getDeviceID();
it returns empty string.
Do you have GCMIntentService defined correctly at the root package of your app?
<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="my_app_package" />
</intent-filter>
</receiver>
Make sure that "my_app_package" is identical to the main package of your app, or your id will return an empty string.
Also notice that
GCMRegistrar.register(this, "...");
is asynchronous. Therefore, calling GCMRegistrar.getRegistrationId(this) immediately after that is not reliable, so you should avoid it.
The id will arrive via broadcast callback to your GCMIntentService, as a part of the registration procedure. from there you can then store the gcm/fcm key anywhere you like, and use it in other parts of the application (usually on the server).
If your application launches first time, you have to wait for OnRegistered callback on your GCMIntentService.java file.
GCMRegistrar.register(this, SENDER_ID);
// Android does NOT wait for registration ends and executes immediately line below
// So your regId will be empty.
regId = GCMRegistrar.getRegistrationId(this);
GCMIntentService.java:
#Override
protected void onRegistered(Context c, String regId) {
// You can get it here!
}
Edit: Newer version of GCM library (which bundled with google play services library) waits for response and returns the Registration ID. So this answer is for older GCM libraries.
I have same problem after 1 day struggle I find solution. First i Put my GCM Related Code in To My Main Package and make change according to My Package in androidManifest.xml
i give you simple example. My project name is GCMExample and i have Three package 1. com.examle.GCMExample(Main Package) , 2. com.examle.GCMExample.activity(Second Package) , 3. com.example.GCMExample.adapter(Third Package)
I am not Getting Registration Id When My GCM Related Class File Into My Second Package
My GCM Related class like 1. GCMIntentService , 2. ServerUtilities , 3. CommonUtilities 4. WakeLocker put Into My Main Package com.example.GCMExample
also my androidManifest.xml
<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" />
<permission android:name="com.example.GCMExample.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.GCMExample.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<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.GCMExample" />
</intent-filter>
</receiver>
<service android:name="com.example.GCMExample.GCMIntentService" />
Registering app com.example.ilkgcm of senders "my_sender_id" -- This error suggests you haven't changed your 'my_sender_id' to a valid sender id which would be a 12-letter code.
If you are not getting response from the registration.one of the main reason is your manifest file is not configured correctly...especially give the "package_name"(your app package name like com.xxx.yyy) in the and correctly.
For example your receiver class name is : "MyCustomIntentService.java" , just change this name as "GCMIntentService.java" then try it again. This is simple solution. Just change your file name on the SRC area.
Related
I'm having a problem with GCM on Android. It fails to execute the onRegistered() callback, or ever return a good regId, on one of my test devices (Droid2) - but it works perfectly well on another device (Galaxy Nexus).
I'm following the basic example here. The caller looks like this:
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals(""))
GCMRegistrar.register(this, Constants.SENDER_ID);
else
Log.v(TAG, "Already registered");
And my manifest has this:
<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" />
and
<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="com.gcl.myapp" />
</intent-filter>
</receiver>
Why isn't the onRegistered() callback working? And what could be causing it to work on one device, but fail on another?? Thanks.
If it works on some devices but not others then it is to do with one of the following:
Pre Android 4.0.4 the device requires a valid google account to work.
GCM only works on devices with Play Store App and API 8 onwards.
Your manifest is badly formatted - use Lint to check!
Device/App is already registered, the Play implementation may not return again.. Try GCMRegistrar.unregister(this); first.
Hope that helps!
I had the same problem. If you are using AngularJS + IonicFramework you do not have to do this:
After you create your factory with your onDeviceReady function, creates onNotificationGCM function. Something like this:
app.factory('PushProcessingService', function () {
..
});
function onNotificationGCM(e) {
}
I was creating onNotificationGCM inside my factory. This solve my problem.
I have created a sample project in Google Console. Referring the sample from this site, http://code.google.com/p/blog-samples/downloads/detail?name=gcm_sample_update1.rar&can=2&q=#makechanges I got my registration Id. Now I don't know what to do next, how I can implement push notification in my app. I want to use Urban Airship to send push to my app. I have created a app in Urban Airship, by giving the package name, API key obtained through Google console. To my server I need to send the Apid to get the messages. But i don't know how to get the Apid.
It is explained here: http://developer.android.com/guide/google/gcm/gs.html
Writing the Android Application
You have to download and add gcm libraries.
Then make changes in manifest:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="xx"/>
and
<permission android:name="my_app_package.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="my_app_package.permission.C2D_MESSAGE" />
inserting Your package name in "my_app_package".
Add other permissions
<!-- 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" />
receiver
<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="my_app_package" />
</intent-filter>
</receiver>
Again write Your package name in "my_app_package".
Then declare your service
<service android:name=".GCMIntentService" />
You have to create a class named GCMIntentService. This class is going to handle the push notifications.
It should look like this:
class GCMIntentService extends com.google.android.gcm.GCMBaseIntentService{
public void onRegistered(Context context, String regId){}
public void onUnregistered(Context context, String regId){}
public void onError(Context context, String errorId){}
public void onMessage(Context context, Intent intent){}
}
In onMessage() you will have to handle the push message. You can use notifications.
Then in Your starting Activity you will have to put this
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
GCMRegistrar.register(this, SENDER_ID);
} else {
Log.v(TAG, "Already registered");
}
in onCreate().
SENDER_ID is the String containing all numbers that you got from the google console.
Well.. There are 3 steps to get APID
1. Run the application
2. Open logcat
3. Find the APID
Note first time you may get APID(Android Push ID) null so run it again you will get
If you want to use Urbanairship you have to use their SDK for user registration (look here), cause UA create a new id for each device and not using Google registration Id when pushing message using their API.
Not sure why they doing it like that but that it... =\
I am implementing gcm notifications in my application. Because I use my code to generate lot of application with different package names I cannot use standard mypackage.GCMIntentService name. When generating applications I do changes only in Manifest and change imports of my R class. So I impelented my own BroadcastReceiver
public class GCMReceiver extends GCMBroadcastReceiver {
#Override
protected String getGCMIntentServiceClassName(Context context) {
return GCMIntentService.class.getName();
}
}
to return name of GCMIntentService regardless of package name.
Here is my manifest:
<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="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="org.rferl.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="org.rferl.permission.C2D_MESSAGE" />
<service
android:name="org.rferl.service.GCMIntentService"
android:enabled="true" />
<receiver
android:name="org.rferl.GCMReceiver"
android:enabled="true"
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="org.rferl" />
</intent-filter>
</receiver>
Everything works fine, I can register, unregister, receive messages. But when application is not runnig no GCMIntentService.onMessage is not called. Am I missing something in my manifest? Why system did not start service?
To change package/class name for application/GCMIntentService/GCMBroadcastReceiver for Android GCM (using Eclipse ADT)
Note: You are advised to verify that you can receive messages through GCM before making the following changes. To implement GCM in Android app using the application's default package name, see GCM: Getting Started.
Package name
To change package name of your app (e.g., new package name = com.example.newpackage),
In Package Explorer, right click the project → Android Tools → Rename Application Package.
This updates the package name automatically and conveniently.
In AndroidManifest.xml, update the package name in permission and uses-permission for C2D_MESSAGE:
<permission android:name="com.example.newpackage.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.example.newpackage.permission.C2D_MESSAGE" />
In AndroidManifest.xml, update the package name in category of the receiver:
<receiver
android:name="com.example.oldpackage.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" > <!-- Not this one!! -->
<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.newpackage" /> <!-- This one!! -->
</intent-filter>
</receiver>
Name of GCMIntentService
If your app's package name is com.example.newpackage, your GCMIntentService must be called com.example.newpackage.GCMIntentService. If not,
Create a new class that extends GCMBroadcastReceiver and override getGCMIntentServiceClassName():
public class MyBroadcastReceiver extends GCMBroadcastReceiver
{
#Override
protected String getGCMIntentServiceClassName(Context context)
{
return MyIntentService.class.getName(); // Don't hard-code like "com.example.oldpackage.MyIntentService", see http://stackoverflow.com/a/936696/1402846
}
}
this is based on Google's documentation on GCMBroadcastReceiver:
By default, the GCMBaseIntentService class belongs to the application main package and is named DEFAULT_INTENT_SERVICE_CLASS_NAME. To use a new class, the getGCMIntentServiceClassName(Context) must be overridden.
In AndroidManifest.xml, update the name of the receiver:
<receiver
android:name="com.example.oldpackage.MyBroadcastReceiver"
... >
</receiver>
In AndroidManifest.xml, update the name of the service:
<service android:name="com.example.oldpackage.MyIntentService" />
Name of GCMBroadcastReceiver
If your changed the package/class name of GCMBroadcastReceiver:
In AndroidManifest.xml, update the name of the receiver:
<receiver
android:name="com.example.oldpackage.NewBroadcastReceiver"
... >
</receiver>
Troubleshooting
Verify that in AndroidManifest.xml, the package name should appear at least 4 times:
In manifest:
<manifest ...
package="com.example.newpackage" ...
In permission:
<permission android:name="com.example.newpackage.permission.C2D_MESSAGE" android:protectionLevel="signature" />
In uses-permission:
<uses-permission android:name="com.example.newpackage.permission.C2D_MESSAGE" />
In category within intent-filter within receiver for the GCM broadcast receiver:
<category android:name="com.example.newpackage" />
If you changed your package name, uninstall the old app on your device/emulator before testing.
If you changed your package name, notice that the registration ID (that you receive in onRegistered()) has changed.
If you received your registration ID in onRegistered(), you should see something like this in LogCat (tag GCMBroadcastReceiver):
GCMBroadcastReceiver onReceive: com.google.android.c2dm.intent.REGISTRATION
GCMBroadcastReceiver GCM IntentService class: com.example.oldpackage.MyIntentService
Verify that the package/class name of the intent service is correct.
If you override getGCMIntentServiceClassName(Context) in your own GCMBroadcastReceiver, you should see something like this in LogCat (tag GCMRegistrar):
GCMRegistrar Setting the name of retry receiver class to com.example.oldpackage.MyBroadcastReceiver
Verify that the package/class name of the broadcast receiver is correct.
When your server sends a message to GCM server, check the HTTP status code and HTTP response for errors.
And if you are desperate:
Check LogCat for errors.
Try restarting your device/emulator.
Try uninstalling your app on the device/emulator.
Try restarting Eclipse.
Try clean and re-build the project.
Try updating ADT (Pull down menu → Window → Android SDK Manager → Install packages).
Try updating Eclipse (Pull down menu → Help → Check for Updates).
Try restarting your computer.
Get a good sleep, or pray.
You should put GCMIntentService class into your root application package.
Here org.rferl
<service
android:name=".GCMIntentService"
android:enabled="true" />
and receiver
<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.EgoSecure.ma" />
</intent-filter>
</receiver>
Because I use my code to generate lot of application with different package names I cannot use standard mypackage.GCMIntentService name.
I'm not sure whether you ask for a runtime or a build time solution. The other answers are runtime solutions so I thought I add some information on possibilites during build time.
In AndroidManifest, you can use the variable $PACKAGE_NAME (available by default) which will refer to the package name you specified in the attribute package in the manifest root element.
The value of this package attribute needs not be a hard coded string but can also be set dynamically via resource reference like so:
<manifest package="#string/app_package" ...>
...
<service
android:name="$PACKAGE_NAME.service.GCMIntentService"
android:enabled="true" />
...
</manifest>
Note .service is just a subpackage that I included to show how you specify these. Of course, this solution would work only if your applications follow general rules like putting Service classes in a .service subpackage.
Also note, that you can actually leave the root package off completely. It will be expanded by Android:
<manifest package="#string/app_package" ...>
...
<service
android:name=".service.GCMIntentService"
android:enabled="true" />
...
</manifest>
In effect, same as above.
If you are looking for a more flexible way to replace values in an AndroidManifest (or different files), you might want to have a look at the Ant Replace task (http://ant.apache.org/manual/Tasks/replace.html) or Resource Filtering (http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html) with Maven.
The gcm broadcast receiver (GCMBroadcastReceiver.class) calls intent service class (GCMIntentService.class) from application root directory. You cannot use "org.rferl.service.GCMIntentService" right now. You should override getGCMIntentServiceClassName method from GCMBroadcastReceiver, that returns name of your GCMIntentService class. How to do that, here
I have tried some forum pages and searched through stackoverflow for the same thing, but I did not find the solution.
I have used the below code to generate registration ID for GCM notification. But I get an empty string as a registration ID:
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
if (GCMRegistrar.isRegistered(this)) {
Log.d("info", GCMRegistrar.getRegistrationId(this));
}
regId = GCMRegistrar.getRegistrationId(this);
Log.v("log", " register id oslo : " + regId);
if (regId.equals("")) {
// replace this with the project ID
GCMRegistrar.register(this, "718437041388");
Log.d("info", GCMRegistrar.getRegistrationId(this));
} else {
Log.d("info", "already registered as" + regId);
}
Please help me with this, tell me if I got anything wrong.
Thank you in advance,
Nirav.
You should not get the registrationId just after GCMRegistrar.register(this, "718437041388");
In fact, do you have a correct GCMIntentService.java which receive the regId?
If yes, you can get the regId from the onRegistered inside GCMIntentService.java
#Override
protected void onRegistered(Context context, String registrationId) {
Log.i(TAG, "Device registered: regId = " + registrationId);
Log.d("GCMIntentService", "in GCMIntentService");
displayMessage(context, getString(R.string.gcm_registered));
ServerUtilities.register(context, registrationId);
}
Notice that
GCMRegistrar.register(this, "...");
is asynchronous. Therefore, calling GCMRegistrar.getRegistrationId(this) immediately after that is not reliable, so you should avoid it.
The id will arrive via broadcast callback to your GCMIntentService, as a part of the registration procedure. from there you can than store the gcm key anywhere you like, and use it in other parts of the application (usually on the server).
Notice that GCMIntentService should be defined at the root package of your app for it to work.
Try using emulator with Google API and also sync with a Google account.
I have same problem after 1 day struggle I find solution.
First i Put my GCM Related Code in To My Main Package and make change according to My Package in androidManifest.xml
i give you simple example. My project name is GCMExample and i have Three package
1. com.examle.GCMExample(Main Package) ,
2. com.examle.GCMExample.activity(Second Package) ,
3. com.example.GCMExample.adapter(Third Package)
I am not Getting Registration Id When My GCM Related Class File Into My Second Package
My GCM Related class like 1. GCMIntentService , 2. ServerUtilities , 3. CommonUtilities 4. WakeLocker put Into My Main Package com.example.GCMExample
also my androidManifest.xml
<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" />
<permission android:name="com.example.GCMExample.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.GCMExample.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<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.GCMExample" />
</intent-filter>
</receiver>
<service android:name="com.example.GCMExample.GCMIntentService" />
Add GCM jar file in your project's lib folder
I'm trying to test the C2DM framework. I got the confirmation email a couple of days ago and then tryied to create a client that could register. For that purpose, I created a simple client following the steps described in this tutorial: http://code.google.com/intl/es-419/android/c2dm/index.html.
The Android manifest file contains among other things this code:
<permission android:name="com.bilthon.ufrj.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.bilthon.ufrj.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET"/>
<receiver android:name=".C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.bilthon.ufrj" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.bilthon.ufrj" />
</intent-filter>
</receiver>
And then, the main activity launched when the program starts has the following code:
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate
registrationIntent.putExtra("sender","mytestemail#gmail.com");
Log.d("WelcomeScreen","mytestemail#gmail.com");
startService(registrationIntent);
I also registered a google account on the AVD running my client, as they said it was required. But the problem is that I cannot get the broadcast receiver to "wake up". I don't know what could be wrong. By analysing the logs, I can see that the registration intent is created and apparently used correctly, but the receiver code just never is executed, what could be wrong?
Thanks in advance
Nelson
Well.. just sorted it out, the problem was with the declaration of the receiver. The tags for the receiver should go inside the application tag, just as demonstrated here: http://developer.android.com/guide/topics/manifest/manifest-intro.html
Here's an example of a well formated Manifest for a C2DM application. Thanks to Mark Murphy for posting the link at the android-c2dm group.
And sorry for the silly mistake.
Nelson
I just got this working myself after wrestling with it for some time.
In the manifest, you have the line
<receiver android:name=".C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND">
Which means you need a class called C2DMReceiver that extends C2DMBaseReceiver in the c2dm package. To get implement this, I copied both the c2dm package and C2DMReceiver.java file from the chrometophone-android example over to my project and was able to get a registration id from the C2DM server as intended.
I had the same problem. My solution was moving all of the permissions in my manifest above the application tag.
Things you can check:
1 I noticed is that you are declaring a C2DM permission but don't use it in your application like so:
<uses-permission android:name="com.bilthon.ufrj.permission.C2D_MESSAGE" />
2 If you have a look at the c2dm library you will see that the helper C2DMessaging's register method creates the intent with an additional call to setPackage.
registrationIntent.setPackage("com.google.android.gsf");