Last active
August 29, 2015 14:22
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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