1515 */
1616package com .example .android .sunshine .app ;
1717
18- import android .app .AlertDialog ;
19- import android .content .Context ;
2018import android .content .Intent ;
2119import android .content .SharedPreferences ;
22- import android .content .pm .PackageInfo ;
23- import android .content .pm .PackageManager ;
2420import android .net .Uri ;
25- import android .os .AsyncTask ;
2621import android .os .Bundle ;
22+ import android .preference .PreferenceManager ;
2723import android .support .v7 .app .ActionBarActivity ;
2824import android .util .Log ;
2925import android .view .Menu ;
3026import android .view .MenuItem ;
3127
28+ import com .example .android .sunshine .app .gcm .RegistrationIntentService ;
3229import com .example .android .sunshine .app .sync .SunshineSyncAdapter ;
3330import com .google .android .gms .common .ConnectionResult ;
34- import com .google .android .gms .common .GooglePlayServicesUtil ;
35- import com .google .android .gms .gcm .GoogleCloudMessaging ;
36-
37- import java .io .IOException ;
38- import java .util .concurrent .atomic .AtomicInteger ;
31+ import com .google .android .gms .common .GoogleApiAvailability ;
3932
4033public class MainActivity extends ActionBarActivity implements ForecastFragment .Callback {
4134
4235 private final String LOG_TAG = MainActivity .class .getSimpleName ();
4336 private static final String DETAILFRAGMENT_TAG = "DFTAG" ;
4437 private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000 ;
45- public static final String PROPERTY_REG_ID = "registration_id" ;
46- private static final String PROPERTY_APP_VERSION = "appVersion" ;
47-
48- /**
49- * Substitute you own sender ID here. This is the project number you got
50- * from the API Console.
51- */
52- String SENDER_ID = "Your-Sender-ID" ;
38+ public static final String SENT_TOKEN_TO_SERVER = "sentTokenToServer" ;
5339
5440 private boolean mTwoPane ;
5541 private String mLocation ;
56- private GoogleCloudMessaging mGcm ;
5742
5843 @ Override
5944 protected void onCreate (Bundle savedInstanceState ) {
@@ -85,25 +70,21 @@ protected void onCreate(Bundle savedInstanceState) {
8570
8671 SunshineSyncAdapter .initializeSyncAdapter (this );
8772
88- // If Google Play Services is not available, some features, such as GCM-powered weather
89- // alerts, will not be available.
73+ // If Google Play Services is up to date, we'll want to register GCM. If it is not, we'll
74+ // skip the registration and this device will not receive any downstream messages from
75+ // our fake server. Because weather alerts are not a core feature of the app, this should
76+ // not affect the behavior of the app, from a user perspective.
9077 if (checkPlayServices ()) {
91- mGcm = GoogleCloudMessaging .getInstance (this );
92- String regId = getRegistrationId (this );
93-
94- if (SENDER_ID .equals ("Your-Sender-ID" )) {
95- new AlertDialog .Builder (this )
96- .setTitle ("Needs Sender ID" )
97- .setMessage ("GCM will not function in Sunshine until you replace your Sender ID with a Sender ID from the Google Developers Console." )
98- .setPositiveButton (android .R .string .ok , null )
99- .create ().show ();
100- } else if (regId .isEmpty ()) {
101- registerInBackground (this );
78+ // Because this is the initial creation of the app, we'll want to be certain we have
79+ // a token. If we do not, then we will start the IntentService that will register this
80+ // application with GCM.
81+ SharedPreferences sharedPreferences =
82+ PreferenceManager .getDefaultSharedPreferences (this );
83+ boolean sentToken = sharedPreferences .getBoolean (SENT_TOKEN_TO_SERVER , false );
84+ if (!sentToken ) {
85+ Intent intent = new Intent (this , RegistrationIntentService .class );
86+ startService (intent );
10287 }
103- } else {
104- Log .i (LOG_TAG , "No valid Google Play Services APK. Weather alerts will be disabled." );
105- // Store regID as null
106- storeRegistrationId (this , null );
10788 }
10889 }
10990
@@ -126,22 +107,16 @@ public boolean onOptionsItemSelected(MenuItem item) {
126107 startActivity (new Intent (this , SettingsActivity .class ));
127108 return true ;
128109 }
110+
129111 return super .onOptionsItemSelected (item );
130112 }
131113
132114 @ Override
133115 protected void onResume () {
134116 super .onResume ();
135-
136- // If Google Play Services is not available, some features, such as GCM-powered weather
137- // alerts, will not be available.
138- if (!checkPlayServices ()) {
139- // Store regID as null
140- }
141-
142- String location = Utility .getPreferredLocation (this );
117+ String location = Utility .getPreferredLocation ( this );
143118 // update the location in our second pane using the fragment manager
144- if (location != null && !location .equals (mLocation )) {
119+ if (location != null && !location .equals (mLocation )) {
145120 ForecastFragment ff = (ForecastFragment )getSupportFragmentManager ().findFragmentById (R .id .fragment_forecast );
146121 if ( null != ff ) {
147122 ff .onLocationChanged ();
@@ -182,10 +157,11 @@ public void onItemSelected(Uri contentUri) {
182157 * the Google Play Store or enable it in the device's system settings.
183158 */
184159 private boolean checkPlayServices () {
185- int resultCode = GooglePlayServicesUtil .isGooglePlayServicesAvailable (this );
160+ GoogleApiAvailability apiAvailability = GoogleApiAvailability .getInstance ();
161+ int resultCode = apiAvailability .isGooglePlayServicesAvailable (this );
186162 if (resultCode != ConnectionResult .SUCCESS ) {
187- if (GooglePlayServicesUtil . isUserRecoverableError (resultCode )) {
188- GooglePlayServicesUtil .getErrorDialog (resultCode , this ,
163+ if (apiAvailability . isUserResolvableError (resultCode )) {
164+ apiAvailability .getErrorDialog (this , resultCode ,
189165 PLAY_SERVICES_RESOLUTION_REQUEST ).show ();
190166 } else {
191167 Log .i (LOG_TAG , "This device is not supported." );
@@ -195,113 +171,4 @@ private boolean checkPlayServices() {
195171 }
196172 return true ;
197173 }
198-
199- /**
200- * Gets the current registration ID for application on GCM service.
201- * <p>
202- * If result is empty, the app needs to register.
203- *
204- * @return registration ID, or empty string if there is no existing
205- * registration ID.
206- */
207- private String getRegistrationId (Context context ) {
208- final SharedPreferences prefs = getGCMPreferences (context );
209- String registrationId = prefs .getString (PROPERTY_REG_ID , "" );
210- if (registrationId .isEmpty ()) {
211- Log .i (LOG_TAG , "GCM Registration not found." );
212- return "" ;
213- }
214-
215- // Check if app was updated; if so, it must clear the registration ID
216- // since the existing registration ID is not guaranteed to work with
217- // the new app version.
218- int registeredVersion = prefs .getInt (PROPERTY_APP_VERSION , Integer .MIN_VALUE );
219- int currentVersion = getAppVersion (context );
220- if (registeredVersion != currentVersion ) {
221- Log .i (LOG_TAG , "App version changed." );
222- return "" ;
223- }
224- return registrationId ;
225- }
226-
227- /**
228- * @return Application's {@code SharedPreferences}.
229- */
230- private SharedPreferences getGCMPreferences (Context context ) {
231- // Sunshine persists the registration ID in shared preferences, but
232- // how you store the registration ID in your app is up to you. Just make sure
233- // that it is private!
234- return getSharedPreferences (MainActivity .class .getSimpleName (), Context .MODE_PRIVATE );
235- }
236-
237- /**
238- * @return Application's version code from the {@code PackageManager}.
239- */
240- private static int getAppVersion (Context context ) {
241- try {
242- PackageInfo packageInfo = context .getPackageManager ()
243- .getPackageInfo (context .getPackageName (), 0 );
244- return packageInfo .versionCode ;
245- } catch (PackageManager .NameNotFoundException e ) {
246- // Should never happen. WHAT DID YOU DO?!?!
247- throw new RuntimeException ("Could not get package name: " + e );
248- }
249- }
250-
251- /**
252- * Registers the application with GCM servers asynchronously.
253- * <p>
254- * Stores the registration ID and app versionCode in the application's
255- * shared preferences.
256- */
257- private void registerInBackground (final Context context ) {
258- new AsyncTask <Void , Void , Void >() {
259- @ Override
260- protected Void doInBackground (Void ... params ) {
261- String msg = "" ;
262- try {
263- if (mGcm == null ) {
264- mGcm = GoogleCloudMessaging .getInstance (context );
265- }
266- String regId = mGcm .register (SENDER_ID );
267- msg = "Device registered, registration ID=" + regId ;
268-
269- // You should send the registration ID to your server over HTTP,
270- // so it can use GCM/HTTP or CCS to send messages to your app.
271- // The request to your server should be authenticated if your app
272- // is using accounts.
273- //sendRegistrationIdToBackend();
274- // For this demo: we don't need to send it because the device
275- // will send upstream messages to a server that echo back the
276- // message using the 'from' address in the message.
277-
278- // Persist the registration ID - no need to register again.
279- storeRegistrationId (context , regId );
280- } catch (IOException ex ) {
281- msg = "Error :" + ex .getMessage ();
282- // TODO: If there is an error, don't just keep trying to register.
283- // Require the user to click a button again, or perform
284- // exponential back-off.
285- }
286- return null ;
287- }
288- }.execute (null , null , null );
289- }
290-
291- /**
292- * Stores the registration ID and app versionCode in the application's
293- * {@code SharedPreferences}.
294- *
295- * @param context application's context.
296- * @param regId registration ID
297- */
298- private void storeRegistrationId (Context context , String regId ) {
299- final SharedPreferences prefs = getGCMPreferences (context );
300- int appVersion = getAppVersion (context );
301- Log .i (LOG_TAG , "Saving regId on app version " + appVersion );
302- SharedPreferences .Editor editor = prefs .edit ();
303- editor .putString (PROPERTY_REG_ID , regId );
304- editor .putInt (PROPERTY_APP_VERSION , appVersion );
305- editor .commit ();
306- }
307174}
0 commit comments