Java tutorial
/* * Copyright (c) 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package jp.januaraid.android.synciteasy.gcm; import com.google.android.gms.gcm.GoogleCloudMessaging; import android.accounts.Account; import android.app.Application; import android.app.IntentService; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import java.io.IOException; import jp.januaraid.android.synciteasy.core.Consts; /** * This class manages Google Cloud Messaging push notifications and CloudQuery * subscriptions. */ public class GCMIntentService extends IntentService { private static final String GCM_KEY_SUBID = "subId"; private static final String GCM_TYPEID_QUERY = "query"; private static final String PROPERTY_REG_ID = "registration_id"; private static final String PROPERTY_APP_VERSION = "app_version"; public static final String BROADCAST_ON_MESSAGE = "on-message-event"; @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this); // The getMessageType() intent parameter must be the intent you received // in your BroadcastReceiver. String messageType = gcm.getMessageType(intent); if (!extras.isEmpty()) { // has effect of unparcelling Bundle /* * Filter messages based on message type. Since it is likely that * GCM will be extended in the future with new message types, just * ignore any message types you're not interested in, or that you * don't recognize. */ if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) { Log.i(Consts.TAG, "onHandleIntent: message error"); } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) { Log.i(Consts.TAG, "onHandleIntent: message deleted"); // If it's a regular GCM message, do some work. } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) { String subId = intent.getStringExtra(GCM_KEY_SUBID); Log.i(Consts.TAG, "onHandleIntent: subId: " + subId); String[] tokens = subId.split(":"); String typeId = tokens[1]; // dispatch message if (GCM_TYPEID_QUERY.equals(typeId)) { Intent messageIntent = new Intent(BROADCAST_ON_MESSAGE); messageIntent.putExtras(intent); messageIntent.putExtra("token", tokens[2]); LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent); Log.i(Consts.TAG, ":sendBroadcast"); // String accountName = getApplicationContext() .getSharedPreferences(Consts.PREF_KEY_CLOUD_BACKEND, Context.MODE_PRIVATE) .getString(Consts.PREF_KEY_ACCOUNT_NAME, null); Account account = null; if (accountName == null) { return; } else { account = new Account(accountName, Consts.ACCOUNT_TYPE); } Bundle settingsBundle = new Bundle(); settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); settingsBundle.putString("token", tokens[2]); ContentResolver.requestSync(account, Consts.AUTHORITY, settingsBundle); } } } // Release the wake lock provided by the WakefulBroadcastReceiver. GCMBroadcastReceiver.completeWakefulIntent(intent); } /** * Returns registration id associated with the specified {@link Application} * . This method will block the thread until regId will be available. * * @param app * {@link Application} * @return registration id */ public static String getRegistrationId(Application app) { SharedPreferences prefs = getGcmPreferences(app); String regId = prefs.getString(PROPERTY_REG_ID, ""); if (regId.isEmpty()) { Log.i(Consts.TAG, "Registration not found."); Log.i("doRegister", "do"); return doRegister(app); } // Check if app was updated; if so, it must clear the registration ID // since the existing regID is not guaranteed to work with the new // app version. int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE); int currentVersion = getAppVersion(app); if (registeredVersion != currentVersion) { Log.i(Consts.TAG, "App version changed."); return doRegister(app); } return regId; } private static String doRegister(Context context) { String msg = ""; Log.i("doRegister", "register " + msg); try { GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); Log.i("doRegister", "register " + msg); String regId = gcm.register(Consts.PROJECT_NUMBER); msg = "Device registered, registration ID=" + regId; Log.i("doRegister", "register " + msg); // 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. SharedPreferences prefs = getGcmPreferences(context); int appVersion = getAppVersion(context); Log.i(Consts.TAG, "Saving regId on app version " + appVersion); SharedPreferences.Editor editor = prefs.edit(); editor.putString(PROPERTY_REG_ID, regId); editor.putInt(PROPERTY_APP_VERSION, appVersion); editor.commit(); } 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; } public GCMIntentService() { super(Consts.PROJECT_NUMBER); } /** * @return the stored SharedPreferences for GCM */ private static SharedPreferences getGcmPreferences(Context context) { return context.getSharedPreferences(GCMIntentService.class.getSimpleName(), MODE_PRIVATE); } /** * @return Application's version code from the {@code PackageManager}. */ private static int getAppVersion(Context context) { try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); return packageInfo.versionCode; } catch (NameNotFoundException e) { // should never happen throw new RuntimeException("Could not get package name: " + e); } } }