blob: 1b2c98da81d382968cdfe18507953e0cc0533071 [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
17package com.android.contacts.common.interactions;
18
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
Marcus Hagerott819214d2016-09-29 14:58:27 -070037import com.android.contacts.SimImportFragment;
Marcus Hagerotta8b448a2016-11-18 12:51:39 -080038import com.android.contacts.activities.SimImportActivity;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080039import com.android.contacts.common.R;
Wenyi Wang13d952e2015-12-09 09:44:44 -080040import com.android.contacts.common.compat.CompatUtils;
Brandon Maxwell62cfa6e2015-12-04 15:27:45 -080041import com.android.contacts.common.compat.PhoneNumberUtilsCompat;
Marcus Hagerott216e2972016-10-26 15:53:42 -070042import com.android.contacts.common.database.SimContactDao;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080043import com.android.contacts.common.model.AccountTypeManager;
Marcus Hagerott216e2972016-10-26 15:53:42 -070044import com.android.contacts.common.model.SimCard;
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070045import com.android.contacts.common.model.SimContact;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080046import com.android.contacts.common.model.account.AccountWithDataSet;
47import com.android.contacts.common.util.AccountSelectionUtil;
48import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
Walter Jang55d0e712016-08-31 17:11:36 -070049import com.android.contacts.editor.SelectAccountDialogFragment;
Chiao Cheng6fe32c02012-12-04 15:44:17 -080050
51import java.util.List;
52
53/**
54 * An dialog invoked to import/export contacts.
55 */
Wenyi Wangc3322282016-11-11 14:53:29 -080056public class ImportDialogFragment extends DialogFragment {
James Laskey1e2102f2016-09-19 10:09:08 -070057 public static final String TAG = "ImportDialogFragment";
Wenyi Wangc33f4922015-09-24 15:28:59 -070058
Wenyi Wangc3322282016-11-11 14:53:29 -080059 public static final String KEY_RES_ID = "resourceId";
60 public static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
Chiao Cheng6fe32c02012-12-04 15:44:17 -080061
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070062 public static final String EXTRA_SIM_ONLY = "extraSimOnly";
63
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070064 public static final String EXTRA_SIM_CONTACT_COUNT_PREFIX = "simContactCount_";
65
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070066 private boolean mSimOnly = false;
Marcus Hagerott216e2972016-10-26 15:53:42 -070067 private SimContactDao mSimDao;
Wenyi Wangc33f4922015-09-24 15:28:59 -070068
Chiao Cheng6fe32c02012-12-04 15:44:17 -080069 /** Preferred way to show this dialog */
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070070 public static void show(FragmentManager fragmentManager) {
71 final ImportDialogFragment fragment = new ImportDialogFragment();
72 fragment.show(fragmentManager, TAG);
73 }
74
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070075 public static void show(FragmentManager fragmentManager, List<SimCard> sims,
76 boolean includeVcf) {
James Laskey1e2102f2016-09-19 10:09:08 -070077 final ImportDialogFragment fragment = new ImportDialogFragment();
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070078 final Bundle args = new Bundle();
79 args.putBoolean(EXTRA_SIM_ONLY, !includeVcf);
80 for (SimCard sim : sims) {
81 final List<SimContact> contacts = sim.getContacts();
82 if (contacts == null) {
83 continue;
84 }
85 args.putInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), contacts.size());
86 }
87
Chiao Cheng6fe32c02012-12-04 15:44:17 -080088 fragment.setArguments(args);
James Laskey1e2102f2016-09-19 10:09:08 -070089 fragment.show(fragmentManager, TAG);
Chiao Cheng6fe32c02012-12-04 15:44:17 -080090 }
91
92 @Override
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070093 public void onCreate(Bundle savedInstanceState) {
94 super.onCreate(savedInstanceState);
95
Sean Midford9da13ab2016-11-07 14:15:54 -080096 setStyle(STYLE_NORMAL, R.style.ContactsAlertDialogTheme);
Marcus Hagerott8636d1e2016-10-27 19:14:12 -070097
Marcus Hagerott02f5dba2016-10-18 12:34:57 -070098 final Bundle args = getArguments();
99 mSimOnly = args != null && args.getBoolean(EXTRA_SIM_ONLY, false);
Marcus Hagerott216e2972016-10-26 15:53:42 -0700100 mSimDao = SimContactDao.create(getContext());
Marcus Hagerott02f5dba2016-10-18 12:34:57 -0700101 }
102
103 @Override
Wenyi Wang9342fbb2015-11-17 19:36:35 -0800104 public Context getContext() {
105 return getActivity();
106 }
107
108 @Override
Sai Cheemalapati8ee2e272014-08-06 10:30:21 -0700109 public void onAttach(Activity activity) {
110 super.onAttach(activity);
Sai Cheemalapati8ee2e272014-08-06 10:30:21 -0700111 }
112
113 @Override
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800114 public Dialog onCreateDialog(Bundle savedInstanceState) {
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700115 final LayoutInflater dialogInflater = (LayoutInflater)
116 getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800117
118 // Adapter that shows a list of string resources
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700119 final ArrayAdapter<AdapterEntry> adapter = new ArrayAdapter<AdapterEntry>(getActivity(),
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800120 R.layout.select_dialog_item) {
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700121
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800122 @Override
123 public View getView(int position, View convertView, ViewGroup parent) {
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700124 final View result = convertView != null ? convertView :
125 dialogInflater.inflate(R.layout.select_dialog_item, parent, false);
126 final TextView primaryText = (TextView) result.findViewById(R.id.primary_text);
127 final TextView secondaryText = (TextView) result.findViewById(R.id.secondary_text);
128 final AdapterEntry entry = getItem(position);
129 secondaryText.setVisibility(View.GONE);
130 if (entry.mChoiceResourceId == R.string.import_from_sim) {
131 final CharSequence secondary = getSimSecondaryText(entry.mSim);
132 if (TextUtils.isEmpty(secondary)) {
133 secondaryText.setVisibility(View.GONE);
134 } else {
135 secondaryText.setText(secondary);
136 secondaryText.setVisibility(View.VISIBLE);
137 }
138 }
139 primaryText.setText(entry.mLabel);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800140 return result;
141 }
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700142
143 CharSequence getSimSecondaryText(SimCard sim) {
144 int count = getSimContactCount(sim);
145
146 CharSequence phone = sim.getFormattedPhone();
147 if (phone == null) {
148 phone = sim.getPhone();
149 }
150 if (phone != null) {
151 phone = PhoneNumberUtilsCompat.createTtsSpannable(phone);
152 }
153
154 if (count != -1 && phone != null) {
155 // We use a template instead of format string so that the TTS span is preserved
156 final CharSequence template = getResources()
157 .getQuantityString(R.plurals.import_from_sim_secondary_template, count);
158 return TextUtils.expandTemplate(template, String.valueOf(count), phone);
159 } else if (phone != null) {
160 return phone;
161 } else if (count != -1) {
162 // count != -1
163 return getResources()
164 .getQuantityString(
165 R.plurals.import_from_sim_secondary_contact_count_fmt, count,
166 count);
167 } else {
168 return null;
169 }
170 }
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800171 };
172
Marcus Hagerott216e2972016-10-26 15:53:42 -0700173 addItems(adapter);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800174
175 final DialogInterface.OnClickListener clickListener =
176 new DialogInterface.OnClickListener() {
177 @Override
178 public void onClick(DialogInterface dialog, int which) {
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700179 final int resId = adapter.getItem(which).mChoiceResourceId;
Marcus Hagerott819214d2016-09-29 14:58:27 -0700180 if (resId == R.string.import_from_sim) {
Wenyi Wangc3322282016-11-11 14:53:29 -0800181 handleSimImportRequest(adapter.getItem(which).mSim);
Marcus Hagerott819214d2016-09-29 14:58:27 -0700182 } else if (resId == R.string.import_from_vcf_file) {
Wenyi Wangc3322282016-11-11 14:53:29 -0800183 handleImportRequest(resId, SimCard.NO_SUBSCRIPTION_ID);
Sailesh Nepalb4a522e2016-02-20 21:17:32 -0800184 } else {
Sailesh Nepalb4a522e2016-02-20 21:17:32 -0800185 Log.e(TAG, "Unexpected resource: "
186 + getActivity().getResources().getResourceEntryName(resId));
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800187 }
Wenyi Wangc3322282016-11-11 14:53:29 -0800188 dialog.dismiss();
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800189 }
190 };
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700191
192 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), getTheme())
193 .setTitle(R.string.dialog_import)
194 .setNegativeButton(android.R.string.cancel, null);
195 if (adapter.isEmpty()) {
196 // Handle edge case; e.g. SIM card was removed.
197 builder.setMessage(R.string.nothing_to_import_message);
198 } else {
199 builder.setSingleChoiceItems(adapter, -1, clickListener);
200 }
201
202 return builder.create();
203 }
204
205 private int getSimContactCount(SimCard sim) {
206 if (sim.getContacts() != null) {
207 return sim.getContacts().size();
208 }
209 final Bundle args = getArguments();
210 if (args == null) {
211 return -1;
212 }
213 return args.getInt(EXTRA_SIM_CONTACT_COUNT_PREFIX + sim.getSimId(), -1);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800214 }
215
Marcus Hagerott216e2972016-10-26 15:53:42 -0700216 private void addItems(ArrayAdapter<AdapterEntry> adapter) {
217 final Resources res = getActivity().getResources();
218 if (res.getBoolean(R.bool.config_allow_import_from_vcf_file) && !mSimOnly) {
219 adapter.add(new AdapterEntry(getString(R.string.import_from_vcf_file),
220 R.string.import_from_vcf_file));
221 }
222 final List<SimCard> sims = mSimDao.getSimCards();
223
224 if (sims.size() == 1) {
225 adapter.add(new AdapterEntry(getString(R.string.import_from_sim),
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700226 R.string.import_from_sim, sims.get(0)));
Marcus Hagerott216e2972016-10-26 15:53:42 -0700227 return;
228 }
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700229 for (int i = 0; i < sims.size(); i++) {
230 final SimCard sim = sims.get(i);
231 adapter.add(new AdapterEntry(getSimDescription(sim, i), R.string.import_from_sim, sim));
Marcus Hagerott216e2972016-10-26 15:53:42 -0700232 }
233 }
234
Wenyi Wangc3322282016-11-11 14:53:29 -0800235 private void handleSimImportRequest(SimCard sim) {
Marcus Hagerotta8b448a2016-11-18 12:51:39 -0800236 startActivity(new Intent(getActivity(), SimImportActivity.class)
237 .putExtra(SimImportActivity.EXTRA_SUBSCRIPTION_ID, sim.getSubscriptionId()));
Marcus Hagerott819214d2016-09-29 14:58:27 -0700238 }
239
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800240 /**
Marcus Hagerott819214d2016-09-29 14:58:27 -0700241 * Handle "import from SD".
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800242 */
Wenyi Wangc3322282016-11-11 14:53:29 -0800243 private void handleImportRequest(int resId, int subscriptionId) {
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800244 // There are three possibilities:
245 // - more than one accounts -> ask the user
246 // - just one account -> use the account without asking the user
247 // - no account -> use phone-local storage without asking the user
248 final AccountTypeManager accountTypes = AccountTypeManager.getInstance(getActivity());
249 final List<AccountWithDataSet> accountList = accountTypes.getAccounts(true);
250 final int size = accountList.size();
251 if (size > 1) {
252 // Send over to the account selector
253 final Bundle args = new Bundle();
254 args.putInt(KEY_RES_ID, resId);
Jay Shraunercf082222014-11-25 13:52:50 -0800255 args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800256 SelectAccountDialogFragment.show(
Wenyi Wangc3322282016-11-11 14:53:29 -0800257 getFragmentManager(), R.string.dialog_new_contact_account,
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800258 AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, args);
Wenyi Wangc3322282016-11-11 14:53:29 -0800259 } else {
260 AccountSelectionUtil.doImport(getActivity(), resId,
261 (size == 1 ? accountList.get(0) : null),
262 (CompatUtils.isMSIMCompatible() ? subscriptionId : -1));
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800263 }
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800264 }
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700265
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700266 private CharSequence getSimDescription(SimCard sim, int index) {
Marcus Hagerott216e2972016-10-26 15:53:42 -0700267 final CharSequence name = sim.getDisplayName();
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700268 if (name != null) {
Marcus Hagerott216e2972016-10-26 15:53:42 -0700269 return getString(R.string.import_from_sim_summary_fmt, name);
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700270 } else {
271 return getString(R.string.import_from_sim_summary_fmt, String.valueOf(index));
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700272 }
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700273 }
274
275 private static class AdapterEntry {
Ihab Awad37321802014-12-05 16:23:11 -0800276 public final CharSequence mLabel;
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700277 public final int mChoiceResourceId;
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700278 public final SimCard mSim;
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700279
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700280 public AdapterEntry(CharSequence label, int resId, SimCard sim) {
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700281 mLabel = label;
282 mChoiceResourceId = resId;
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700283 mSim = sim;
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700284 }
285
286 public AdapterEntry(String label, int resId) {
Brian Attwell87ffb822015-02-03 10:28:11 -0800287 // Store a nonsense value for mSubscriptionId. If this constructor is used,
288 // the mSubscriptionId value should not be read later.
Marcus Hagerott8636d1e2016-10-27 19:14:12 -0700289 this(label, resId, /* sim= */ null);
Brian Attwellc07c8bb2014-10-06 14:55:49 -0700290 }
291 }
Chiao Cheng6fe32c02012-12-04 15:44:17 -0800292}