Roll NDK to pick std::deque patch.
[android_tools.git] / sdk / tools / templates / activities / LoginActivity / root / src / app_package / PlusBaseActivity.java.ftl
blob45ea9a974ff50eccbd4e77c241d4b2493e7ae01a
1 package ${packageName};
3 import android.content.Intent;
4 import android.content.IntentSender;
5 import android.os.Bundle;
6 <#if minApiLevel lt 14>import android.support.v7.app.ActionBarActivity;</#if>
7 <#if minApiLevel gte 14>import android.app.Activity;</#if>
8 import android.util.Log;
10 import com.google.android.gms.common.ConnectionResult;
11 import com.google.android.gms.common.GooglePlayServicesClient;
12 import com.google.android.gms.common.Scopes;
13 import com.google.android.gms.plus.PlusClient;
14 <#if applicationPackage??>import ${applicationPackage}.R;</#if>
16 /**
17  * A base class to wrap communication with the Google Play Services PlusClient.
18  */
19 public abstract class PlusBaseActivity extends <#if minApiLevel lt 14>ActionBar</#if>Activity
20         implements GooglePlayServicesClient.ConnectionCallbacks,
21         GooglePlayServicesClient.OnConnectionFailedListener {
23     private static final String TAG = PlusBaseActivity.class.getSimpleName();
25     // A magic number we will use to know that our sign-in error resolution activity has completed
26     private static final int OUR_REQUEST_CODE = 49404;
28     // A flag to stop multiple dialogues appearing for the user
29     private boolean mAutoResolveOnFail;
31     // A flag to track when a connection is already in progress
32     public boolean mPlusClientIsConnecting = false;
34     // This is the helper object that connects to Google Play Services.
35     private PlusClient mPlusClient;
37     // The saved result from {@link #onConnectionFailed(ConnectionResult)}.  If a connection
38     // attempt has been made, this is non-null.
39     // If this IS null, then the connect method is still running.
40     private ConnectionResult mConnectionResult;
42     /**
43      * Called when the {@link PlusClient} revokes access to this app.
44      */
45     protected abstract void onPlusClientRevokeAccess();
47     /**
48      * Called when the PlusClient is successfully connected.
49      */
50     protected abstract void onPlusClientSignIn();
52     /**
53      * Called when the {@link PlusClient} is disconnected.
54      */
55     protected abstract void onPlusClientSignOut();
57     /**
58      * Called when the {@link PlusClient} is blocking the UI.  If you have a progress bar widget,
59      * this tells you when to show or hide it.
60      */
61     protected abstract void onPlusClientBlockingUI(boolean show);
63     /**
64      * Called when there is a change in connection state.  If you have "Sign in"/ "Connect",
65      * "Sign out"/ "Disconnect", or "Revoke access" buttons, this lets you know when their states
66      * need to be updated.
67      */
68     protected abstract void updateConnectButtonState();
70     @Override
71     protected void onCreate(Bundle savedInstanceState) {
72         super.onCreate(savedInstanceState);
74         // Initialize the PlusClient connection.
75         // Scopes indicate the information about the user your application will be able to access.
76         mPlusClient =
77                 new PlusClient.Builder(this, this, this).setScopes(Scopes.PLUS_LOGIN,
78                         Scopes.PLUS_ME).build();
79     }
81     /**
82      * Try to sign in the user.
83      */
84     public void signIn() {
85         if (!mPlusClient.isConnected()) {
86             // Show the dialog as we are now signing in.
87             setProgressBarVisible(true);
88             // Make sure that we will start the resolution (e.g. fire the intent and pop up a
89             // dialog for the user) for any errors that come in.
90             mAutoResolveOnFail = true;
91             // We should always have a connection result ready to resolve,
92             // so we can start that process.
93             if (mConnectionResult != null) {
94                 startResolution();
95             } else {
96                 // If we don't have one though, we can start connect in
97                 // order to retrieve one.
98                 initiatePlusClientConnect();
99             }
100         }
102         updateConnectButtonState();
103     }
105     /**
106      * Connect the {@link PlusClient} only if a connection isn't already in progress.  This will
107      * call back to {@link #onConnected(android.os.Bundle)} or
108      * {@link #onConnectionFailed(com.google.android.gms.common.ConnectionResult)}.
109      */
110     private void initiatePlusClientConnect() {
111         if (!mPlusClient.isConnected() && !mPlusClient.isConnecting()) {
112             mPlusClient.connect();
113         }
114     }
116     /**
117      * Disconnect the {@link PlusClient} only if it is connected (otherwise, it can throw an error.)
118      * This will call back to {@link #onDisconnected()}.
119      */
120     private void initiatePlusClientDisconnect() {
121         if (mPlusClient.isConnected()) {
122             mPlusClient.disconnect();
123         }
124     }
126     /**
127      * Sign out the user (so they can switch to another account).
128      */
129     public void signOut() {
131         // We only want to sign out if we're connected.
132         if (mPlusClient.isConnected()) {
133             // Clear the default account in order to allow the user to potentially choose a
134             // different account from the account chooser.
135             mPlusClient.clearDefaultAccount();
137             // Disconnect from Google Play Services, then reconnect in order to restart the
138             // process from scratch.
139             initiatePlusClientDisconnect();
141             Log.v(TAG, "Sign out successful!");
142         }
144         updateConnectButtonState();
145     }
147     /**
148      * Revoke Google+ authorization completely.
149      */
150     public void revokeAccess() {
152         if (mPlusClient.isConnected()) {
153             // Clear the default account as in the Sign Out.
154             mPlusClient.clearDefaultAccount();
156             // Revoke access to this entire application. This will call back to
157             // onAccessRevoked when it is complete, as it needs to reach the Google
158             // authentication servers to revoke all tokens.
159             mPlusClient.revokeAccessAndDisconnect(new PlusClient.OnAccessRevokedListener() {
160                 public void onAccessRevoked(ConnectionResult result) {
161                     updateConnectButtonState();
162                     onPlusClientRevokeAccess();
163                 }
164             });
165         }
167     }
169     @Override
170     protected void onStart() {
171         super.onStart();
172         initiatePlusClientConnect();
173     }
175     @Override
176     protected void onStop() {
177         super.onStop();
178         initiatePlusClientDisconnect();
179     }
181     public boolean isPlusClientConnecting() {
182         return mPlusClientIsConnecting;
183     }
185     private void setProgressBarVisible(boolean flag) {
186         mPlusClientIsConnecting = flag;
187         onPlusClientBlockingUI(flag);
188     }
190     /**
191      * A helper method to flip the mResolveOnFail flag and start the resolution
192      * of the ConnectionResult from the failed connect() call.
193      */
194     private void startResolution() {
195         try {
196             // Don't start another resolution now until we have a result from the activity we're
197             // about to start.
198             mAutoResolveOnFail = false;
199             // If we can resolve the error, then call start resolution and pass it an integer tag
200             // we can use to track.
201             // This means that when we get the onActivityResult callback we'll know it's from
202             // being started here.
203             mConnectionResult.startResolutionForResult(this, OUR_REQUEST_CODE);
204         } catch (IntentSender.SendIntentException e) {
205             // Any problems, just try to connect() again so we get a new ConnectionResult.
206             mConnectionResult = null;
207             initiatePlusClientConnect();
208         }
209     }
211     /**
212      * An earlier connection failed, and we're now receiving the result of the resolution attempt
213      * by PlusClient.
214      *
215      * @see #onConnectionFailed(ConnectionResult)
216      */
217     @Override
218     protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
219         updateConnectButtonState();
220         if (requestCode == OUR_REQUEST_CODE && responseCode == RESULT_OK) {
221             // If we have a successful result, we will want to be able to resolve any further
222             // errors, so turn on resolution with our flag.
223             mAutoResolveOnFail = true;
224             // If we have a successful result, let's call connect() again. If there are any more
225             // errors to resolve we'll get our onConnectionFailed, but if not,
226             // we'll get onConnected.
227             initiatePlusClientConnect();
228         } else if (requestCode == OUR_REQUEST_CODE && responseCode != RESULT_OK) {
229             // If we've got an error we can't resolve, we're no longer in the midst of signing
230             // in, so we can stop the progress spinner.
231             setProgressBarVisible(false);
232         }
233     }
235     /**
236      * Successfully connected (called by PlusClient)
237      */
238     @Override
239     public void onConnected(Bundle connectionHint) {
240         updateConnectButtonState();
241         setProgressBarVisible(false);
242         onPlusClientSignIn();
243     }
245     /**
246      * Successfully disconnected (called by PlusClient)
247      */
248     @Override
249     public void onDisconnected() {
250         updateConnectButtonState();
251         onPlusClientSignOut();
252     }
254     /**
255      * Connection failed for some reason (called by PlusClient)
256      * Try and resolve the result.  Failure here is usually not an indication of a serious error,
257      * just that the user's input is needed.
258      *
259      * @see #onActivityResult(int, int, Intent)
260      */
261     @Override
262     public void onConnectionFailed(ConnectionResult result) {
263         updateConnectButtonState();
265         // Most of the time, the connection will fail with a user resolvable result. We can store
266         // that in our mConnectionResult property ready to be used when the user clicks the
267         // sign-in button.
268         if (result.hasResolution()) {
269             mConnectionResult = result;
270             if (mAutoResolveOnFail) {
271                 // This is a local helper function that starts the resolution of the problem,
272                 // which may be showing the user an account chooser or similar.
273                 startResolution();
274             }
275         }
276     }
278     public PlusClient getPlusClient() {
279         return mPlusClient;
280     }