Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.contacts.util;
     18 
     19 import com.android.contacts.R;
     20 import com.android.contacts.model.GoogleAccountType;
     21 
     22 import android.accounts.AccountManager;
     23 import android.accounts.AccountManagerCallback;
     24 import android.accounts.AccountManagerFuture;
     25 import android.accounts.AuthenticatorDescription;
     26 import android.accounts.AuthenticatorException;
     27 import android.accounts.OperationCanceledException;
     28 import android.app.Activity;
     29 import android.content.Context;
     30 import android.content.SharedPreferences;
     31 import android.os.Bundle;
     32 import android.preference.PreferenceManager;
     33 import android.util.Log;
     34 
     35 import java.io.IOException;
     36 
     37 /**
     38  * Utility class for controlling whether the standard "no account" prompt on launch is shown.
     39  */
     40 public class AccountPromptUtils {
     41 
     42     private static final String TAG = AccountPromptUtils.class.getSimpleName();
     43 
     44     /** {@link SharedPreferences} key for whether or not the "no account" prompt should be shown. */
     45     private static final String KEY_SHOW_ACCOUNT_PROMPT = "settings.showAccountPrompt";
     46 
     47     /**
     48      * The following intent keys are understood by the {@link AccountManager} and should not be
     49      * changed unless the API changes.
     50      */
     51     private static final String KEY_INTRO_MESSAGE = "introMessage";
     52     private static final String KEY_ALLOW_SKIP_ACCOUNT_SETUP = "allowSkip";
     53     private static final String KEY_USER_SKIPPED_ACCOUNT_SETUP = "setupSkipped";
     54 
     55     private static SharedPreferences getSharedPreferences(Context context) {
     56         return PreferenceManager.getDefaultSharedPreferences(context);
     57     }
     58 
     59     /**
     60      * Returns true if the "no account" prompt should be shown
     61      * (according to {@link SharedPreferences}), otherwise return false. Since this prompt is
     62      * Google-specific for the time being, this method will also return false if the Google
     63      * account type is not available from the {@link AccountManager}.
     64      */
     65     public static boolean shouldShowAccountPrompt(Context context) {
     66         // TODO: Remove the filtering of account types once there is an API in
     67         // {@link AccountManager} to show a similar account prompt
     68         // (see {@link AccountManager#addAccount()} in {@link #launchAccountPrompt()}
     69         // for any type of account. Bug: 5375902
     70         AuthenticatorDescription[] allTypes =
     71                 AccountManager.get(context).getAuthenticatorTypes();
     72         for (AuthenticatorDescription authenticatorType : allTypes) {
     73             if (GoogleAccountType.ACCOUNT_TYPE.equals(authenticatorType.type)) {
     74                 return getSharedPreferences(context).getBoolean(KEY_SHOW_ACCOUNT_PROMPT, true);
     75             }
     76         }
     77         return false;
     78     }
     79 
     80     /**
     81      * Remember to never show the "no account" prompt again by saving this to
     82      * {@link SharedPreferences}.
     83      */
     84     public static void neverShowAccountPromptAgain(Context context) {
     85         getSharedPreferences(context).edit()
     86                 .putBoolean(KEY_SHOW_ACCOUNT_PROMPT, false)
     87                 .apply();
     88     }
     89 
     90     /**
     91      * Launch the "no account" prompt. (We assume the caller has already verified that the prompt
     92      * can be shown, so checking the {@link #KEY_SHOW_ACCOUNT_PROMPT} value in
     93      * {@link SharedPreferences} will not be done in this method).
     94      */
     95     public static void launchAccountPrompt(Activity activity) {
     96         Bundle options = new Bundle();
     97         options.putCharSequence(KEY_INTRO_MESSAGE, activity.getString(R.string.no_account_prompt));
     98         options.putBoolean(KEY_ALLOW_SKIP_ACCOUNT_SETUP, true);
     99         AccountManager.get(activity).addAccount(GoogleAccountType.ACCOUNT_TYPE, null, null, options,
    100                 activity, getAccountManagerCallback(activity), null);
    101     }
    102 
    103     private static AccountManagerCallback<Bundle> getAccountManagerCallback(
    104             final Activity activity) {
    105         return new AccountManagerCallback<Bundle>() {
    106             @Override
    107             public void run(AccountManagerFuture<Bundle> future) {
    108                 if (future.isCancelled()) {
    109                     // The account creation process was canceled
    110                     activity.finish();
    111                     return;
    112                 }
    113                 try {
    114                     Bundle result = future.getResult();
    115                     if (result.getBoolean(KEY_USER_SKIPPED_ACCOUNT_SETUP)) {
    116                         AccountPromptUtils.neverShowAccountPromptAgain(activity);
    117                     }
    118                 } catch (OperationCanceledException ignore) {
    119                     Log.e(TAG, "Account setup error: account creation process canceled");
    120                 } catch (IOException ignore) {
    121                     Log.e(TAG, "Account setup error: No authenticator was registered for this"
    122                             + "account type or the authenticator failed to respond");
    123                 } catch (AuthenticatorException ignore) {
    124                     Log.e(TAG, "Account setup error: Authenticator experienced an I/O problem");
    125                 }
    126             }
    127         };
    128     }
    129 }
    130