blob: 7f5ce4eb6fe2cf17b89d9ac669fa08768b7470c2 [file] [log] [blame]
Chiao Cheng6fe32c02012-12-04 15:44:17 -08001/*
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
Gary Mai69c182a2016-12-05 13:07:03 -080017package com.android.contacts.interactions;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080018
Sai Cheemalapati8ee2e272014-08-06 10:30:21 -070019import android.app.Activity;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080020import android.app.AlertDialog;
21import android.app.Dialog;
Brian Attwellc2e912c2014-10-27 12:29:44 -070022import android.app.DialogFragment;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080023import android.app.FragmentManager;
24import android.content.Context;
25import android.content.DialogInterface;
Marcus Hagerotta8b448a2016-11-18 12:51:39 -080026import android.content.Intent;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080027import android.content.res.Resources;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080028import android.os.Bundle;
Brian Attwellc07c8bb2014-10-06 14:55:49 -070029import android.text.TextUtils;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080030import android.util.Log;
31import android.view.LayoutInflater;
32import android.view.View;
33import android.view.ViewGroup;
34import android.widget.ArrayAdapter;
35import android.widget.TextView;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080036
Arthur Wang3f6a2442016-12-05 14:51:59 -080037import com.android.contacts.R;
Gary Mai0a49afa2016-12-05 15:53:58 -080038import com.android.contacts.activities.SimImportActivity;
Gary Mai69c182a2016-12-05 13:07:03 -080039import com.android.contacts.compat.CompatUtils;
40import com.android.contacts.compat.PhoneNumberUtilsCompat;
41import com.android.contacts.database.SimContactDao;
Gary Mai0a49afa2016-12-05 15:53:58 -080042import com.android.contacts.editor.SelectAccountDialogFragment;
Gary Mai69c182a2016-12-05 13:07:03 -080043import com.android.contacts.model.AccountTypeManager;
44import com.android.contacts.model.SimCard;
45import com.android.contacts.model.SimContact;
46import com.android.contacts.model.account.AccountWithDataSet;
47import com.android.contacts.util.AccountSelectionUtil;
48import com.android.contacts.util.AccountsListAdapter.AccountListFilter;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080049
50import java.util.List;
51
52/**
53 * An dialog invoked to import/export contacts.
54 */
Wenyi Wangc3322282016-11-11 14:53:29 -080055public class ImportDialogFragment extends DialogFragment {
James Laskey1e2102f2016-09-19 10:09:08 -070056 public static final String TAG = "ImportDialogFragment";
Wenyi Wangc33f4922015-09-24 15:28:59 -070057
Wenyi Wangc3322282016-11-11 14:53:29 -080058 public static final String KEY_RES_ID = "resourceId";
59 public static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
Chiao Cheng6fe32c02012-12-04 15:44:17 -080060
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070061 public static final String EXTRA_SIM_ONLY = "extraSimOnly";
62
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070063 public static final String EXTRA_SIM_CONTACT_COUNT_PREFIX = "simContactCount_";
64
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070065 private boolean mSimOnly = false;
Marcus Hagerott216e2972016-10-26 15:53:42 -070066 private SimContactDao mSimDao;
Wenyi Wangc33f4922015-09-24 15:28:59 -070067
Chiao Cheng6fe32c02012-12-04 15:44:17 -080068 /** Preferred way to show this dialog */
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070069 public static void show(FragmentManager fragmentManager) {
70 final ImportDialogFragment fragment = new ImportDialogFragment();
71 fragment.show(fragmentManager, TAG);
72 }
73
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070074 public static void show(FragmentManager fragmentManager, List<SimCard> sims,
75 boolean includeVcf) {
James Laskey1e2102f2016-09-19 10:09:08 -070076 final ImportDialogFragment fragment = new ImportDialogFragment();
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070077 final Bundle args = new Bundle();
78 args.putBoolean(EXTRA_SIM_ONLY, !includeVcf);
79 for (SimCard sim : sims) {
80 final List<SimContact> contacts = sim.getContacts();
81 if (contacts == null) {
82 continue;
83 }
84 args.putInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), contacts.size());
85 }
86
Chiao Cheng6fe32c02012-12-04 15:44:17 -080087 fragment.setArguments(args);
James Laskey1e2102f2016-09-19 10:09:08 -070088 fragment.show(fragmentManager, TAG);
Chiao Cheng6fe32c02012-12-04 15:44:17 -080089 }
90
91 @Override
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070092 public void onCreate(Bundle savedInstanceState) {
93 super.onCreate(savedInstanceState);
94
Sean Midford9da13ab2016-11-07 14:15:54 -080095 setStyle(STYLE_NORMAL, R.style.ContactsAlertDialogTheme);
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070096
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070097 final Bundle args = getArguments();
98 mSimOnly = args != null && args.getBoolean(EXTRA_SIM_ONLY, false);
Marcus Hagerott216e2972016-10-26 15:53:42 -070099 mSimDao = SimContactDao.create(getContext());
Marcus Hagerott02f5dba2016-10-18 12:34:57 -0700100 }
101
102 @Override
Wenyi Wang9342fbb2015-11-17 19:36:35 -0800103 public Context getContext() {
104 return getActivity();
105 }
106
107 @Override
Sai Cheemalapati8ee2e272014-08-06 10:30:21 -0700108 public void onAttach(Activity activity) {
109 super.onAttach(activity);
Sai Cheemalapati8ee2e272014-08-06 10:30:21 -0700110 }
111
112 @Override
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800113 public Dialog onCreateDialog(Bundle savedInstanceState) {
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700114 final LayoutInflater dialogInflater = (LayoutInflater)
115 getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800116
117 // Adapter that shows a list of string resources
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700118 final ArrayAdapter<AdapterEntry> adapter = new ArrayAdapter<AdapterEntry>(getActivity(),
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800119 R.layout.select_dialog_item) {
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700120
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800121 @Override
122 public View getView(int position, View convertView, ViewGroup parent) {
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700123 final View result = convertView != null ? convertView :
124 dialogInflater.inflate(R.layout.select_dialog_item, parent, false);
125 final TextView primaryText = (TextView) result.findViewById(R.id.primary_text);
126 final TextView secondaryText = (TextView) result.findViewById(R.id.secondary_text);
127 final AdapterEntry entry = getItem(position);
128 secondaryText.setVisibility(View.GONE);
129 if (entry.mChoiceResourceId == R.string.import_from_sim) {
130 final CharSequence secondary = getSimSecondaryText(entry.mSim);
131 if (TextUtils.isEmpty(secondary)) {
132 secondaryText.setVisibility(View.GONE);
133 } else {
134 secondaryText.setText(secondary);
135 secondaryText.setVisibility(View.VISIBLE);
136 }
137 }
138 primaryText.setText(entry.mLabel);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800139 return result;
140 }
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700141
142 CharSequence getSimSecondaryText(SimCard sim) {
143 int count = getSimContactCount(sim);
144
145 CharSequence phone = sim.getFormattedPhone();
146 if (phone == null) {
147 phone = sim.getPhone();
148 }
149 if (phone != null) {
150 phone = PhoneNumberUtilsCompat.createTtsSpannable(phone);
151 }
152
153 if (count != -1 && phone != null) {
154 // We use a template instead of format string so that the TTS span is preserved
155 final CharSequence template = getResources()
156 .getQuantityString(R.plurals.import_from_sim_secondary_template, count);
157 return TextUtils.expandTemplate(template, String.valueOf(count), phone);
158 } else if (phone != null) {
159 return phone;
160 } else if (count != -1) {
161 // count != -1
162 return getResources()
163 .getQuantityString(
164 R.plurals.import_from_sim_secondary_contact_count_fmt, count,
165 count);
166 } else {
167 return null;
168 }
169 }
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800170 };
171
Marcus Hagerott216e2972016-10-26 15:53:42 -0700172 addItems(adapter);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800173
174 final DialogInterface.OnClickListener clickListener =
175 new DialogInterface.OnClickListener() {
176 @Override
177 public void onClick(DialogInterface dialog, int which) {
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700178 final int resId = adapter.getItem(which).mChoiceResourceId;
Marcus Hagerott819214d2016-09-29 14:58:27 -0700179 if (resId == R.string.import_from_sim) {
Wenyi Wangc3322282016-11-11 14:53:29 -0800180 handleSimImportRequest(adapter.getItem(which).mSim);
Marcus Hagerott819214d2016-09-29 14:58:27 -0700181 } else if (resId == R.string.import_from_vcf_file) {
Wenyi Wangc3322282016-11-11 14:53:29 -0800182 handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
Sailesh Nepalb4a522e2016-02-20 21:17:32 -0800183 } else {
Sailesh Nepalb4a522e2016-02-20 21:17:32 -0800184 Log.e(TAG, "Unexpected resource: "
185 + getActivity().getResources().getResourceEntryName(resId));
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800186 }
Wenyi Wangc3322282016-11-11 14:53:29 -0800187 dialog.dismiss();
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800188 }
189 };
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700190
191 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), getTheme())
192 .setTitle(R.string.dialog_import)
193 .setNegativeButton(android.R.string.cancel, null);
194 if (adapter.isEmpty()) {
195 // Handle edge case; e.g. SIM card was removed.
196 builder.setMessage(R.string.nothing_to_import_message);
197 } else {
198 builder.setSingleChoiceItems(adapter, -1, clickListener);
199 }
200
201 return builder.create();
202 }
203
204 private int getSimContactCount(SimCard sim) {
205 if (sim.getContacts() != null) {
206 return sim.getContacts().size();
207 }
208 final Bundle args = getArguments();
209 if (args == null) {
210 return -1;
211 }
212 return args.getInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), -1);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800213 }
214
Marcus Hagerott216e2972016-10-26 15:53:42 -0700215 private void addItems(ArrayAdapter<AdapterEntry> adapter) {
216 final Resources res = getActivity().getResources();
217 if (res.getBoolean(R.bool.config_allow_import_from_vcf_file) && !mSimOnly) {
218 adapter.add(new AdapterEntry(getString(R.string.import_from_vcf_file),
219 R.string.import_from_vcf_file));
220 }
221 final List<SimCard> sims = mSimDao.getSimCards();
222
223 if (sims.size() == 1) {
224 adapter.add(new AdapterEntry(getString(R.string.import_from_sim),
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700225 R.string.import_from_sim, sims.get(0)));
Marcus Hagerott216e2972016-10-26 15:53:42 -0700226 return;
227 }
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700228 for (int i = 0; i < sims.size(); i++) {
229 final SimCard sim = sims.get(i);
230 adapter.add(new AdapterEntry(getSimDescription(sim, i), R.string.import_from_sim, sim));
Marcus Hagerott216e2972016-10-26 15:53:42 -0700231 }
232 }
233
Wenyi Wangc3322282016-11-11 14:53:29 -0800234 private void handleSimImportRequest(SimCard sim) {
Marcus Hagerotta8b448a2016-11-18 12:51:39 -0800235 startActivity(new Intent(getActivity(), SimImportActivity.class)
236 .putExtra(SimImportActivity.EXTRA_SUBSCRIPTION_ID, sim.getSubscriptionId()));
Marcus Hagerott819214d2016-09-29 14:58:27 -0700237 }
238
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800239 /**
Marcus Hagerott819214d2016-09-29 14:58:27 -0700240 * Handle "import from SD".
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800241 */
Wenyi Wangc3322282016-11-11 14:53:29 -0800242 private void handleImportRequest(int resId, int subscriptionId) {
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800243 // There are three possibilities:
244 // - more than one accounts -> ask the user
245 // - just one account -> use the account without asking the user
246 // - no account -> use phone-local storage without asking the user
247 final AccountTypeManager accountTypes = AccountTypeManager.getInstance(getActivity());
248 final List<AccountWithDataSet> accountList = accountTypes.getAccounts(true);
249 final int size = accountList.size();
250 if (size > 1) {
251 // Send over to the account selector
252 final Bundle args = new Bundle();
253 args.putInt(KEY_RES_ID, resId);
Jay Shraunercf082222014-11-25 13:52:50 -0800254 args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800255 SelectAccountDialogFragment.show(
Wenyi Wangc3322282016-11-11 14:53:29 -0800256 getFragmentManager(), R.string.dialog_new_contact_account,
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800257 AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, args);
Wenyi Wangc3322282016-11-11 14:53:29 -0800258 } else {
259 AccountSelectionUtil.doImport(getActivity(), resId,
260 (size == 1 ? accountList.get(0) : null),
261 (CompatUtils.isMSIMCompatible() ? subscriptionId : -1));
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800262 }
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800263 }
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700264
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700265 private CharSequence getSimDescription(SimCard sim, int index) {
Marcus Hagerott216e2972016-10-26 15:53:42 -0700266 final CharSequence name = sim.getDisplayName();
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700267 if (name != null) {
Marcus Hagerott216e2972016-10-26 15:53:42 -0700268 return getString(R.string.import_from_sim_summary_fmt, name);
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700269 } else {
270 return getString(R.string.import_from_sim_summary_fmt, String.valueOf(index));
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700271 }
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700272 }
273
274 private static class AdapterEntry {
Ihab Awad37321802014-12-05 16:23:11 -0800275 public final CharSequence mLabel;
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700276 public final int mChoiceResourceId;
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700277 public final SimCard mSim;
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700278
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700279 public AdapterEntry(CharSequence label, int resId, SimCard sim) {
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700280 mLabel = label;
281 mChoiceResourceId = resId;
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700282 mSim = sim;
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700283 }
284
285 public AdapterEntry(String label, int resId) {
Brian Attwell87ffb822015-02-03 10:28:11 -0800286 // Store a nonsense value for mSubscriptionId. If this constructor is used,
287 // the mSubscriptionId value should not be read later.
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700288 this(label, resId, /* sim= */ null);
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700289 }
290 }
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800291}