Home | History | Annotate | Download | only in interactions
      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.contacts.common.interactions;
     18 
     19 import android.app.Activity;
     20 import android.app.AlertDialog;
     21 import android.app.Dialog;
     22 import android.app.FragmentManager;
     23 import android.content.Context;
     24 import android.content.DialogInterface;
     25 import android.content.Intent;
     26 import android.content.res.Resources;
     27 import android.database.Cursor;
     28 import android.net.Uri;
     29 import android.os.Bundle;
     30 import android.provider.ContactsContract.Contacts;
     31 import android.telephony.TelephonyManager;
     32 import android.util.Log;
     33 import android.view.LayoutInflater;
     34 import android.view.View;
     35 import android.view.ViewGroup;
     36 import android.widget.ArrayAdapter;
     37 import android.widget.TextView;
     38 import android.widget.Toast;
     39 
     40 import com.android.contacts.common.R;
     41 import com.android.contacts.common.editor.SelectAccountDialogFragment;
     42 import com.android.contacts.common.model.AccountTypeManager;
     43 import com.android.contacts.common.model.account.AccountWithDataSet;
     44 import com.android.contacts.common.util.AccountSelectionUtil;
     45 import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
     46 import com.android.contacts.common.vcard.ExportVCardActivity;
     47 import com.android.contacts.common.vcard.VCardCommonArguments;
     48 import com.android.dialerbind.analytics.AnalyticsDialogFragment;
     49 
     50 import java.util.List;
     51 
     52 /**
     53  * An dialog invoked to import/export contacts.
     54  */
     55 public class ImportExportDialogFragment extends AnalyticsDialogFragment
     56         implements SelectAccountDialogFragment.Listener {
     57     public static final String TAG = "ImportExportDialogFragment";
     58 
     59     private static final String KEY_RES_ID = "resourceId";
     60     private static final String ARG_CONTACTS_ARE_AVAILABLE = "CONTACTS_ARE_AVAILABLE";
     61 
     62     private final String[] LOOKUP_PROJECTION = new String[] {
     63             Contacts.LOOKUP_KEY
     64     };
     65 
     66     /** Preferred way to show this dialog */
     67     public static void show(FragmentManager fragmentManager, boolean contactsAreAvailable,
     68             Class callingActivity) {
     69         final ImportExportDialogFragment fragment = new ImportExportDialogFragment();
     70         Bundle args = new Bundle();
     71         args.putBoolean(ARG_CONTACTS_ARE_AVAILABLE, contactsAreAvailable);
     72         args.putString(VCardCommonArguments.ARG_CALLING_ACTIVITY, callingActivity.getName());
     73         fragment.setArguments(args);
     74         fragment.show(fragmentManager, ImportExportDialogFragment.TAG);
     75     }
     76 
     77     @Override
     78     public void onAttach(Activity activity) {
     79         super.onAttach(activity);
     80         sendScreenView();
     81     }
     82 
     83     @Override
     84     public Dialog onCreateDialog(Bundle savedInstanceState) {
     85         // Wrap our context to inflate list items using the correct theme
     86         final Resources res = getActivity().getResources();
     87         final LayoutInflater dialogInflater = (LayoutInflater)getActivity()
     88                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     89         final boolean contactsAreAvailable = getArguments().getBoolean(ARG_CONTACTS_ARE_AVAILABLE);
     90         final String callingActivity = getArguments().getString(
     91                 VCardCommonArguments.ARG_CALLING_ACTIVITY);
     92 
     93         // Adapter that shows a list of string resources
     94         final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(getActivity(),
     95                 R.layout.select_dialog_item) {
     96             @Override
     97             public View getView(int position, View convertView, ViewGroup parent) {
     98                 final TextView result = (TextView)(convertView != null ? convertView :
     99                         dialogInflater.inflate(R.layout.select_dialog_item, parent, false));
    100 
    101                 final int resId = getItem(position);
    102                 result.setText(resId);
    103                 return result;
    104             }
    105         };
    106 
    107         final TelephonyManager manager =
    108                 (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
    109 
    110         if (manager != null && manager.hasIccCard()
    111                 && res.getBoolean(R.bool.config_allow_sim_import)) {
    112             adapter.add(R.string.import_from_sim);
    113         }
    114         if (res.getBoolean(R.bool.config_allow_import_from_sdcard)) {
    115             adapter.add(R.string.import_from_sdcard);
    116         }
    117         if (res.getBoolean(R.bool.config_allow_export_to_sdcard)) {
    118             if (contactsAreAvailable) {
    119                 adapter.add(R.string.export_to_sdcard);
    120             }
    121         }
    122         if (res.getBoolean(R.bool.config_allow_share_visible_contacts)) {
    123             if (contactsAreAvailable) {
    124                 adapter.add(R.string.share_visible_contacts);
    125             }
    126         }
    127 
    128         final DialogInterface.OnClickListener clickListener =
    129                 new DialogInterface.OnClickListener() {
    130             @Override
    131             public void onClick(DialogInterface dialog, int which) {
    132                 boolean dismissDialog;
    133                 final int resId = adapter.getItem(which);
    134                 switch (resId) {
    135                     case R.string.import_from_sim:
    136                     case R.string.import_from_sdcard: {
    137                         dismissDialog = handleImportRequest(resId);
    138                         break;
    139                     }
    140                     case R.string.export_to_sdcard: {
    141                         dismissDialog = true;
    142                         Intent exportIntent = new Intent(getActivity(), ExportVCardActivity.class);
    143                         exportIntent.putExtra(VCardCommonArguments.ARG_CALLING_ACTIVITY,
    144                                 callingActivity);
    145                         getActivity().startActivity(exportIntent);
    146                         break;
    147                     }
    148                     case R.string.share_visible_contacts: {
    149                         dismissDialog = true;
    150                         doShareVisibleContacts();
    151                         break;
    152                     }
    153                     default: {
    154                         dismissDialog = true;
    155                         Log.e(TAG, "Unexpected resource: "
    156                                 + getActivity().getResources().getResourceEntryName(resId));
    157                     }
    158                 }
    159                 if (dismissDialog) {
    160                     dialog.dismiss();
    161                 }
    162             }
    163         };
    164         return new AlertDialog.Builder(getActivity())
    165                 .setTitle(contactsAreAvailable
    166                         ? R.string.dialog_import_export
    167                         : R.string.dialog_import)
    168                 .setSingleChoiceItems(adapter, -1, clickListener)
    169                 .create();
    170     }
    171 
    172     private void doShareVisibleContacts() {
    173         // TODO move the query into a loader and do this in a background thread
    174         final Cursor cursor = getActivity().getContentResolver().query(Contacts.CONTENT_URI,
    175                 LOOKUP_PROJECTION, Contacts.IN_VISIBLE_GROUP + "!=0", null, null);
    176         if (cursor != null) {
    177             try {
    178                 if (!cursor.moveToFirst()) {
    179                     Toast.makeText(getActivity(), R.string.share_error, Toast.LENGTH_SHORT).show();
    180                     return;
    181                 }
    182 
    183                 StringBuilder uriListBuilder = new StringBuilder();
    184                 int index = 0;
    185                 do {
    186                     if (index != 0)
    187                         uriListBuilder.append(':');
    188                     uriListBuilder.append(cursor.getString(0));
    189                     index++;
    190                 } while (cursor.moveToNext());
    191                 Uri uri = Uri.withAppendedPath(
    192                         Contacts.CONTENT_MULTI_VCARD_URI,
    193                         Uri.encode(uriListBuilder.toString()));
    194 
    195                 final Intent intent = new Intent(Intent.ACTION_SEND);
    196                 intent.setType(Contacts.CONTENT_VCARD_TYPE);
    197                 intent.putExtra(Intent.EXTRA_STREAM, uri);
    198                 getActivity().startActivity(intent);
    199             } finally {
    200                 cursor.close();
    201             }
    202         }
    203     }
    204 
    205     /**
    206      * Handle "import from SIM" and "import from SD".
    207      *
    208      * @return {@code true} if the dialog show be closed.  {@code false} otherwise.
    209      */
    210     private boolean handleImportRequest(int resId) {
    211         // There are three possibilities:
    212         // - more than one accounts -> ask the user
    213         // - just one account -> use the account without asking the user
    214         // - no account -> use phone-local storage without asking the user
    215         final AccountTypeManager accountTypes = AccountTypeManager.getInstance(getActivity());
    216         final List<AccountWithDataSet> accountList = accountTypes.getAccounts(true);
    217         final int size = accountList.size();
    218         if (size > 1) {
    219             // Send over to the account selector
    220             final Bundle args = new Bundle();
    221             args.putInt(KEY_RES_ID, resId);
    222             SelectAccountDialogFragment.show(
    223                     getFragmentManager(), this,
    224                     R.string.dialog_new_contact_account,
    225                     AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, args);
    226 
    227             // In this case, because this DialogFragment is used as a target fragment to
    228             // SelectAccountDialogFragment, we can't close it yet.  We close the dialog when
    229             // we get a callback from it.
    230             return false;
    231         }
    232 
    233         AccountSelectionUtil.doImport(getActivity(), resId,
    234                 (size == 1 ? accountList.get(0) : null));
    235         return true; // Close the dialog.
    236     }
    237 
    238     /**
    239      * Called when an account is selected on {@link SelectAccountDialogFragment}.
    240      */
    241     @Override
    242     public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
    243         AccountSelectionUtil.doImport(getActivity(), extraArgs.getInt(KEY_RES_ID), account);
    244 
    245         // At this point the dialog is still showing (which is why we can use getActivity() above)
    246         // So close it.
    247         dismiss();
    248     }
    249 
    250     @Override
    251     public void onAccountSelectorCancelled() {
    252         // See onAccountChosen() -- at this point the dialog is still showing.  Close it.
    253         dismiss();
    254     }
    255 }
    256