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