Merge "Show Notification when parsing vCard failed." into honeycomb
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 95dad37..b0dffca 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -745,11 +745,12 @@
we believe it is rather rare in the actual world. -->
<string name="fail_reason_vcard_parse_error">Failed to parse vCard for unexpected reason</string>
- <!-- The failed reason shown when the current vCard importer cannot parse the file since the
- parser is incomplete (actually, there's missing part in the current vCard parser, though
- our understanding is that the functionality missed by the current vCard parser
- is rarely needed in the actual vCard...). -->
- <string name="fail_reason_vcard_not_supported_error">Failed to parse vCard though it seems in valid format, since the current implementation does not support it</string>
+ <!-- The failed reason shown when vCard importer doesn't support the format.
+ This may be shown when the vCard is corrupted [CHAR LIMIT=40] -->
+ <string name="fail_reason_not_supported">The format is not supported.</string>
+
+ <!-- Message used when vCard import has failed. [CHAR LIMIT=40] -->
+ <string name="vcard_import_failed">Failed to import vCard</string>
<!-- The failure message shown when the system could not find any vCard file.
(with extension ".vcf" in USB storage.)
diff --git a/src/com/android/contacts/vcard/ImportVCardActivity.java b/src/com/android/contacts/vcard/ImportVCardActivity.java
index 71bd376..8cda708 100644
--- a/src/com/android/contacts/vcard/ImportVCardActivity.java
+++ b/src/com/android/contacts/vcard/ImportVCardActivity.java
@@ -34,6 +34,8 @@
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -47,6 +49,7 @@
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;
@@ -57,6 +60,7 @@
import android.text.TextUtils;
import android.text.style.RelativeSizeSpan;
import android.util.Log;
+import android.widget.Toast;
import java.io.File;
import java.io.IOException;
@@ -101,6 +105,11 @@
private static final String SECURE_DIRECTORY_NAME = ".android_secure";
+ /**
+ * Notification id used when error happened before sending an import request to VCardServer.
+ */
+ private static final int DEFAULT_NOTIFICATION_ID = 1000;
+
final static String CACHED_URIS = "cached_uris";
private AccountSelectionUtil.AccountSelectedListener mAccountSelectionListener;
@@ -121,6 +130,8 @@
private String mErrorMessage;
+ private Handler mHandler = new Handler();
+
private static class VCardFile {
private final String mName;
private final String mCanonicalPath;
@@ -155,6 +166,7 @@
mResId = R.id.dialog_error_with_message;
mErrorMessage = errorMessage;
}
+ @Override
public void run() {
showDialog(mResId);
}
@@ -162,10 +174,11 @@
private class CancelListener
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
+ @Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
-
+ @Override
public void onCancel(DialogInterface dialog) {
finish();
}
@@ -285,8 +298,18 @@
Log.w(LOG_TAG, "destUri is null");
break;
}
- final ImportRequest parameter = constructImportRequest(
- localDataUri, sourceUri);
+ final ImportRequest parameter;
+ try {
+ parameter = constructImportRequest(localDataUri, sourceUri);
+ } catch (VCardException e) {
+ Log.e(LOG_TAG, "Maybe the file is in wrong format", e);
+ showFailureNotification(R.string.fail_reason_not_supported);
+ return;
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Unexpected IOException", e);
+ showFailureNotification(R.string.fail_reason_io_error);
+ return;
+ }
if (mCanceled) {
Log.i(LOG_TAG, "vCard cache operation is canceled.");
return;
@@ -371,7 +394,8 @@
* information. This variable populates {@link ImportRequest#originalUri}.
*/
private ImportRequest constructImportRequest(
- final Uri localDataUri, final Uri originalUri) {
+ final Uri localDataUri, final Uri originalUri)
+ throws IOException, VCardException {
final ContentResolver resolver = ImportVCardActivity.this.getContentResolver();
VCardEntryCounter counter = null;
VCardSourceDetector detector = null;
@@ -417,13 +441,8 @@
vcardVersion = shouldUseV30 ? VCARD_VERSION_V30 : VCARD_VERSION_V21;
} catch (VCardNestedException e) {
Log.w(LOG_TAG, "Nested Exception is found (it may be false-positive).");
- // Go through without returning null.
- } catch (VCardException e) {
- Log.e(LOG_TAG, "VCardException during constructing ImportRequest", e);
- return null;
- } catch (IOException e) {
- Log.e(LOG_TAG, "IOException during constructing ImportRequest", e);
- return null;
+ // Go through without throwing the Exception, as we may be able to detect the
+ // version before it
}
return new ImportRequest(mAccount,
localDataUri, originalUri,
@@ -943,4 +962,21 @@
showDialog(R.id.dialog_searching_vcard);
}
}
+
+ private void showFailureNotification(int reasonId) {
+ final NotificationManager notificationManager =
+ (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
+ final Notification notification =
+ VCardService.constructImportFailureNotification(
+ ImportVCardActivity.this,
+ getString(reasonId));
+ notificationManager.notify(DEFAULT_NOTIFICATION_ID, notification);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(ImportVCardActivity.this,
+ getString(R.string.vcard_import_failed), Toast.LENGTH_LONG).show();
+ }
+ });
+ }
}
diff --git a/src/com/android/contacts/vcard/VCardService.java b/src/com/android/contacts/vcard/VCardService.java
index efa93d4..13d938c 100644
--- a/src/com/android/contacts/vcard/VCardService.java
+++ b/src/com/android/contacts/vcard/VCardService.java
@@ -491,6 +491,23 @@
}
/**
+ * Constructs a Notification telling the vCard import has failed.
+ *
+ * @param context
+ * @param reason The reason why the import has failed. Shown in description field.
+ */
+ /* package */ static Notification constructImportFailureNotification(
+ Context context, String reason) {
+ return new Notification.Builder(context)
+ .setAutoCancel(true)
+ .setSmallIcon(android.R.drawable.stat_notify_error)
+ .setContentTitle(context.getString(R.string.vcard_import_failed))
+ .setContentText(reason)
+ .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0))
+ .getNotification();
+ }
+
+ /**
* Returns an appropriate file name for vCard export. Returns null when impossible.
*
* @return destination path for a vCard file to be exported. null on error and mErrorReason