Home | History | Annotate | Download | only in setup
      1 /*
      2  * Copyright (C) 2010 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.email.activity.setup;
     18 
     19 import android.app.ActionBar;
     20 import android.app.Fragment;
     21 import android.content.Intent;
     22 import android.net.Uri;
     23 import android.os.Bundle;
     24 import android.support.annotation.NonNull;
     25 import android.view.KeyEvent;
     26 import android.view.Menu;
     27 import android.view.MenuItem;
     28 
     29 import com.android.email.R;
     30 import com.android.email.setup.AuthenticatorSetupIntentHelper;
     31 import com.android.emailcommon.utility.IntentUtilities;
     32 import com.android.mail.providers.UIProvider.EditSettingsExtras;
     33 import com.android.mail.ui.settings.MailPreferenceActivity;
     34 import com.android.mail.utils.Utils;
     35 
     36 import java.util.List;
     37 
     38 /**
     39  * Handles account preferences, using multi-pane arrangement when possible.
     40  *
     41  * This activity uses the following fragments:
     42  *   AccountSettingsFragment
     43  *   GeneralPreferences
     44  *   DebugFragment
     45  *
     46  */
     47 public class EmailPreferenceActivity extends MailPreferenceActivity {
     48     /*
     49      * Intent to open account settings for account=1
     50         adb shell am start -a android.intent.action.EDIT \
     51             -d '"content://ui.email.android.com/settings?ACCOUNT_ID=1"'
     52      */
     53 
     54     // Intent extras for our internal activity launch
     55     private static final String EXTRA_ENABLE_DEBUG = "AccountSettings.enable_debug";
     56     // STOPSHIP: Do not ship with the debug menu allowed.
     57     private static final boolean DEBUG_MENU_ALLOWED = false;
     58 
     59     // Intent extras for launch directly from system account manager
     60     // NOTE: This string must match the one in res/xml/account_preferences.xml
     61     private static String INTENT_ACCOUNT_MANAGER_ENTRY;
     62 
     63     // Key codes used to open a debug settings fragment.
     64     private static final int[] SECRET_KEY_CODES = {
     65             KeyEvent.KEYCODE_D, KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_B, KeyEvent.KEYCODE_U,
     66             KeyEvent.KEYCODE_G
     67             };
     68     private int mSecretKeyCodeIndex = 0;
     69 
     70     // When the user taps "Email Preferences" 10 times in a row, we'll enable the debug settings.
     71     private int mNumGeneralHeaderClicked = 0;
     72 
     73     private boolean mShowDebugMenu;
     74     private Uri mFeedbackUri;
     75     private MenuItem mFeedbackMenuItem;
     76 
     77     @Override
     78     public Intent getIntent() {
     79         final Intent intent = super.getIntent();
     80         final long accountId = IntentUtilities.getAccountIdFromIntent(intent);
     81         if (accountId < 0) {
     82             return intent;
     83         }
     84         Intent modIntent = new Intent(intent);
     85         modIntent.putExtra(EXTRA_SHOW_FRAGMENT, AccountSettingsFragment.class.getCanonicalName());
     86         modIntent.putExtra(
     87                 EXTRA_SHOW_FRAGMENT_ARGUMENTS,
     88                 AccountSettingsFragment.buildArguments(
     89                         IntentUtilities.getAccountNameFromIntent(intent)));
     90         modIntent.putExtra(EXTRA_NO_HEADERS, true);
     91         return modIntent;
     92     }
     93 
     94     @Override
     95     public void onCreate(Bundle savedInstanceState) {
     96         super.onCreate(savedInstanceState);
     97 
     98         final Intent i = getIntent();
     99         if (savedInstanceState == null) {
    100             // If we are not restarting from a previous instance, we need to
    101             // figure out the initial prefs to show.  (Otherwise, we want to
    102             // continue showing whatever the user last selected.)
    103             if (INTENT_ACCOUNT_MANAGER_ENTRY == null) {
    104                 INTENT_ACCOUNT_MANAGER_ENTRY = getString(R.string.intent_account_manager_entry);
    105             }
    106             if (INTENT_ACCOUNT_MANAGER_ENTRY.equals(i.getAction())) {
    107                 // This case occurs if we're changing account settings from Settings -> Accounts.
    108                 // We get an account object in the intent, but it's not actually useful to us since
    109                 // it's always just the first account of that type. The user can't specify which
    110                 // account they wish to view from within the settings UI, so just dump them at the
    111                 // main screen.
    112                 // android.accounts.Account acct = i.getParcelableExtra("account");
    113             } else if (i.hasExtra(EditSettingsExtras.EXTRA_FOLDER)) {
    114                 throw new IllegalArgumentException("EXTRA_FOLDER is no longer supported");
    115             } else {
    116                 // Otherwise, we're called from within the Email app and look for our extras
    117                 final long accountId = IntentUtilities.getAccountIdFromIntent(i);
    118                 if (accountId != -1) {
    119                     final Bundle args = AccountSettingsFragment.buildArguments(accountId);
    120                     startPreferencePanel(AccountSettingsFragment.class.getName(), args,
    121                             0, null, null, 0);
    122                 }
    123             }
    124         }
    125         mShowDebugMenu = i.getBooleanExtra(EXTRA_ENABLE_DEBUG, false);
    126 
    127         final ActionBar actionBar = getActionBar();
    128         if (actionBar != null) {
    129             actionBar.setDisplayOptions(
    130                     ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);
    131         }
    132 
    133         mFeedbackUri = Utils.getValidUri(getString(R.string.email_feedback_uri));
    134     }
    135 
    136     /**
    137      * Listen for secret sequence and, if heard, enable debug menu
    138      */
    139     @Override
    140     public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
    141         if (event.getKeyCode() == SECRET_KEY_CODES[mSecretKeyCodeIndex]) {
    142             mSecretKeyCodeIndex++;
    143             if (mSecretKeyCodeIndex == SECRET_KEY_CODES.length) {
    144                 mSecretKeyCodeIndex = 0;
    145                 enableDebugMenu();
    146             }
    147         } else {
    148             mSecretKeyCodeIndex = 0;
    149         }
    150         return super.onKeyDown(keyCode, event);
    151     }
    152 
    153     @Override
    154     public boolean onCreateOptionsMenu(Menu menu) {
    155         super.onCreateOptionsMenu(menu);
    156         getMenuInflater().inflate(R.menu.settings_menu, menu);
    157 
    158         mFeedbackMenuItem = menu.findItem(R.id.feedback_menu_item);
    159         return true;
    160     }
    161 
    162     @Override
    163     public boolean onPrepareOptionsMenu(Menu menu) {
    164         super.onPrepareOptionsMenu(menu);
    165 
    166         if (mFeedbackMenuItem != null) {
    167             // We only want to enable the feedback menu item, if there is a valid feedback uri
    168             mFeedbackMenuItem.setVisible(!Uri.EMPTY.equals(mFeedbackUri));
    169         }
    170         return true;
    171     }
    172 
    173 
    174     @Override
    175     public boolean onOptionsItemSelected(MenuItem item) {
    176         switch (item.getItemId()) {
    177             case android.R.id.home:
    178                 // The app icon on the action bar is pressed.  Just emulate a back press.
    179                 // TODO: this should navigate to the main screen, even if a sub-setting is open.
    180                 // But we shouldn't just finish(), as we want to show "discard changes?" dialog
    181                 // when necessary.
    182                 onBackPressed();
    183                 break;
    184             case R.id.feedback_menu_item:
    185                 Utils.sendFeedback(this, mFeedbackUri, false /* reportingProblem */);
    186                 break;
    187             default:
    188                 return super.onOptionsItemSelected(item);
    189         }
    190         return true;
    191     }
    192 
    193     @Override
    194     public boolean isValidFragment(String fragmentName) {
    195         // This activity is not exported, so we can allow any fragment
    196         return true;
    197     }
    198 
    199     private void enableDebugMenu() {
    200         mShowDebugMenu = true;
    201         invalidateHeaders();
    202     }
    203 
    204     private void onAddNewAccount() {
    205         final Intent setupIntent = AuthenticatorSetupIntentHelper.actionNewAccountIntent(this);
    206         startActivity(setupIntent);
    207     }
    208 
    209     @Override
    210     public void onBuildExtraHeaders(List<Header> target) {
    211         super.onBuildExtraHeaders(target);
    212 
    213         loadHeadersFromResource(R.xml.email_extra_preference_headers, target);
    214 
    215         // if debug header is enabled, show it
    216         if (DEBUG_MENU_ALLOWED) {
    217             if (mShowDebugMenu) {
    218                 // setup lightweight header for debugging
    219                 final Header debugHeader = new Header();
    220                 debugHeader.title = getText(R.string.debug_title);
    221                 debugHeader.summary = null;
    222                 debugHeader.iconRes = 0;
    223                 debugHeader.fragment = DebugFragment.class.getCanonicalName();
    224                 debugHeader.fragmentArguments = null;
    225                 target.add(debugHeader);
    226             }
    227         }
    228     }
    229 
    230     /**
    231      * Called when the user selects an item in the header list.  Handles save-data cases as needed
    232      *
    233      * @param header The header that was selected.
    234      * @param position The header's position in the list.
    235      */
    236     @Override
    237     public void onHeaderClick(@NonNull Header header, int position) {
    238         // Secret keys:  Click 10x to enable debug settings
    239         if (position == 0) {
    240             mNumGeneralHeaderClicked++;
    241             if (mNumGeneralHeaderClicked == 10) {
    242                 enableDebugMenu();
    243             }
    244         } else {
    245             mNumGeneralHeaderClicked = 0;
    246         }
    247         if (header.id == R.id.add_account_header) {
    248             onAddNewAccount();
    249             return;
    250         }
    251 
    252         // Process header click normally
    253         super.onHeaderClick(header, position);
    254     }
    255 
    256     @Override
    257     public void onAttachFragment(Fragment f) {
    258         super.onAttachFragment(f);
    259         // When we're changing fragments, enable/disable the add account button
    260         invalidateOptionsMenu();
    261     }
    262 }
    263