C2DM registration failed because same auth_key - android

I'm currently testing my c2dm app on a notebook. I used two emulator to test the communication between my server & client devices. The problem is the second device failed to register to my server because it has the same [auth_token] as the first device. (Both of them have a different valid gmail account). Is there anyone can help so I can use two (or more) emulators with different [auth_token]? Thanks before.. :)

i used above code for registering
SharedPreferences wmbPreference1 = PreferenceManager.getDefaultSharedPreferences(LoginActivity.this);
boolean isRegistrationId = wmbPreference1.getBoolean("RegistrationId", true);
if(isRegistrationId)
{
Log.w("C2DM", "start registration process");
SharedPreferences.Editor editor = wmbPreference1.edit();
editor.putBoolean("RegistrationId", false);
editor.commit();
Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
intent.putExtra("app",PendingIntent.getBroadcast(put here your current acitivity.this, 0, new Intent(), 0));`
intent.putExtra("sender", "xyz#gmail.com");//put here different gmail id
startService(intent);
}
and used class below to receive registration id....
public class C2DMRegistrationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.w("C2DM", "Registration Receiver called");
if ("com.google.android.c2dm.intent.REGISTRATION".equals(action)) {
Log.w("C2DM", "Received registration ID");
final String registrationId = intent
.getStringExtra("registration_id");
String error = intent.getStringExtra("error");
Log.w("C2DM", "Received registration ID"+registrationId);
Log.d("C2DM", "dmControl: registrationId = " + registrationId
+ ", error = " + error);
String deviceId = Secure.getString(context.getContentResolver(),
Secure.ANDROID_ID);
Log.w("C2DM", "Received device ID"+deviceId);
}
}
hope this will help.

We cant test C2DM in Simulators. Because it requires market app in device to get registered for C2DM server. and also the market app need to be signed in. SO that the app will run flawlessly.

Related

Firebase android push notification doesn't work on other device

sorry for my bad english.
I sending push notification from my codeigniter web to android app, I have 3 devices to test it.
My first device, it works well for me.
And then in my second and third device my android didn't receive any message.
I tried to send notification from my firebase console, then I choose target is user segment with my package name. All of my devices receive the message.
Then I tried to send notification using topic, which is my topic is global. Only my first device receives the message.
Here's my code :
public static final String TOPIC_GLOBAL = "global";
public static final String REGISTRATION_COMPLETE = "registrationComplete";
public static final String PUSH_NOTIFICATION = "pushNotification";
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
displayFirebaseRegId();
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
String message = intent.getStringExtra("message");
Toast.makeText(getApplicationContext(), "Push notification: " + message, Toast.LENGTH_LONG).show();
// txtMessage.setText(message);
}
}
};
private void displayFirebaseRegId() {
SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF, 0);
String regId = pref.getString("regId", null);
Log.e(TAG, "Firebase reg id: " + regId);
if (!TextUtils.isEmpty(regId))
{
//Toast.makeText(getApplicationContext(),regId,Toast.LENGTH_LONG).show();
}
// Toast.makeText(getApplicationContext(), regId, Toast.LENGTH_LONG).show();
else
Toast.makeText(getApplicationContext(),"Firebase Reg Id is not received yet!)",Toast.LENGTH_LONG).show();
}

Explicit com.google.android.c2dm.intent.REGISTER intent

I migrated to GCM from C2DM way back when, so I'm still registering by creating a com.google.android.c2dm.intent.REGISTER intent and passing it to startService, as specified in the GCM migration documentation (which apparently is out of date):
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(context, 0, new Intent(), 0));
registrationIntent.putExtra("sender", "xxxxxx");
context.startService(registrationIntent);
Starting Android 5.0 Intents need to be explicit: how can I do this here? I could call setComponent on the intent, but what would I use as the component name?
I use a function that converts ExplicitFromImplicitIntent:
Intent explicit = createExplicitFromImplicitIntent(mContext, registrationIntent);
startService(explicit);
public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
if (resolveInfo == null ) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
You should simply stop using that intent, which is long deprecated. Since mid 2013, the recommended way to register to GCM is via the Google Play Services library, and all it requires is calling a single register method of the GoogleCloudMessaging class.
Example (taken from the official demo):
GoogleCloudMessaging gcm;
...
/**
* Registers the application with GCM servers asynchronously.
* <p>
* Stores the registration ID and the app versionCode in the application's
* shared preferences.
*/
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
// You should send the registration ID to your server over HTTP, so it
// can use GCM/HTTP or CCS to send messages to your app.
sendRegistrationIdToBackend();
// For this demo: we don't need to send it because the device will send
// upstream messages to a server that echo back the message using the
// 'from' address in the message.
// Persist the regID - no need to register again.
storeRegistrationId(context, regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
Note that the registration is done in the background (via an AsyncTask) since the new registration method is blocking, so it can't be called on the main thread.

What events cause GCM re-registration?

I have an Android app with a large user base that uses GCM. A server side misconfiguration resulted in zero backups for our GCM registration DB (really bad!), now there is no way to message these apps.
My question is: what client or server system events would cause GCM to re-register with the server? e.g. client apk version update, client google play services update, etc.
As an alternative, is there a way for the server to basically invalidate ALL the token registrations such that all of the Android clients would be forced to re-register?
You would have to release a new version of your app which (if your current logic doesn't already do it) should register to GCM and send the registration ID to your server. This, unfortunately, will give you the Registration IDs for only the devices that install the new version, but there's nothing better you can do.
You can add logic to your new app version that would be able to overcome this problem the next time it happens, this time without requiring a new version. For example, each time the app is launched, make an API call to your server that contains some unique ID of the app instance (not necessarily the Registration ID), and if your server doesn't find that ID in your DB (or doesn't find a Registration ID associated with it), you force the app instance to go through some registration process, that would require the app to re-send the Registration ID to your server. This still won't help you restore the Registration IDs of devices that don't launch your app, but at least you'll be able to restore the Registration IDs of all you active users.
I don't know how much this method is feasible, but still it may be useful.
You need to release a new version of your app.
Whenever an app registered with GCM launches it looks for a registration id and calls for getRegistrationId() function. We store that in shared prefs inside our app data.
Here's some code from the official docs :
private String getRegistrationId(Context context)
{
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty())
{
Log.i(TAG, "Registration not found.");
return "";
}
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion)
{
Log.i(TAG, "App version changed.");
return "";
}
return registrationId;
}
We use a specific key to store the registeration id in shared prefs (here it is PROPERTY_REG_ID which is already defined as public static final String PROPERTY_REG_ID = "registration_id";). Each time our app launches our it checks for the presence of this key.
So what i was suggesting was is to change this shared prefs key for the registration id.
This definitely would not be found in the shared prefs and would ask for a re-registration from the GCM and would call the registerInBackground() function.
private void registerInBackground()
{
new AsyncTask()
{
#Override
protected String doInBackground(Void... params)
{
String msg = "";
try
{
if (gcm == null)
{
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regid;
sendRegistrationIdToBackend();
storeRegistrationId(context, regid);
}
catch (IOException ex)
{
msg = "Error :" + ex.getMessage();
}
return msg;
}
#Override
protected void onPostExecute(String msg)
{
mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
After the registration you need to use the new shared prefs key to store the new registration id.
The drawback of this whole thing is that you can get the registration id of only those who would update the app.

How to send a Notification for particular Android device by unique id via GCM by Windows Azure?

I have done a simple Broadcasting the notification to android device using azure mobile service, I have received all the notifications.
But how to send a notification to particular device by using unique id like MAC-id or IMEI No(Any unique id from device).I have seen the
following link Here but it used some TAG to get notification. But I didn't get the notification.
My client code is
private void registerForNotification() {
try {
NotificationsManager.handleNotifications(this, SENDER_ID, ClientNotificationHandler.class);
gcm = GoogleCloudMessaging.getInstance(this);
String connectionString = "Endpoint=sb://notifischeduler-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedKey";
hub = new NotificationHub("notifischeduler", connectionString, this);
if(Constant.DEBUG)
Log.d(TAG, "Hub Details >>> "+hub.getConnectionString()+" HUB Path >> "+hub.getNotificationHubPath());
registerWithNotificationHubs();
} catch (Exception e) {
e.printStackTrace();
}
}
#SuppressWarnings("unchecked")
private void registerWithNotificationHubs() {
new AsyncTask() {
#Override
protected Object doInBackground(Object... params) {
try {
hub.unregister();
String regid = gcm.register(SENDER_ID);
String[] devArray = {"ANDROIDMOBILE2".trim()};
if(Constant.DEBUG)
Log.d(TAG,"HuB RegID "+regid);
hub.register(regid,devArray);
} catch (Exception e) {
e.printStackTrace();
return e;
}
return null;
}
}.execute(null, null, null);
}
In the devArray I need to pass the Unique Identification. How to achieve this?
Thanks for any help !
GCM Registration ID is the unique ID to identify a Android Device...
String regId = GCMRegistrar.getRegistrationId(this);
GCM Registration ID is the unique ID to identify any Android Device
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
regId = getRegistrationId(context);
and then send a Notification to regId (a unique Android device).

How can we find device token in android emulator for Google Cloud Messaging

I am trying to implement google cloud messaging by using emulator. but in server side device token is needed. how can i get this token. how can i get the variable "device"
import com.google.android.gcm.server.*;
Sender sender = new Sender(myApiKey);
Message message = new Message.Builder().build();
MulticastResult result = sender.send(message, devices, 5);
You can get the device ID like this
import android.provider.Settings.Secure;
String android_id=Secure.getString(getContext().getContentResolver(),Secure.ANDROID_ID);
It register app with GCM. In return it will give an alpha numeric string which will sent to our server for notification. For getting GCM id for your project follow [developer page] : http://developer.android.com/guide/google/gcm/gs.html
public String registerGCM(Context context)
{
String TAG = "GCM Already register";
String SENDER_ID =<Your Gcm ID>;
GCMRegistrar.checkDevice(context);
GCMRegistrar.checkManifest(context);
String gcmRegId = GCMRegistrar.getRegistrationId(context);
System.out.println("GCM Reg id is ======>"+gcmRegId);
if (gcmRegId.equals(""))
{
GCMRegistrar.register(context, SENDER_ID);
System.out.println("GCM Reg id is ======>blank");
String gcmregID = GCMRegistrar.getRegistrationId(context);
System.out.println("GCM Reg id is ======>"+gcmregID);
return gcmregID;
}
else
{
Log.v(TAG, "Already registered");
}
return gcmRegId;
}
get device id by
import android.provider.Settings.Secure;
String android_id=Secure.getString(getContext().getContentResolver(),Secure.ANDROID_ID);

Categories

Resources