I had UrbanAirship implemented in version 1 of the app.
Now I extended FirebaseMessagingService in version 2 of the app.
I am not getting a call in onNewToken() to be able to send the token to my servers.
My boilerplate code looks like
AndroidManifest.xml
<service
android:name=".services.fcm.PushMessageReceiver"
android:enabled="true"
android:exported="true"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
and Receiver
public class PushMessageReceiver extends FirebaseMessagingService { ...
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
...
}
#Override
public void onNewToken(String s) {
Log.i(Config.LOGTAG, "######**** new token for fcm called");
Context ctx =ApplicationCustom.getContext();
SharedPreferences preferences = ctx.getSharedPreferences(Config.SHARED_PREFERENCES, Context.MODE_PRIVATE);
preferences.edit().putString(Config.SHARED_PREFS_DEVICE_TOKEN, s).apply();
Intent intent = new Intent(this, XmppConnectionService.class);
intent.setAction(XmppConnectionService.ACTION_FCM_TOKEN_REFRESH);
intent.putExtra("token", s);
startService(intent);
pushToServer();
}
public static void getToken() {
Log.i(Config.LOGTAG, "######**** get token for fcm called");
try {
Log.i(Config.LOGTAG, "######**** delete token for fcm called");
FirebaseInstanceId.getInstance().deleteInstanceId();
FirebaseInstanceId.getInstance().getInstanceId();
} catch (IOException e) {
e.printStackTrace();
Log.w(Config.LOGTAG, "######**** delete InstanceId failed", e);
}
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task
-> {
if (!task.isSuccessful()) {
Log.w(Config.LOGTAG, "getInstanceId failed", task.getException());
return;
}
Log.i(Config.LOGTAG, "######**** getInstanceId successful");
// Get new Instance ID token
String token = task.getResult().getToken();
Context ctx = ApplicationCustom.getContext();
SharedPreferences preferences = ctx.getSharedPreferences(Config.SHARED_PREFERENCES, Context.MODE_PRIVATE);
preferences.edit().putString(Config.SHARED_PREFS_DEVICE_TOKEN, token).apply();
pushToServer();
});
}
public void pushToServer(){
// Logic to push token to a server reading from preferences
}
}
Observations:
1) onNewToken never gets called for apps that are being updated.
2) new installs get a token
3) after I added a call to FirebaseInstanceId.getInstance().deleteInstanceId()
OnComplete does not get called either.
4) A call to getToken(senderId, "FCM") on real phones (not emulators) invariably results in
java.io.IOException: TOO_MANY_REGISTRATIONS
at com.google.firebase.iid.zzr.zza(Unknown Source:66)
at com.google.firebase.iid.zzr.zza(Unknown Source:79)
at com.google.firebase.iid.zzu.then(Unknown Source:4)
at com.google.android.gms.tasks.zzd.run(Unknown Source:5)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
how do I fix observation 1. Is it because the token has already been delivered to UrbanAirship that onNewToken does not get called?
Fyi getToken is called in a service onCreate() method.
implementation 'com.google.firebase:firebase-messaging:17.3.4'
you can get fcm token by this:-
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (task.isSuccessful()) {
String firebaseToken = task.getResult().getToken();
} else {
getFirebaseToken();
}
}
});
That's okay if your onNewToken() is not called. You can get the latest token already made by firebase for your device. onNewToken() is called on specific occasions.
The registration token may change when:
-The app deletes Instance ID
-The app is restored on a new device
-The user uninstalls/reinstall the app
-The user clears app data.
Do read the firebase documentation :
https://firebase.google.com/docs/cloud-messaging/android/client#retrieve-the-current-registration-token
And for your second query, deleteInstanceId is a blocking call, so you will have to do it in a background thread. like this,
new Thread(new Runnable() {
#Override
public void run() {
try {
FirebaseInstanceId.getInstance().deleteInstanceId();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
Some time onTokenRefresh() method call with some delay and it will generate token when new install happen that how its behave their for we need to implement functionality like below to overcome those issue maintain new user login also
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private String TAG = getClass().getName();
public static final String TOKEN_BROADCAST = "myfcmtokenbroadcast";
#Override
public void onTokenRefresh() {
//For registration of token
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//To displaying token on logcat
Log.d("TOKEN: ", refreshedToken);
//calling the method store token and passing token
getApplicationContext().sendBroadcast(new Intent(TOKEN_BROADCAST));
storeToken(refreshedToken);
}
private void storeToken(String token) {
//we will save the token in sharedpreferences later
SharedPrefManager.getInstance(getApplicationContext()).saveDeviceToken(token);
}
}
In your onCreate method in MainActivity class call this methord
private void registerFCMToken(){
registerReceiver(broadcastReceiver, new IntentFilter(MyFirebaseInstanceIDService.TOKEN_BROADCAST));
final boolean isRegisterFcm = preferences.getBoolean("IS_REGISTER_FCM", false);
// FCM token Register when onTokenRefresh method call
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String fcmToken = SharedPrefManager.getInstance(MainActivity.this).getDeviceToken();
if(!isRegisterFcm) {
RegisterFcmTokenRequest request = new RegisterFcmTokenRequest();
request.setFcmtoken(fcmToken);
performRegisterFcmRequest(request);
}
}
};
// FCM token Register when new user Login
if(SharedPrefManager.getInstance(this).getDeviceToken() != null && !isRegisterFcm) {
String fcmToken = SharedPrefManager.getInstance(MainActivity.this).getDeviceToken();
RegisterFcmTokenRequest request = new RegisterFcmTokenRequest();
request.setFcmtoken(fcmToken);
performRegisterFcmRequest(request);
}
}
In the onDestroy method
unregisterReceiver(broadcastReceiver);
This class maintains the Shredpreferance for FCM token
public class SharedPrefManager {
private static final String SHARED_PREF_NAME = "FCMSharedPref";
private static final String TAG_TOKEN = "tagtoken";
private static SharedPrefManager mInstance;
private static Context mCtx;
private SharedPrefManager(Context context) {
mCtx = context;
}
public static synchronized SharedPrefManager getInstance(Context context) {
if (mInstance == null) {
mInstance = new SharedPrefManager(context);
}
return mInstance;
}
//this method will save the device token to shared preferences
public boolean saveDeviceToken(String token){
SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(TAG_TOKEN, token);
editor.apply();
return true;
}
//this method will fetch the device token from shared preferences
public String getDeviceToken(){
SharedPreferences sharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
return sharedPreferences.getString(TAG_TOKEN, null);
}
}
Related
I've followed this method to send my fcm token in the URL.
Following is my custom launcher activity
public class LauncherActivity
extends com.google.androidbrowserhelper.trusted.LauncherActivity {
private String fcmToken;
#Override
protected Uri getLaunchingUrl() {
Uri uri = super.getLaunchingUrl();
return uri
.buildUpon()
.appendQueryParameter("fcmToken", fcmToken)
.build();
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirebaseMessaging.getInstance().getToken()
.addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (!task.isSuccessful()) {
return;
}
fcmToken = task.getResult();
launchTwa();
}
});
}
#Override
protected boolean shouldLaunchImmediately() {
return false;
}
Problem is when i run the app for the first time it get stuck in the splash screen.Then after killing the app , second time onward it works.
This issues is discussed in here as well , but with no luck.Any help will be appreciated.
Since i didn't find and resolution to this , following is the way i found to overcome this issue.Now i don't have the stuck in initial step and already token is passed to my server.
LauncherActivity.java
public class LauncherActivity
extends com.google.androidbrowserhelper.trusted.LauncherActivity {
private String fcmToken;
#Override
protected Uri getLaunchingUrl() {
uri = super.getLaunchingUrl();
return uri
.buildUpon()
.appendQueryParameter("fcmToken", fcmToken)
.build();
}
#Override
protected boolean shouldLaunchImmediately() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
fcmToken = preferences.getString("fcmTokenNew", "");
Boolean res = false;
if(fcmToken != null && !fcmToken.trim().isEmpty()) {
res = true;
}
return res;
}
}
CustomFirebaseMessagingService.java
public class CustomFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onNewToken(String token) {
sendToSariroti(token);
}
protected void sendToServer(String fcmToken) {
try {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("fcmTokenNew",fcmToken);
editor.apply();
Intent intent = getBaseContext().getPackageManager().getLaunchIntentForPackage(
getBaseContext().getPackageName() );
intent .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
What is happening is when you first launch the app,
It checks whether the parameter(fcmToken) is not null/available inside shouldLaunchImmediately If it's available , no problem , continue with launching the app
If token not available stop launching the app
Inside onNewToken , it watches until token is received from Firebase.
After it received it will call sendToServer.
Inside sendToServer, it store the fcmToken in shared preference and re-launch the app again.
Hope this will help to someone.
This issue has been handled in version 2.2.2 of android-browser-helper. For versions before that you can call onEnterAnimationComplete() after calling launchTwa(). You can find more info about this workaround here
Maybe I am doing a wrong step. I have 3 activities:
Launcher
Login
MainActivity
In the onCreate of my MainActivity, I am calling the service:
void iniciarServicioSendTokenFCM(){
servicioFCM= new Intent(this, IDService.class);
startService(servicioFCM);
}
And this is executed, because it gets to enter in onCreate of Service but onTokenRefresh() is never executed.
I have done these steps too. I have uninstalled and reinstalled the app but it didn't work.
public class IDService extends FirebaseInstanceIdService {
private ConnectionStatusSync ConnSync;//= new ConnectionStatusSync(this);
private DispositivoSync Sync;
private Integer dispositivoId;
private PreferenceUtil preferenceUtil ;
private String tokenDispositivo;
private DispositivoSync.OnFragmentInteractionListener listener;
public IDService() {
}
#Override
public void onCreate() {
super.onCreate();
Listener();
ConnSync = new ConnectionStatusSync(this);
Sync = new DispositivoSync(this);
preferenceUtil= new PreferenceUtil(this);
dispositivoId=preferenceUtil.getInt(getString(R.string.dispositivoID),0,null);
dispositivoId=(dispositivoId==0?null:dispositivoId);
tokenDispositivo= new IDUtil(this).getId();
}
private void Listener(){
listener = new DispositivoSync.OnFragmentInteractionListener() {
#Override
public void onFinished(boolean terminoBien, int dispositivoID) {
if(terminoBien){
preferenceUtil.savePreference(getString(R.string.dispositivoID),dispositivoID,null);
}
}
};
}
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
preferenceUtil.savePreference(getString(R.string.TokenFCM),refreshedToken,null);
//Log.d(TAG, "Refreshed token: " + refreshedToken);
// TODO: Implement this method to send any registration to your app's servers.
if(validaciones())
sendRegistrationToServer(refreshedToken);
}
private boolean validaciones(){
return dispositivoId!=null && MainActivity.mOperador!=null;
}
private void sendRegistrationToServer(final String token){
final Thread registrar = new Thread(new Runnable() {
#Override
public void run() {
Sync.EnviarDispositivo(MainActivity.mOperador.getOperadorIdServidor(),dispositivoId,token,tokenDispositivo,listener );
}
});
Thread hilo = new Thread(new Runnable() {
#Override
public void run() {
Command commandNull= new Command() {
#Override
public void execute() {
}
};
ConnSync.CheckConnection(registrar,commandNull);
}
});
hilo.start();
}
}
In an app that uses Firebase Cloud Messaging, the client immediately starts generating the token when the app starts.
Most likely the initial token has already been generated by the time you start listening for onTokenRefresh(). So you'll want to also immediately request and store the token in your iniciarServicioSendTokenFCM method:
sendRegistrationToServer(FirebaseInstanceId.getInstance().getToken());
I don't think it is very useful to store the token in shared preferences by the way, given that it is readily accessible from FirebaseInstanceId.getInstance().getToken().
I'm using Lock for providing Login functionality in my android App to users.
Here is my code:
private Lock lock;
private LocalBroadcastManager broadcastManager;
private BroadcastReceiver authenticationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String idToken = intent.getStringExtra("com.auth0.android.lock.extra.IdToken");
String tokenType = intent.getStringExtra("com.auth0.android.lock.extra.TokenType");
Log.i(TAG, "User logged in with " + idToken + " "+ tokenType);
}
};
//Not sure use of this callback though its not being called anytime.
private LockCallback callback = new AuthenticationCallback() {
#Override
public void onAuthentication(Credentials credentials) {
Log.d(TAG, "Authenticated");
}
#Override
public void onCanceled() {
Log.d(TAG, "Authentication cancelled");
}
#Override
public void onError(LockException error) {
Log.d(TAG, "Authentication Error");
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Auth0 auth0 = new Auth0(getString(R.string.auth0_clientId), getString(R.string.auth0_domain));
this.lock = Lock.newBuilder(auth0, callback)
.build();
broadcastManager = LocalBroadcastManager.getInstance(this);
broadcastManager.registerReceiver(authenticationReceiver, new IntentFilter("com.auth0.android.lock.action.Authentication"));
startActivity(this.lock.newIntent(this));
}
I have following two questions:
1). First of all I don't understand why it needs callback though it doesn't callback even after authentication succeeded.
2). Shouldn't LocalBroadcastManager get response with UserProfile information instead of token information?
I'm using Lock version: com.auth0.android:lock:2.0.0-beta.2
Is there any better way to do it?
Thanks in advance!
have you tried onSuccess method? I cant see in your code, that's why it's not executing after successful attempt.
Override onSuccess method in your LockCallback callback, this will return UserProfile.
/**
* Callback for authentication API calls to Auth0 API.
*/
public interface AuthenticationCallback extends Callback {
/**
* Called when authentication is successful.
* It might include user's profile and token information.
* #param profile User's profile information or null.
* #param token User's token information (e.g. id_token).
*/
void onSuccess(UserProfile profile, Token token);
}
Source
I am trying to understand the code behind Google's GCM quickstart example. Specifically, I don't understand how the code checks whether registration is already done.
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
if (checkPlayServices()) {
// Start IntentService to register this application with GCM.
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
}
RegistrationIntentService:
#Override
protected void onHandleIntent(Intent intent)
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
// [START register_for_gcm]
// Initially this call goes out to the network to retrieve the token, subsequent calls
// are local.
// [START get_token]
InstanceID instanceID = InstanceID.getInstance(this);
// R.string.gcm_defaultSenderId (the Sender ID) is typically derived from google-services.json.
// See https://developers.google.com/cloud-messaging/android/start for details on this file.
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
// [END get_token]
Log.i(TAG, "GCM Registration Token: " + token);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(token);
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
sharedPreferences.edit().putBoolean(AppSharedPreferences.SENT_TOKEN_TO_SERVER, true).apply();
// [END register_for_gcm]
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// on a third-party server, this ensures that we'll attempt the update at a later time.
sharedPreferences.edit().putBoolean(AppSharedPreferences.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(QuickstartPreferences.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
In RegistrationIntentService, the comments say that initially the call goes to retrieve the token, but subsequent calls are local. Does this mean that it will simply check to see if the app already has the token and not make the call anymore? I really don't understand this portion and I don't see anywhere in this example code where it checks for the existence of the token.
For that logic, you can refer to my working sample code:
public class MainActivity extends AppCompatActivity {
private final Context mContext = this;
private final String SENDER_ID = "425...."; // Project Number at https://console.developers.google.com/project/....
private final String SHARD_PREF = "com.example.gcmclient_preferences";
private final String GCM_TOKEN = "gcmtoken";
private final String LOG_TAG = "GCM";
public static TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences appPrefs = mContext.getSharedPreferences(SHARD_PREF, Context.MODE_PRIVATE);
String token = appPrefs.getString(GCM_TOKEN, "");
if (token.isEmpty()) {
try {
getGCMToken();
} catch (Exception e) {
e.printStackTrace();
}
}
mTextView = (TextView) findViewById(R.id.textView);
}
private void getGCMToken() {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
InstanceID instanceID = InstanceID.getInstance(mContext);
String token = instanceID.getToken(SENDER_ID, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
if (token != null && !token.isEmpty()) {
SharedPreferences appPrefs = mContext.getSharedPreferences(SHARD_PREF, Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = appPrefs.edit();
prefsEditor.putString(GCM_TOKEN, token);
prefsEditor.apply();
}
Log.i(LOG_TAG, token);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
}
You can read my answer at the following for more information
Adding Google Cloud Messagin (GCM) for Android - Registration process
Hope this helps!
InstanceID which is part of the Google Play Services library will check if there is a cached token and return that when getToken is called. If there is no cached token then it will go out to the network to retrieve a new token and return that.
Thus your application has to handle the possibility of that calling InstanceID.getToken will result in a network call. Hence the reason it is called in an IntentService.
I have an activity that call an Otto Event called LoadAuthenticateEvent this event then goes to my ClientManager.java where the following code is:
#Subscribe
public void onLoadAuthenticateEvent(LoadAuthenticateEvent loadAuthenticateEvent) {
// GCM cannot register on the main thread
String deviceID = "";
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
String differentId = GCMRegistrationUtil.registerDevice(mContext);
Log.d(TAG, "Device Id: " + differentId);
}
});
thread.start();
String email = loadAuthenticateEvent.getEmail();
String password = loadAuthenticateEvent.getPassword();
Callback<User> callback = new Callback<User>() {
#Override
public void success(User user, Response response) {
sClient.setOrganization(user.getRole().getOrganization().getSubdomain());
mBus.post(new LoadedMeEvent(user));
}
#Override
public void failure(RetrofitError retrofitError) {
mBus.post(new LoadedErrorEvent(retrofitError));
}
};
sClient.authenticate(email, password, deviceID, PLATFORM, callback);
}
The problem is that the server needs the deviceID, but GCM requires that a call be asynchronous and not on the main thread, how should I go about implementing this where I can properly get the deviceID and then pass it to sClient? Since it is possible that deviceID might be empty.
The best way is to contact GCM is through services.
Creates a IntentService to catch the intent released from the
activity
onHandleIntent(Intent intent)
Device sends service request GCM and receives the tokenID.
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Implement this method to send any registration to your app's servers.
sendRegistrationToserver(token)
Notify UI that registrationComplete
Intent registrationComplete = new Intent(GcmUtils.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
(Optional) Subscribe to topic channels
private void subscribeTopics(String token, ArrayList topics_gcm)throws IOException {
for (String topic : topics_gcm) {
GcmPubSub pubSub = GcmPubSub.getInstance(this);
pubSub.subscribe(token, topic, null);
}
}
Full IntentService:
public class RegistrationIntentService extends IntentService {
private static final String TAG = "RegIntentService";
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
ArrayList<String> topics_gcm = intent.getStringArrayListExtra("topics_gcm");
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
// In the (unlikely) event that multiple refresh operations occur simultaneously,
// ensure that they are processed sequentially.
synchronized (TAG) {
// Initially this call goes out to the network to retrieve the token, subsequent calls
// are local.
// [START get_token]
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
// [END get_token]
Log.i(TAG, "GCM Registration Token: " + token);
// TODO: Implement this method to send any registration to your app's servers.
//sendRegistrationToServer(token);
// TODO: Subscribe to topic channels
//subscribeTopics(token, topics_gcm);
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
sharedPreferences.edit().putBoolean(GcmUtils.SENT_TOKEN_TO_SERVER, true).apply();
// [END register_for_gcm]
}
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// on a third-party server, this ensures that we'll attempt the update at a later time.
sharedPreferences.edit().putBoolean(GcmUtils.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(GcmUtils.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
/**
* Persist registration to third-party servers.
*
* Modify this method to associate the user's GCM registration token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
/**
* Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
*
* #param token GCM token
* #throws IOException if unable to reach the GCM PubSub service
*/
// [START subscribe_topics]
private void subscribeTopics(String token, ArrayList<String> topics_gcm) throws IOException {
for (String topic : topics_gcm) {
GcmPubSub pubSub = GcmPubSub.getInstance(this);
pubSub.subscribe(token, topic, null);
}
}
// [END subscribe_topics]
}
Start IntentService from any context: activity, service....
Intent intent = new Intent(getContext(), egistrationIntentService.class);
intent.putCharSequenceArrayListExtra("topics_gcm", topcics_gcm);
getContext().startService(intent);
If you want to make the sClient call on the UI thread (not sure if that is a good solution for you), use a Handler to call it once your GCM registration ID is returned by GCM.
The accepted answer here has sample code to help you out.
I ended up using an AsyncTask for this specific thing like so:
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String regId = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(mContext);
}
regId = gcm.register(GCMConfig.getSenderId());
storeRegistrationId(mContext, regId);
} catch (IOException e) {
Log.e(TAG, "Error: ", e);
e.printStackTrace();
}
Log.d(TAG, "GCM AsyncTask completed");
return regId;
}
#Override
protected void onPostExecute(String result) {
// Get the message
Log.d(TAG, "Registered with GCM Result: " + result);
}
}.execute(null, null, null);
}
This worked really well inside the GCMRegistration class