Skip to content

Instantly share code, notes, and snippets.

@bmoliveira
Last active August 29, 2015 14:22
Show Gist options
  • Save bmoliveira/c19eabe88c33b5a09fd2 to your computer and use it in GitHub Desktop.
Save bmoliveira/c19eabe88c33b5a09fd2 to your computer and use it in GitHub Desktop.
Android Helper to get GCM Token from Play services, with fluent api callback registration
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.util.Log;
import android.util.Pair;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import java.io.IOException;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
/*
public class GCMTokenUsageSample
{
public static void registerInBackground(final Context context)
{
new AndroidCGMTokenBuilder(context.getString(R.string.gcm_key))
.setTokenAgeDays(20)
.setErrorAction(new AndroidCGMTokenBuilder.ActionListener<String>()
{
@Override
public void onResult(String result)
{
Log.d(TAG, "Error description:" + result);
}
}
)
.setPlayServicesNotFoundAction(
new AndroidCGMTokenBuilder.ActionListener<String>()
{
@Override
public void onResult(String result)
{
Log.d(TAG, result);
}
}
)
.setLocalValidTokenAction(
new AndroidCGMTokenBuilder.ActionListener<String>()
{
@Override
public void onResult(String result)
{
Log.d(TAG, "Valid local token " + result);
}
}
)
.setSuccessAction(
new AndroidCGMTokenBuilder.ActionListener<String>()
{
@Override
public void onResult(String result)
{
Log.d(TAG, "Success: " + result);
}
}
)
.fetchToken(context);
}
}
*/
public class AndroidCGMTokenBuilder
{
private static final String TAG = "AndroidGCMTokenBuilder";
private enum ServiceResult
{
Success,
Error,
ServicesNotFound,
SameResult
}
public static abstract class ActionListener<T>
{
public abstract void onResult(T result);
}
// difference in days
private static int maximumTokenAge = 10;
private String key;
private ActionListener<String> localResult;
private ActionListener<String> success;
private ActionListener<String> playServicesNotFound;
private ActionListener<String> error;
public AndroidCGMTokenBuilder(String key)
{
this.key = key;
}
public AndroidCGMTokenBuilder setTokenAgeDays(int days)
{
maximumTokenAge = days;
return this;
}
public AndroidCGMTokenBuilder setSuccessAction(ActionListener<String> success)
{
this.success = success;
return this;
}
public AndroidCGMTokenBuilder setLocalValidTokenAction(ActionListener<String> sameResult)
{
this.localResult = sameResult;
return this;
}
public AndroidCGMTokenBuilder setPlayServicesNotFoundAction(ActionListener<String> playServicesNotFound)
{
this.playServicesNotFound = playServicesNotFound;
return this;
}
public AndroidCGMTokenBuilder setErrorAction(ActionListener<String> error)
{
this.error = error;
return this;
}
//
// deletes a already stored token
public AndroidCGMTokenBuilder resetToken(Context context)
{
resetStoredToken(context);
return this;
}
//
// executes the request
public void fetchToken(Context context)
{
registerInBackground(context, key);
}
private void registerInBackground(final Context context, final String key)
{
new AsyncTask<Void, String, Pair<ServiceResult, String>>()
{
@Override
protected Pair<ServiceResult, String> doInBackground(Void... params)
{
return fetchTask(context, key);
}
@Override
protected void onPostExecute(Pair<ServiceResult, String> result)
{
handleRegisterResult(result);
}
}.execute(null, null, null);
}
//
// Called in the async Task
private Pair<ServiceResult, String> fetchTask(Context context, String key)
{
try
{
String token = getStoredToken(context);
if ( token != null )
{
// Already has a valid token
return new Pair<>(ServiceResult.SameResult, token);
}
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
if ( gcm == null || !Helper.isPlayServicesAvailable(context) )
{
// Could not find play services
return new Pair<>(ServiceResult.ServicesNotFound, "Play services not found");
}
token = gcm.register(key);
if ( token == null )
{
// Unknown error fetching from play services
return new Pair<>(ServiceResult.Error, "Error fetching");
}
// Store the token and return success
storeToken(context, token);
return new Pair<>(ServiceResult.Success, token);
} catch (final IOException ex)
{
return new Pair<>(ServiceResult.Error, "IO Exception");
} catch (NullPointerException ex2)
{
return new Pair<>(ServiceResult.Error, "Null pointer exception");
} catch (Exception ex3)
{
ex3.printStackTrace();
return new Pair<>(ServiceResult.Error, ex3.toString());
}
}
//
// Async task callback on main thread
private void handleRegisterResult(Pair<ServiceResult, String> result)
{
switch (result.first)
{
case Success:
if ( success != null )
{
success.onResult(result.second);
}
break;
case Error:
if ( error != null )
{
error.onResult(result.second);
}
break;
case ServicesNotFound:
if ( playServicesNotFound != null )
{
playServicesNotFound.onResult(result.second);
}
break;
case SameResult:
if ( localResult != null )
{
localResult.onResult(result.second);
}
else if ( success != null )
{
success.onResult(result.second);
}
break;
}
}
private static long getExpirationAgeInMilis()
{
if ( maximumTokenAge <= 0 )
{
Log.d(TAG, "maximum token age should be bigger than 0 (Zero)");
maximumTokenAge = 1;
}
return TimeUnit.DAYS.toMillis(maximumTokenAge);
}
//
// Validates last token date
private static boolean isTokenExpired(Context context)
{
Calendar storedCalendar = GCMTokenPreferences.getGCMTokenDate(context);
if ( storedCalendar == null )
{
return true;
}
Calendar now = Calendar.getInstance();
long difference = now.getTimeInMillis() - storedCalendar.getTimeInMillis();
return difference > getExpirationAgeInMilis();
}
//
// Store in the device gcm token, and set token date now
private void storeToken(Context context, String token)
{
GCMTokenPreferences.storeGCMToken(context, token);
// set token date now!
GCMTokenPreferences.storeGCMTokenDate(context, Calendar.getInstance());
}
//
// Get stored token if exist and is valid
public static @Nullable String getStoredToken(Context context)
{
//
// Checks if the stored token is valid
if ( isTokenExpired(context) )
{
return null;
}
return GCMTokenPreferences.getGCMToken(context);
}
public static void resetStoredToken(Context context)
{
GCMTokenPreferences.resetToken(context);
}
public static class Helper
{
//
// Checks for play services
public static boolean isPlayServicesAvailable(Context context)
{
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
return resultCode == ConnectionResult.SUCCESS
|| resultCode == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED
|| resultCode == ConnectionResult.SERVICE_UPDATING;
}
}
private static class GCMTokenPreferences
{
private static class PreferenceKeys
{
// Shared Preferences main key
private static final String Preferences = "GCM_PREFERENCES_FETCH_PREFS";
// Token preferences key
private static final String Token = "GCM_PREFERENCES_TOKEN_KEY";
// Token date preferences keys
private static final String TokenDateDay = "GCM_PREFERENCES_TOKEN_DATE_DAY_KEY";
private static final String TokenDateMonth = "GCM_PREFERENCES_TOKEN_DATE_MONTH_KEY";
private static final String TokenDateYear = "GCM_PREFERENCES_TOKEN_DATE_YEAR_KEY";
}
public static SharedPreferences getPreferences(Context context)
{
return context.getSharedPreferences(PreferenceKeys.Preferences, Context.MODE_PRIVATE);
}
private static void storeGCMToken(Context context, String token)
{
SharedPreferences.Editor e = getPreferences(context).edit();
e.putString(PreferenceKeys.Token, token);
e.apply();
}
private static String getGCMToken(Context context)
{
return getPreferences(context).getString(PreferenceKeys.Token, null);
}
private static void storeGCMTokenDate(Context context, Calendar calendar)
{
SharedPreferences.Editor e = getPreferences(context).edit();
e.putInt(PreferenceKeys.TokenDateDay, calendar.get(Calendar.DAY_OF_YEAR));
e.putInt(PreferenceKeys.TokenDateMonth, calendar.get(Calendar.MONTH));
e.putInt(PreferenceKeys.TokenDateYear, calendar.get(Calendar.YEAR));
e.apply();
}
private static Calendar getGCMTokenDate(Context context)
{
int day = getPreferences(context).getInt(PreferenceKeys.TokenDateDay, -1);
if ( day == -1 )
{
return null;
}
int month = getPreferences(context).getInt(PreferenceKeys.TokenDateMonth, 0);
int year = getPreferences(context).getInt(PreferenceKeys.TokenDateYear, 0);
Calendar result = Calendar.getInstance();
result.set(year, month, day);
return result;
}
public static void resetToken(Context context)
{
SharedPreferences.Editor e = getPreferences(context).edit();
e.remove(PreferenceKeys.Token);
e.remove(PreferenceKeys.TokenDateDay);
e.remove(PreferenceKeys.TokenDateMonth);
e.remove(PreferenceKeys.TokenDateYear);
e.apply();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment