diff options
author | Walter Jang <wjang@google.com> | 2015-07-14 20:40:13 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-07-14 20:40:13 +0000 |
commit | 76d303fa5fa2ff107f0c233dd195787c9ed0b48b (patch) | |
tree | 2abff5b1853eef90573d36e8875cbf34e29a9885 | |
parent | 51f53811614d9185c8de800ed2403e9f3245b581 (diff) | |
parent | ed2a24cb0a9f207e4f1211cfff51bd8e6bcfad90 (diff) | |
download | packages_apps_ContactsCommon-76d303fa5fa2ff107f0c233dd195787c9ed0b48b.tar.gz packages_apps_ContactsCommon-76d303fa5fa2ff107f0c233dd195787c9ed0b48b.tar.bz2 packages_apps_ContactsCommon-76d303fa5fa2ff107f0c233dd195787c9ed0b48b.zip |
Merge "Allow the user to select the vcards to import" into mnc-dev
9 files changed, 63 insertions, 472 deletions
diff --git a/res/values/donottranslate_config.xml b/res/values/donottranslate_config.xml index 1e0ee401..9d9513bf 100644 --- a/res/values/donottranslate_config.xml +++ b/res/values/donottranslate_config.xml @@ -15,18 +15,8 @@ --> <resources> - <!-- Flag indicating whether Contacts app is allowed to import contacts from SDCard --> - <bool name="config_allow_import_from_sdcard">true</bool> - <!-- If true, all vcard files are imported from SDCard without asking a user. - If not, dialog shows to let the user to select whether all vcard files are imported or not. - If the user selects "not", then the application ask the user to select a file.--> - <bool name="config_import_all_vcard_from_sdcard_automatically">false</bool> - <!-- If true, vcard importer shows a dialog which asks the user whether the user wants - to import all vcard files in SDCard or select one vcard file. If false, the dialog is - skipped and the importer asks the user to choose one vcard file. - If config_import_all_vcard_from_sdcard_automatically is set true, this configuration - is ignored. --> - <bool name="config_allow_users_select_all_vcard_import">true</bool> + <!-- Flag indicating whether Contacts app is allowed to import contacts --> + <bool name="config_allow_import_from_vcf_file">true</bool> <!-- If true, an option is shown in Display Options UI to choose a sort order --> <bool name="config_sort_order_user_changeable">true</bool> diff --git a/res/values/ids.xml b/res/values/ids.xml index 41cee452..4ba65e11 100644 --- a/res/values/ids.xml +++ b/res/values/ids.xml @@ -16,14 +16,7 @@ <resources> <!-- For vcard.ImportVCardActivity --> - <item type="id" name="dialog_searching_vcard"/> - <item type="id" name="dialog_sdcard_not_found"/> - <item type="id" name="dialog_vcard_not_found"/> - <item type="id" name="dialog_select_import_type"/> - <item type="id" name="dialog_select_one_vcard"/> - <item type="id" name="dialog_select_multiple_vcard"/> <item type="id" name="dialog_cache_vcard"/> - <item type="id" name="dialog_io_exception"/> <item type="id" name="dialog_error_with_message"/> <!-- For vcard.CancelActivity --> diff --git a/res/values/strings.xml b/res/values/strings.xml index ddeee238..c3725a39 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -428,8 +428,8 @@ a ren't members of any other group. [CHAR LIMIT=25] --> <!-- Action string for selecting a SIM subscription for importing contacts, without a phone number --> <string name="import_from_sim_summary_no_number">Import from SIM <xliff:g id="sim_name">%1$s</xliff:g></string> - <!-- Action string for selecting (USB) storage for importing contacts [CHAR LIMIT=30] --> - <string name="import_from_sdcard" product="default">Import from storage</string> + <!-- Action string for selecting a .vcf file to import contacts from [CHAR LIMIT=30] --> + <string name="import_from_vcf_file" product="default">Import from .vcf file</string> <!-- Message shown in a Dialog confirming a user's cancel request toward existing vCard import. The argument is file name for the vCard import the user wants to cancel. @@ -545,11 +545,6 @@ a ren't members of any other group. [CHAR LIMIT=25] --> <!-- Dialog message shown when exporting Contact data failed. [CHAR LIMIT=NONE] --> <string name="exporting_contact_failed_message">The contact data wasn\'t exported.\nReason: \"<xliff:g id="fail_reason">%s</xliff:g>\"</string> - <!-- Dialog message shown when (USB) storage does not exist [CHAR LIMIT=30] --> - <string name="no_sdcard_message" product="nosdcard">No storage was found.</string> - <!-- Dialog message shown when SDcard does not exist. [CHAR LIMIT=30] --> - <string name="no_sdcard_message" product="default">No SD card was found.</string> - <!-- Description shown when importing vCard data. The argument is the name of a contact which is being read. [CHAR LIMIT=20] --> @@ -620,29 +615,6 @@ a ren't members of any other group. [CHAR LIMIT=25] --> <!-- Dialog title shown when a user confirms whether he/she export Contact data. [CHAR LIMIT=32] --> <string name="confirm_export_title">Export contacts?</string> - <!-- Dialog title shown when a user is asked to select vCard file. [CHAR LIMIT=25] --> - <string name="select_vcard_title">Choose vCard file</string> - - <!-- One of alternatives shown when the system allows a user to select how many vCard files - should be imported. This message shows only when the system is certain that there's more - than one vCard files available in the system. --> - <string name="import_one_vcard_string">Import one vCard file</string> - - <!-- One of alternatives shown when the system allows a user to select how many vCard files - should be imported. This message shows only when the system is certain that there's more - than one vCard files available in the system. --> - <string name="import_multiple_vcard_string">Import multiple vCard files</string> - - <!-- One of alternatives shown when the system allows a user to select how many vCard files - should be imported. This message shows only when the system is certain that there's more - than one vCard files available in the system. --> - <string name="import_all_vcard_string">Import all vCard files</string> - - <!-- Dialog message shown when searching VCard data from (USB) storage [CHAR LIMIT=NONE] --> - <string name="searching_vcard_message" product="nosdcard">Searching for vCard data in storage\u2026</string> - <!-- Dialog message shown when searching VCard data from SD Card. [CHAR LIMIT=NONE] --> - <string name="searching_vcard_message" product="default">Searching for vCard data on SD card\u2026</string> - <!-- The title shown when vCard importer is caching files to be imported into local temporary data storage. [CHAR LIMIT=40] --> <string name="caching_vcard_title">Caching</string> @@ -662,7 +634,7 @@ a ren't members of any other group. [CHAR LIMIT=25] --> <string name="progress_notifier_message">Importing <xliff:g id="current_number">%s</xliff:g>/<xliff:g id="total_number">%s</xliff:g>: <xliff:g id="name" example="Joe Due">%s</xliff:g></string> <!-- Action that exports all contacts to a user selected destination. [CHAR LIMIT=25] --> - <string name="export" product="default">Export</string> + <string name="export_to_vcf_file" product="default">Export to .vcf file</string> <!-- Contact preferences related strings --> diff --git a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java index acef8224..5e1daf43 100644 --- a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java +++ b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java @@ -117,9 +117,9 @@ public class ImportExportDialogFragment extends DialogFragment mSubscriptionManager = SubscriptionManager.from(getActivity()); - if (res.getBoolean(R.bool.config_allow_import_from_sdcard)) { - adapter.add(new AdapterEntry(getString(R.string.import_from_sdcard), - R.string.import_from_sdcard)); + if (res.getBoolean(R.bool.config_allow_import_from_vcf_file)) { + adapter.add(new AdapterEntry(getString(R.string.import_from_vcf_file), + R.string.import_from_vcf_file)); } if (manager != null && res.getBoolean(R.bool.config_allow_sim_import)) { final List<SubscriptionInfo> subInfoRecords = @@ -138,7 +138,8 @@ public class ImportExportDialogFragment extends DialogFragment } if (res.getBoolean(R.bool.config_allow_export)) { if (contactsAreAvailable) { - adapter.add(new AdapterEntry(getString(R.string.export), R.string.export)); + adapter.add(new AdapterEntry(getString(R.string.export_to_vcf_file), + R.string.export_to_vcf_file)); } } if (res.getBoolean(R.bool.config_allow_share_visible_contacts)) { @@ -156,12 +157,12 @@ public class ImportExportDialogFragment extends DialogFragment final int resId = adapter.getItem(which).mChoiceResourceId; switch (resId) { case R.string.import_from_sim: - case R.string.import_from_sdcard: { + case R.string.import_from_vcf_file: { dismissDialog = handleImportRequest(resId, adapter.getItem(which).mSubscriptionId); break; } - case R.string.export: { + case R.string.export_to_vcf_file: { dismissDialog = true; Intent exportIntent = new Intent(getActivity(), ExportVCardActivity.class); exportIntent.putExtra(VCardCommonArguments.ARG_CALLING_ACTIVITY, diff --git a/src/com/android/contacts/common/util/AccountSelectionUtil.java b/src/com/android/contacts/common/util/AccountSelectionUtil.java index 1ea92ed0..ccbc2046 100644 --- a/src/com/android/contacts/common/util/AccountSelectionUtil.java +++ b/src/com/android/contacts/common/util/AccountSelectionUtil.java @@ -166,8 +166,8 @@ public class AccountSelectionUtil { doImportFromSim(context, account, subscriptionId); break; } - case R.string.import_from_sdcard: { - doImportFromSdCard(context, account); + case R.string.import_from_vcf_file: { + doImportFromVcfFile(context, account); break; } } @@ -187,7 +187,7 @@ public class AccountSelectionUtil { context.startActivity(importIntent); } - public static void doImportFromSdCard(Context context, AccountWithDataSet account) { + public static void doImportFromVcfFile(Context context, AccountWithDataSet account) { Intent importIntent = new Intent(context, ImportVCardActivity.class); if (account != null) { importIntent.putExtra("account_name", account.name); diff --git a/src/com/android/contacts/common/vcard/ExportVCardActivity.java b/src/com/android/contacts/common/vcard/ExportVCardActivity.java index 9ee02fe2..1a1b5e82 100644 --- a/src/com/android/contacts/common/vcard/ExportVCardActivity.java +++ b/src/com/android/contacts/common/vcard/ExportVCardActivity.java @@ -26,22 +26,15 @@ import android.content.ServiceConnection; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; -import android.os.Handler; import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; import android.provider.OpenableColumns; import android.text.BidiFormatter; import android.text.TextDirectionHeuristics; -import android.text.TextUtils; import android.util.Log; import com.android.contacts.common.R; import com.android.contacts.common.activity.RequestImportVCardPermissionsActivity; -import java.io.File; - /** * Shows a dialog confirming the export and asks actual vCard export to {@link VCardService} * @@ -54,7 +47,6 @@ public class ExportVCardActivity extends Activity implements ServiceConnection, private static final String LOG_TAG = "VCardExport"; private static final boolean DEBUG = VCardService.DEBUG; private static final int REQUEST_CREATE_DOCUMENT = 100; - private static final String VCARD_MIME_TYPE = "text/vcard"; /** * True when this Activity is connected to {@link VCardService}. @@ -134,7 +126,7 @@ public class ExportVCardActivity extends Activity implements ServiceConnection, // Have the user choose where vcards will be exported to final Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType(VCARD_MIME_TYPE); + intent.setType(VCardService.VCARD_MIME_TYPE); intent.putExtra(Intent.EXTRA_TITLE, mBidiFormatter.unicodeWrap( getString(R.string.exporting_vcard_filename), TextDirectionHeuristics.LTR)); startActivityForResult(intent, REQUEST_CREATE_DOCUMENT); diff --git a/src/com/android/contacts/common/vcard/ImportVCardActivity.java b/src/com/android/contacts/common/vcard/ImportVCardActivity.java index 658e65af..79d51ad3 100644 --- a/src/com/android/contacts/common/vcard/ImportVCardActivity.java +++ b/src/com/android/contacts/common/vcard/ImportVCardActivity.java @@ -22,26 +22,21 @@ import android.app.Dialog; import android.app.Notification; import android.app.NotificationManager; import android.app.ProgressDialog; +import android.content.ClipData; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.ServiceConnection; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.provider.OpenableColumns; -import android.text.SpannableStringBuilder; -import android.text.Spanned; import android.text.TextUtils; -import android.text.style.RelativeSizeSpan; import android.util.Log; import android.widget.Toast; @@ -49,7 +44,6 @@ import com.android.contacts.common.R; import com.android.contacts.common.activity.RequestImportVCardPermissionsActivity; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.account.AccountWithDataSet; -import com.android.contacts.common.util.AccountSelectionUtil; import com.android.vcard.VCardEntryCounter; import com.android.vcard.VCardParser; import com.android.vcard.VCardParser_V21; @@ -67,15 +61,9 @@ import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import java.util.Vector; /** * The class letting users to import vCard. This includes the UI part for letting them select @@ -91,33 +79,21 @@ public class ImportVCardActivity extends Activity { private static final int SELECT_ACCOUNT = 0; - /* package */ static final String VCARD_URI_ARRAY = "vcard_uri"; - /* package */ static final String ESTIMATED_VCARD_TYPE_ARRAY = "estimated_vcard_type"; - /* package */ static final String ESTIMATED_CHARSET_ARRAY = "estimated_charset"; - /* package */ static final String VCARD_VERSION_ARRAY = "vcard_version"; - /* package */ static final String ENTRY_COUNT_ARRAY = "entry_count"; - /* package */ final static int VCARD_VERSION_AUTO_DETECT = 0; /* package */ final static int VCARD_VERSION_V21 = 1; /* package */ final static int VCARD_VERSION_V30 = 2; - private static final String SECURE_DIRECTORY_NAME = ".android_secure"; + private static final int REQUEST_OPEN_DOCUMENT = 100; /** * Notification id used when error happened before sending an import request to VCardServer. */ private static final int FAILURE_NOTIFICATION_ID = 1; - final static String CACHED_URIS = "cached_uris"; - private AccountWithDataSet mAccount; - private ProgressDialog mProgressDialogForScanVCard; private ProgressDialog mProgressDialogForCachingVCard; - private List<VCardFile> mAllVCardFileList; - private VCardScanThread mVCardScanThread; - private VCardCacheThread mVCardCacheThread; private ImportRequestConnection mConnection; /* package */ VCardImportExportListener mListener; @@ -126,30 +102,6 @@ public class ImportVCardActivity extends Activity { private Handler mHandler = new Handler(); - private static class VCardFile { - private final String mName; - private final String mCanonicalPath; - private final long mLastModified; - - public VCardFile(String name, String canonicalPath, long lastModified) { - mName = name; - mCanonicalPath = canonicalPath; - mLastModified = lastModified; - } - - public String getName() { - return mName; - } - - public String getCanonicalPath() { - return mCanonicalPath; - } - - public long getLastModified() { - return mLastModified; - } - } - // Runs on the UI thread. private class DialogDisplayer implements Runnable { private final int mResId; @@ -516,243 +468,10 @@ public class ImportVCardActivity extends Activity { } } - private class ImportTypeSelectedListener implements - DialogInterface.OnClickListener { - public static final int IMPORT_ONE = 0; - public static final int IMPORT_MULTIPLE = 1; - public static final int IMPORT_ALL = 2; - public static final int IMPORT_TYPE_SIZE = 3; - - private int mCurrentIndex; - - public void onClick(DialogInterface dialog, int which) { - if (which == DialogInterface.BUTTON_POSITIVE) { - switch (mCurrentIndex) { - case IMPORT_ALL: - importVCardFromSDCard(mAllVCardFileList); - break; - case IMPORT_MULTIPLE: - showDialog(R.id.dialog_select_multiple_vcard); - break; - default: - showDialog(R.id.dialog_select_one_vcard); - break; - } - } else if (which == DialogInterface.BUTTON_NEGATIVE) { - finish(); - } else { - mCurrentIndex = which; - } - } - } - - private class VCardSelectedListener implements - DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener { - private int mCurrentIndex; - private Set<Integer> mSelectedIndexSet; - - public VCardSelectedListener(boolean multipleSelect) { - mCurrentIndex = 0; - if (multipleSelect) { - mSelectedIndexSet = new HashSet<Integer>(); - } - } - - public void onClick(DialogInterface dialog, int which) { - if (which == DialogInterface.BUTTON_POSITIVE) { - if (mSelectedIndexSet != null) { - List<VCardFile> selectedVCardFileList = new ArrayList<VCardFile>(); - final int size = mAllVCardFileList.size(); - // We'd like to sort the files by its index, so we do not use Set iterator. - for (int i = 0; i < size; i++) { - if (mSelectedIndexSet.contains(i)) { - selectedVCardFileList.add(mAllVCardFileList.get(i)); - } - } - importVCardFromSDCard(selectedVCardFileList); - } else { - importVCardFromSDCard(mAllVCardFileList.get(mCurrentIndex)); - } - } else if (which == DialogInterface.BUTTON_NEGATIVE) { - finish(); - } else { - // Some file is selected. - mCurrentIndex = which; - if (mSelectedIndexSet != null) { - if (mSelectedIndexSet.contains(which)) { - mSelectedIndexSet.remove(which); - } else { - mSelectedIndexSet.add(which); - } - } - } - } - - public void onClick(DialogInterface dialog, int which, boolean isChecked) { - if (mSelectedIndexSet == null || (mSelectedIndexSet.contains(which) == isChecked)) { - Log.e(LOG_TAG, String.format("Inconsist state in index %d (%s)", which, - mAllVCardFileList.get(which).getCanonicalPath())); - } else { - onClick(dialog, which); - } - } - } - - /** - * Thread scanning VCard from SDCard. After scanning, the dialog which lets a user select - * a vCard file is shown. After the choice, VCardReadThread starts running. - */ - private class VCardScanThread extends Thread implements OnCancelListener, OnClickListener { - private boolean mCanceled; - private boolean mGotIOException; - private File mRootDirectory; - - // To avoid recursive link. - private Set<String> mCheckedPaths; - private PowerManager.WakeLock mWakeLock; - - private class CanceledException extends Exception { - } - - public VCardScanThread(File sdcardDirectory) { - mCanceled = false; - mGotIOException = false; - mRootDirectory = sdcardDirectory; - mCheckedPaths = new HashSet<String>(); - PowerManager powerManager = (PowerManager)ImportVCardActivity.this.getSystemService( - Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock( - PowerManager.SCREEN_DIM_WAKE_LOCK | - PowerManager.ON_AFTER_RELEASE, LOG_TAG); - } - - @Override - public void run() { - mAllVCardFileList = new Vector<VCardFile>(); - try { - mWakeLock.acquire(); - getVCardFileRecursively(mRootDirectory); - } catch (CanceledException e) { - mCanceled = true; - } catch (IOException e) { - mGotIOException = true; - } finally { - mWakeLock.release(); - } - - if (mCanceled) { - mAllVCardFileList = null; - } - - mProgressDialogForScanVCard.dismiss(); - mProgressDialogForScanVCard = null; - - if (mGotIOException) { - runOnUiThread(new DialogDisplayer(R.id.dialog_io_exception)); - } else if (mCanceled) { - finish(); - } else { - int size = mAllVCardFileList.size(); - final Context context = ImportVCardActivity.this; - if (size == 0) { - runOnUiThread(new DialogDisplayer(R.id.dialog_vcard_not_found)); - } else { - startVCardSelectAndImport(); - } - } - } - - private void getVCardFileRecursively(File directory) - throws CanceledException, IOException { - if (mCanceled) { - throw new CanceledException(); - } - - // e.g. secured directory may return null toward listFiles(). - final File[] files = directory.listFiles(); - if (files == null) { - final String currentDirectoryPath = directory.getCanonicalPath(); - final String secureDirectoryPath = - mRootDirectory.getCanonicalPath().concat(SECURE_DIRECTORY_NAME); - if (!TextUtils.equals(currentDirectoryPath, secureDirectoryPath)) { - Log.w(LOG_TAG, "listFiles() returned null (directory: " + directory + ")"); - } - return; - } - for (File file : directory.listFiles()) { - if (mCanceled) { - throw new CanceledException(); - } - String canonicalPath = file.getCanonicalPath(); - if (mCheckedPaths.contains(canonicalPath)) { - continue; - } - - mCheckedPaths.add(canonicalPath); - - if (file.isDirectory()) { - getVCardFileRecursively(file); - } else if (canonicalPath.toLowerCase().endsWith(".vcf") && - file.canRead()){ - String fileName = file.getName(); - VCardFile vcardFile = new VCardFile( - fileName, canonicalPath, file.lastModified()); - mAllVCardFileList.add(vcardFile); - } - } - } - - public void onCancel(DialogInterface dialog) { - mCanceled = true; - } - - public void onClick(DialogInterface dialog, int which) { - if (which == DialogInterface.BUTTON_NEGATIVE) { - mCanceled = true; - } - } - } - - private void startVCardSelectAndImport() { - int size = mAllVCardFileList.size(); - if (getResources().getBoolean(R.bool.config_import_all_vcard_from_sdcard_automatically) || - size == 1) { - importVCardFromSDCard(mAllVCardFileList); - } else if (getResources().getBoolean(R.bool.config_allow_users_select_all_vcard_import)) { - runOnUiThread(new DialogDisplayer(R.id.dialog_select_import_type)); - } else { - runOnUiThread(new DialogDisplayer(R.id.dialog_select_one_vcard)); - } - } - - private void importVCardFromSDCard(final List<VCardFile> selectedVCardFileList) { - final int size = selectedVCardFileList.size(); - String[] uriStrings = new String[size]; - int i = 0; - for (VCardFile vcardFile : selectedVCardFileList) { - uriStrings[i] = "file://" + vcardFile.getCanonicalPath(); - i++; - } - importVCard(uriStrings); - } - - private void importVCardFromSDCard(final VCardFile vcardFile) { - importVCard(new Uri[] {Uri.parse("file://" + vcardFile.getCanonicalPath())}); - } - private void importVCard(final Uri uri) { importVCard(new Uri[] {uri}); } - private void importVCard(final String[] uriStrings) { - final int length = uriStrings.length; - final Uri[] uris = new Uri[length]; - for (int i = 0; i < length; i++) { - uris[i] = Uri.parse(uriStrings[i]); - } - importVCard(uris); - } - private void importVCard(final Uri[] uris) { runOnUiThread(new Runnable() { @Override @@ -766,61 +485,6 @@ public class ImportVCardActivity extends Activity { }); } - private Dialog getSelectImportTypeDialog() { - final DialogInterface.OnClickListener listener = new ImportTypeSelectedListener(); - final AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setTitle(R.string.select_vcard_title) - .setPositiveButton(android.R.string.ok, listener) - .setOnCancelListener(mCancelListener) - .setNegativeButton(android.R.string.cancel, mCancelListener); - - final String[] items = new String[ImportTypeSelectedListener.IMPORT_TYPE_SIZE]; - items[ImportTypeSelectedListener.IMPORT_ONE] = - getString(R.string.import_one_vcard_string); - items[ImportTypeSelectedListener.IMPORT_MULTIPLE] = - getString(R.string.import_multiple_vcard_string); - items[ImportTypeSelectedListener.IMPORT_ALL] = - getString(R.string.import_all_vcard_string); - builder.setSingleChoiceItems(items, ImportTypeSelectedListener.IMPORT_ONE, listener); - return builder.create(); - } - - private Dialog getVCardFileSelectDialog(boolean multipleSelect) { - final int size = mAllVCardFileList.size(); - final VCardSelectedListener listener = new VCardSelectedListener(multipleSelect); - final AlertDialog.Builder builder = - new AlertDialog.Builder(this) - .setTitle(R.string.select_vcard_title) - .setPositiveButton(android.R.string.ok, listener) - .setOnCancelListener(mCancelListener) - .setNegativeButton(android.R.string.cancel, mCancelListener); - - CharSequence[] items = new CharSequence[size]; - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - for (int i = 0; i < size; i++) { - VCardFile vcardFile = mAllVCardFileList.get(i); - SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); - stringBuilder.append(vcardFile.getName()); - stringBuilder.append('\n'); - int indexToBeSpanned = stringBuilder.length(); - // Smaller date text looks better, since each file name becomes easier to read. - // The value set to RelativeSizeSpan is arbitrary. You can change it to any other - // value (but the value bigger than 1.0f would not make nice appearance :) - stringBuilder.append( - "(" + dateFormat.format(new Date(vcardFile.getLastModified())) + ")"); - stringBuilder.setSpan( - new RelativeSizeSpan(0.7f), indexToBeSpanned, stringBuilder.length(), - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - items[i] = stringBuilder; - } - if (multipleSelect) { - builder.setMultiChoiceItems(items, (boolean[])null, listener); - } else { - builder.setSingleChoiceItems(items, 0, listener); - } - return builder.create(); - } - @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); @@ -875,60 +539,64 @@ public class ImportVCardActivity extends Activity { } finish(); } + } else if (requestCode == REQUEST_OPEN_DOCUMENT) { + if (resultCode == Activity.RESULT_OK) { + final ClipData clipData = intent.getClipData(); + if (clipData != null) { + final ArrayList<Uri> uris = new ArrayList<>(); + for (int i = 0; i < clipData.getItemCount(); i++) { + ClipData.Item item = clipData.getItemAt(i); + final Uri uri = item.getUri(); + if (uri != null) { + uris.add(uri); + } + } + if (uris.isEmpty()) { + Log.w(LOG_TAG, "No vCard was selected for import"); + finish(); + } else { + Log.i(LOG_TAG, "Multiple vCards selected for import: " + uris); + importVCard(uris.toArray(new Uri[0])); + } + } else { + final Uri uri = intent.getData(); + if (uri != null) { + Log.i(LOG_TAG, "vCard selected for import: " + uri); + importVCard(uri); + } else { + Log.w(LOG_TAG, "No vCard was selected for import"); + finish(); + } + } + } else { + if (resultCode != Activity.RESULT_CANCELED) { + Log.w(LOG_TAG, "Result code was not OK nor CANCELED" + resultCode); + } + finish(); + } } } private void startImport() { - Intent intent = getIntent(); // Handle inbound files - Uri uri = intent.getData(); + Uri uri = getIntent().getData(); if (uri != null) { Log.i(LOG_TAG, "Starting vCard import using Uri " + uri); importVCard(uri); } else { Log.i(LOG_TAG, "Start vCard without Uri. The user will select vCard manually."); - doScanExternalStorageAndImportVCard(); + final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType(VCardService.VCARD_MIME_TYPE); + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); + startActivityForResult(intent, REQUEST_OPEN_DOCUMENT); } } @Override protected Dialog onCreateDialog(int resId, Bundle bundle) { switch (resId) { - case R.id.dialog_searching_vcard: { - if (mProgressDialogForScanVCard == null) { - String message = getString(R.string.searching_vcard_message); - mProgressDialogForScanVCard = - ProgressDialog.show(this, "", message, true, false); - mProgressDialogForScanVCard.setOnCancelListener(mVCardScanThread); - mVCardScanThread.start(); - } - return mProgressDialogForScanVCard; - } - case R.id.dialog_sdcard_not_found: { - AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setIconAttribute(android.R.attr.alertDialogIcon) - .setMessage(R.string.no_sdcard_message) - .setOnCancelListener(mCancelListener) - .setPositiveButton(android.R.string.ok, mCancelListener); - return builder.create(); - } - case R.id.dialog_vcard_not_found: { - final String message = getString(R.string.import_failure_no_vcard_file); - AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setMessage(message) - .setOnCancelListener(mCancelListener) - .setPositiveButton(android.R.string.ok, mCancelListener); - return builder.create(); - } - case R.id.dialog_select_import_type: { - return getSelectImportTypeDialog(); - } - case R.id.dialog_select_multiple_vcard: { - return getVCardFileSelectDialog(true); - } - case R.id.dialog_select_one_vcard: { - return getVCardFileSelectDialog(false); - } case R.id.dialog_cache_vcard: { if (mProgressDialogForCachingVCard == null) { final String title = getString(R.string.caching_vcard_title); @@ -942,16 +610,6 @@ public class ImportVCardActivity extends Activity { } return mProgressDialogForCachingVCard; } - case R.id.dialog_io_exception: { - String message = (getString(R.string.scanning_sdcard_failed_message, - getString(R.string.fail_reason_io_error))); - AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setIconAttribute(android.R.attr.alertDialogIcon) - .setMessage(message) - .setOnCancelListener(mCancelListener) - .setPositiveButton(android.R.string.ok, mCancelListener); - return builder.create(); - } case R.id.dialog_error_with_message: { String message = mErrorMessage; if (TextUtils.isEmpty(message)) { @@ -991,22 +649,6 @@ public class ImportVCardActivity extends Activity { } } - /** - * Scans vCard in external storage (typically SDCard) and tries to import it. - * - When there's no SDCard available, an error dialog is shown. - * - When multiple vCard files are available, asks a user to select one. - */ - private void doScanExternalStorageAndImportVCard() { - // TODO: should use getExternalStorageState(). - final File file = Environment.getExternalStorageDirectory(); - if (!file.exists() || !file.isDirectory() || !file.canRead()) { - showDialog(R.id.dialog_sdcard_not_found); - } else { - mVCardScanThread = new VCardScanThread(file); - showDialog(R.id.dialog_searching_vcard); - } - } - /* package */ void showFailureNotification(int reasonId) { final NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); diff --git a/src/com/android/contacts/common/vcard/SelectAccountActivity.java b/src/com/android/contacts/common/vcard/SelectAccountActivity.java index d05810db..66bfbca1 100644 --- a/src/com/android/contacts/common/vcard/SelectAccountActivity.java +++ b/src/com/android/contacts/common/vcard/SelectAccountActivity.java @@ -56,7 +56,7 @@ public class SelectAccountActivity extends Activity { // - more than one accounts -> ask the user // - just one account -> use the account without asking the user // - no account -> use phone-local storage without asking the user - final int resId = R.string.import_from_sdcard; + final int resId = R.string.import_from_vcf_file; final AccountTypeManager accountTypes = AccountTypeManager.getInstance(this); final List<AccountWithDataSet> accountList = accountTypes.getAccounts(true); if (accountList.size() == 0) { @@ -99,7 +99,7 @@ public class SelectAccountActivity extends Activity { @Override protected Dialog onCreateDialog(int resId, Bundle bundle) { switch (resId) { - case R.string.import_from_sdcard: { + case R.string.import_from_vcf_file: { if (mAccountSelectionListener == null) { throw new NullPointerException( "mAccountSelectionListener must not be null."); diff --git a/src/com/android/contacts/common/vcard/VCardService.java b/src/com/android/contacts/common/vcard/VCardService.java index b78c06f8..ddd3c1fe 100644 --- a/src/com/android/contacts/common/vcard/VCardService.java +++ b/src/com/android/contacts/common/vcard/VCardService.java @@ -66,6 +66,7 @@ public class VCardService extends Service { /* package */ static final String CACHE_FILE_PREFIX = "import_tmp_"; + /* package */ static final String VCARD_MIME_TYPE = "text/vcard"; private class CustomMediaScannerConnectionClient implements MediaScannerConnectionClient { final MediaScannerConnection mConnection; |