/* * Copyright 2012 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 com.google.android.apps.iosched.util; import com.google.android.apps.iosched.R; import com.google.android.apps.iosched.calendar.SessionCalendarService; import com.google.android.apps.iosched.provider.ScheduleContract; import com.google.android.apps.iosched.ui.AccountActivity; import com.google.android.gcm.GCMRegistrar; import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AccountManagerCallback; import android.accounts.AccountManagerFuture; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.TextUtils; import android.widget.Toast; import static com.google.android.apps.iosched.util.LogUtils.LOGE; import static com.google.android.apps.iosched.util.LogUtils.LOGI; import static com.google.android.apps.iosched.util.LogUtils.makeLogTag; /** * An assortment of authentication and login helper utilities. */ public class AccountUtils { private static final String TAG = makeLogTag(AccountUtils.class); private static final String PREF_CHOSEN_ACCOUNT = "chosen_account"; private static final String PREF_AUTH_TOKEN = "auth_token"; // The auth scope required for the app. In our case we use the "conference API" // (not currently open source) which requires the developerssite (and readonly variant) scope. private static final String AUTH_TOKEN_TYPE = "oauth2:" + "https://www.googleapis.com/auth/developerssite " + "https://www.googleapis.com/auth/developerssite.readonly "; public static boolean isAuthenticated(final Context context) { return !TextUtils.isEmpty(getChosenAccountName(context)); } public static String getChosenAccountName(final Context context) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); return sp.getString(PREF_CHOSEN_ACCOUNT, null); } private static void setChosenAccountName(final Context context, final String accountName) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); sp.edit().putString(PREF_CHOSEN_ACCOUNT, accountName).commit(); } public static String getAuthToken(final Context context) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); return sp.getString(PREF_AUTH_TOKEN, null); } private static void setAuthToken(final Context context, final String authToken) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); sp.edit().putString(PREF_AUTH_TOKEN, authToken).commit(); } public static void invalidateAuthToken(final Context context) { AccountManager am = AccountManager.get(context); am.invalidateAuthToken(GoogleAccountManager.ACCOUNT_TYPE, getAuthToken(context)); setAuthToken(context, null); } public static interface AuthenticateCallback { public boolean shouldCancelAuthentication(); public void onAuthTokenAvailable(String authToken); } public static void tryAuthenticate(Activity activity, AuthenticateCallback callback, int activityRequestCode, Account account) { //noinspection deprecation AccountManager.get(activity).getAuthToken( account, AUTH_TOKEN_TYPE, false, getAccountManagerCallback(callback, account, activity, activity, activityRequestCode), null); } public static void tryAuthenticateWithErrorNotification(Context context, AuthenticateCallback callback, Account account) { //noinspection deprecation AccountManager.get(context).getAuthToken( account, AUTH_TOKEN_TYPE, true, getAccountManagerCallback(callback, account, context, null, 0), null); } private static AccountManagerCallback<Bundle> getAccountManagerCallback( final AuthenticateCallback callback, final Account account, final Context context, final Activity activity, final int activityRequestCode) { return new AccountManagerCallback<Bundle>() { public void run(AccountManagerFuture<Bundle> future) { if (callback != null && callback.shouldCancelAuthentication()) { return; } try { Bundle bundle = future.getResult(); if (activity != null && bundle.containsKey(AccountManager.KEY_INTENT)) { Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT); intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); activity.startActivityForResult(intent, activityRequestCode); } else if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) { final String token = bundle.getString(AccountManager.KEY_AUTHTOKEN); setAuthToken(context, token); setChosenAccountName(context, account.name); if (callback != null) { callback.onAuthTokenAvailable(token); } } } catch (Exception e) { LOGE(TAG, "Authentication error", e); } } }; } public static void signOut(final Context context) { // Clear out all Google I/O-created sessions from Calendar if (UIUtils.hasICS()) { LOGI(TAG, "Clearing all sessions from Google Calendar using SessionCalendarService."); Toast.makeText(context, R.string.toast_deleting_sessions_from_calendar, Toast.LENGTH_LONG).show(); context.startService( new Intent(SessionCalendarService.ACTION_CLEAR_ALL_SESSIONS_CALENDAR) .setClass(context, SessionCalendarService.class) .putExtra(SessionCalendarService.EXTRA_ACCOUNT_NAME, getChosenAccountName(context))); } invalidateAuthToken(context); SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); sp.edit().clear().commit(); context.getContentResolver().delete(ScheduleContract.BASE_CONTENT_URI, null, null); GCMRegistrar.unregister(context); } public static void startAuthenticationFlow(final Context context, final Intent finishIntent) { Intent loginFlowIntent = new Intent(context, AccountActivity.class); loginFlowIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); loginFlowIntent.putExtra(AccountActivity.EXTRA_FINISH_INTENT, finishIntent); context.startActivity(loginFlowIntent); } }