Let ImportVCardActivity choose an account if multiple account exist.
Remove VCardActivity, which does nothing effective.
Remove getReopenableUri(), since this change the method unnecessary.
Bug: 2528512
Bug: 2568427
Change-Id: I1ffb4171fefaad1ddc7406fe5447876d4c647610
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1e9b525..04d0cf4 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -448,9 +448,9 @@
</intent-filter>
</activity>
- <activity android:name=".VCardActivity"
- android:theme="@android:style/Theme.NoTitleBar" >
- <intent-filter>
+ <activity android:name=".ImportVCardActivity"
+ android:theme="@style/BackgroundOnly">
+ <intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:mimeType="text/directory" />
<data android:mimeType="text/x-vcard" />
@@ -458,9 +458,6 @@
</intent-filter>
</activity>
- <activity android:name=".ImportVCardActivity"
- android:theme="@style/BackgroundOnly" />
-
<activity android:name=".ExportVCardActivity"
android:theme="@style/BackgroundOnly" />
</application>
diff --git a/src/com/android/contacts/ImportVCardActivity.java b/src/com/android/contacts/ImportVCardActivity.java
index 4dcf5d5..adc2f67 100644
--- a/src/com/android/contacts/ImportVCardActivity.java
+++ b/src/com/android/contacts/ImportVCardActivity.java
@@ -31,7 +31,6 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
-import android.os.FileUtils;
import android.os.Handler;
import android.os.PowerManager;
import android.pim.vcard.VCardConfig;
@@ -54,12 +53,12 @@
import android.text.style.RelativeSizeSpan;
import android.util.Log;
-import java.io.BufferedOutputStream;
+import com.android.contacts.model.Sources;
+import com.android.contacts.util.AccountSelectionUtil;
+
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -109,6 +108,8 @@
private static final boolean DO_PERFORMANCE_PROFILE = false;
private Handler mHandler = new Handler(); // Run on the UI thread.
+
+ private AccountSelectionUtil.AccountSelectedListener mAccountSelectionListener;
private Account mAccount;
private ProgressDialog mProgressDialogForScanVCard;
@@ -201,12 +202,7 @@
// Even in such cases, some should be done.
try {
if (mUri != null) { // Read one vCard expressed by mUri
- final Uri uri = getReopenableUri(mUri);
- if (uri == null) {
- shouldCallFinish = false;
- return;
- }
-
+ final Uri targetUri = mUri;
mProgressDialogForReadVCard.setProgressNumberFormat("");
mProgressDialogForReadVCard.setProgress(0);
@@ -222,13 +218,13 @@
Arrays.asList(counter, detector));
boolean result;
try {
- result = readOneVCardFile(uri,
+ result = readOneVCardFile(targetUri,
VCardConfig.DEFAULT_CHARSET, builderCollection, null, true, null);
} catch (VCardNestedException e) {
try {
// Assume that VCardSourceDetector was able to detect the source.
// Try again with the detector.
- result = readOneVCardFile(uri,
+ result = readOneVCardFile(targetUri,
VCardConfig.DEFAULT_CHARSET, counter, detector, false, null);
} catch (VCardNestedException e2) {
result = false;
@@ -250,7 +246,7 @@
mProgressDialogForReadVCard.setIndeterminate(false);
mProgressDialogForReadVCard.setMax(counter.getCount());
String charset = detector.getEstimatedCharset();
- createdUri = doActuallyReadOneVCard(uri, null, charset, true, detector,
+ createdUri = doActuallyReadOneVCard(targetUri, null, charset, true, detector,
mErrorFileNameList);
} else { // Read multiple files.
mProgressDialogForReadVCard.setProgressNumberFormat(
@@ -263,16 +259,12 @@
return;
}
// TODO: detect scheme!
- final Uri uri = getReopenableUri(
- Uri.parse("file://" + vcardFile.getCanonicalPath()));
- if (uri == null) {
- shouldCallFinish = false;
- return;
- }
+ final Uri targetUri =
+ Uri.parse("file://" + vcardFile.getCanonicalPath());
VCardSourceDetector detector = new VCardSourceDetector();
try {
- if (!readOneVCardFile(uri, VCardConfig.DEFAULT_CHARSET,
+ if (!readOneVCardFile(targetUri, VCardConfig.DEFAULT_CHARSET,
detector, null, true, mErrorFileNameList)) {
continue;
}
@@ -280,7 +272,7 @@
// Assume that VCardSourceDetector was able to detect the source.
}
String charset = detector.getEstimatedCharset();
- doActuallyReadOneVCard(uri, mAccount,
+ doActuallyReadOneVCard(targetUri, mAccount,
charset, false, detector, mErrorFileNameList);
mProgressDialogForReadVCard.incrementProgressBy(1);
}
@@ -333,49 +325,6 @@
}
}
- private Uri getReopenableUri(final Uri uri) {
- if ("file".equals(uri.getScheme())) {
- return uri;
- } else {
- // We may not be able to scan a given uri more than once when it does not
- // point to a local file, while it is necessary to scan it more than once
- // because of vCard limitation. We rely on a local temporary file instead.
- //
- // e.g. Email app's AttachmentProvider is able to give us a content Uri
- // with an attachment file, but we cannot "sometimes" (not always) scan
- // the Uri more than once because of permission revocation.
- InputStream is = null;
- OutputStream os = null;
- Uri reopenableUri = null;
- try {
- is = mResolver.openInputStream(uri);
- File dir = getDir("tmp", MODE_PRIVATE);
- mTempFile = dir.createTempFile("vcf", null, dir);
- FileUtils.copyToFile(is, mTempFile);
- reopenableUri = Uri.parse("file://" + mTempFile.getCanonicalPath());
- } catch (IOException e) {
- mHandler.post(new DialogDisplayer(
- getString(R.string.fail_reason_io_error) +
- ": " + e.getLocalizedMessage()));
- return null;
- } finally {
- if (is != null) {
- try {
- is.close();
- } catch (IOException e) {
- }
- }
- if (os != null) {
- try {
- os.close();
- } catch (IOException e) {
- }
- }
- }
- return reopenableUri;
- }
- }
-
private Uri doActuallyReadOneVCard(Uri uri, Account account,
String charset, boolean showEntryParseProgress,
VCardSourceDetector detector, List<String> errorFileNameList) {
@@ -783,7 +732,7 @@
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
- Intent intent = getIntent();
+ final Intent intent = getIntent();
if (intent != null) {
final String accountName = intent.getStringExtra("account_name");
final String accountType = intent.getStringExtra("account_type");
@@ -794,6 +743,41 @@
Log.e(LOG_TAG, "intent does not exist");
}
+ // The caller often does not know account information at all, so we show the UI instead.
+ if (mAccount == null) {
+ // There's three possibilities:
+ // - 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 Sources sources = Sources.getInstance(this);
+ final List<Account> accountList = sources.getAccounts(true);
+ final int size = accountList.size();
+ if (size > 1) {
+ final int resId = R.string.import_from_sdcard;
+ mAccountSelectionListener =
+ new AccountSelectionUtil.AccountSelectedListener(
+ this, accountList, resId) {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ mAccount = mAccountList.get(which);
+ // Instead of using Intent mechanism, call the relevant private method,
+ // to avoid throwing an Intent to itself again.
+ startImport();
+ }
+ };
+ showDialog(resId);
+ return;
+ } else {
+ mAccount = size > 0 ? accountList.get(0) : null;
+ }
+ }
+
+ startImport();
+ }
+
+ private void startImport() {
+ Intent intent = getIntent();
final String action = intent.getAction();
final Uri uri = intent.getData();
Log.v(LOG_TAG, "action = " + action + " ; path = " + uri);
@@ -805,13 +789,21 @@
if (uri != null) {
importOneVCardFromSDCard(uri);
} else {
- startImportVCardFromSdCard();
+ doScanExternalStorageAndImportVCard();
}
}
@Override
protected Dialog onCreateDialog(int resId) {
switch (resId) {
+ case R.string.import_from_sdcard: {
+ if (mAccountSelectionListener == null) {
+ throw new NullPointerException(
+ "mAccountSelectionListener must not be null.");
+ }
+ return AccountSelectionUtil.getSelectAccountDialog(this, resId,
+ mAccountSelectionListener);
+ }
case R.id.dialog_searching_vcard: {
if (mProgressDialogForScanVCard == null) {
String title = getString(R.string.searching_vcard_title);
@@ -938,15 +930,12 @@
}
}
- /* public methods */
-
/**
- * Tries to start importing VCard. If there's no SDCard available,
- * an error dialog is shown. If there is, start scanning using another thread
- * and shows a progress dialog. Several interactions will occur.
- * This method should be called from a thread with a looper (like 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.
*/
- public void startImportVCardFromSdCard() {
+ private void doScanExternalStorageAndImportVCard() {
// TODO: should use getExternalStorageState().
final File file = Environment.getExternalStorageDirectory();
if (!file.exists() || !file.isDirectory() || !file.canRead()) {
diff --git a/src/com/android/contacts/VCardActivity.java b/src/com/android/contacts/VCardActivity.java
deleted file mode 100644
index ef04be6..0000000
--- a/src/com/android/contacts/VCardActivity.java
+++ /dev/null
@@ -1,62 +0,0 @@
-//package com.motorola.vcardshare;
-
-package com.android.contacts;
-
-import java.util.List;
-import com.android.contacts.model.Sources;
-import com.android.contacts.util.AccountSelectionUtil;
-import android.accounts.Account;
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Log;
-
-public class VCardActivity extends Activity {
- private static final String TAG = "VCardActivity";
- public static final int IMPORT_TYPE_GOOGLE = 0;
- public static final int IMPORT_TYPE_EXCHANGE = 1;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.vcardshare_main);
-
- Intent intent = getIntent();
- String action = intent.getAction();
- Log.v(TAG, "action is " + action);
- Uri path = intent.getData();
- Log.v(TAG, "path is " + path);
- String mimeType = intent.getType();
- Log.v(TAG, "mimeType is " + mimeType);
-
- if (action.equals(Intent.ACTION_VIEW)) {
-
- AccountSelectionUtil.mVCardShare = true;
- AccountSelectionUtil.mPath = path;
- handleImportRequest(R.string.import_from_sdcard);
- } else {
- Log.w(TAG, "VcardActivity not handle such action: " + action);
- }
- finish();
- }
-
- private void handleImportRequest(int resId) {
- // There's three possibilities:
- // - 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 Sources sources = Sources.getInstance(this);
- final List<Account> accountList = sources.getAccounts(true);
- final int size = accountList.size();
- Log.v(TAG, "account num = " + size);
-
- if (size > 1) {
- // showDialog(resId);
- AccountSelectionUtil.getSelectAccountDialog(this, resId);
- }
-
- AccountSelectionUtil.doImport(this, resId, (size == 1 ? accountList.get(0) : null));
- }
-}
diff --git a/src/com/android/contacts/util/AccountSelectionUtil.java b/src/com/android/contacts/util/AccountSelectionUtil.java
index e32ef69..3618fad 100644
--- a/src/com/android/contacts/util/AccountSelectionUtil.java
+++ b/src/com/android/contacts/util/AccountSelectionUtil.java
@@ -50,13 +50,14 @@
public static Uri mPath;
- private static class AccountSelectedListener
- implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
+ public static class AccountSelectedListener
+ implements DialogInterface.OnClickListener {
final private Context mContext;
- final private List<Account> mAccountList;
final private int mResId;
+ final protected List<Account> mAccountList;
+
public AccountSelectedListener(Context context, List<Account> accountList, int resId) {
if (accountList == null || accountList.size() == 0) {
Log.e(LOG_TAG, "The size of Account list is 0.");
@@ -70,17 +71,19 @@
dialog.dismiss();
doImport(mContext, mResId, mAccountList.get(which));
}
-
- public void onCancel(DialogInterface dialog) {
- dialog.dismiss();
- }
}
public static Dialog getSelectAccountDialog(Context context, int resId) {
- return getSelectAccountDialog(context, resId, null);
+ return getSelectAccountDialog(context, resId, null, null);
}
public static Dialog getSelectAccountDialog(Context context, int resId,
+ DialogInterface.OnClickListener onClickListener) {
+ return getSelectAccountDialog(context, resId, onClickListener, null);
+ }
+
+ public static Dialog getSelectAccountDialog(Context context, int resId,
+ DialogInterface.OnClickListener onClickListener,
DialogInterface.OnCancelListener onCancelListener) {
final Sources sources = Sources.getInstance(context);
final List<Account> writableAccountList = sources.getAccounts(true);
@@ -123,12 +126,22 @@
}
};
- AccountSelectedListener accountSelectedListener =
- new AccountSelectedListener(context, writableAccountList, resId);
+ if (onClickListener == null) {
+ AccountSelectedListener accountSelectedListener =
+ new AccountSelectedListener(context, writableAccountList, resId);
+ onClickListener = accountSelectedListener;
+ }
+ if (onCancelListener == null) {
+ onCancelListener = new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ dialog.dismiss();
+ }
+ };
+ }
return new AlertDialog.Builder(context)
.setTitle(R.string.dialog_new_contact_account)
- .setSingleChoiceItems(accountAdapter, 0, accountSelectedListener)
- .setOnCancelListener(accountSelectedListener)
+ .setSingleChoiceItems(accountAdapter, 0, onClickListener)
+ .setOnCancelListener(onCancelListener)
.create();
}