summaryrefslogtreecommitdiffstats
path: root/src/com/android/contacts/vcard/NotificationImportExportListener.java
diff options
context:
space:
mode:
authorJeff Hamilton <jham@android.com>2011-08-03 09:38:47 -0500
committerJeff Hamilton <jham@android.com>2011-08-09 15:59:37 -0500
commit1167da421b68952a590b050c32def7e0eff7cca6 (patch)
tree9bc488fe65ebc8a41160a026891ee2a8d4fd23c1 /src/com/android/contacts/vcard/NotificationImportExportListener.java
parent3572293500a7406813e61e6fedd63ca606debc19 (diff)
downloadandroid_packages_apps_Contacts-1167da421b68952a590b050c32def7e0eff7cca6.tar.gz
android_packages_apps_Contacts-1167da421b68952a590b050c32def7e0eff7cca6.tar.bz2
android_packages_apps_Contacts-1167da421b68952a590b050c32def7e0eff7cca6.zip
Move the notification logic out to a listener
so there can be an Activity based version of the listener as well for NFC VCARD imports. Removed the now unused showImmediatley from ImportRequest. Change-Id: I37292676239444516bcc11486fc53e69b869dfa6
Diffstat (limited to 'src/com/android/contacts/vcard/NotificationImportExportListener.java')
-rw-r--r--src/com/android/contacts/vcard/NotificationImportExportListener.java302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/com/android/contacts/vcard/NotificationImportExportListener.java b/src/com/android/contacts/vcard/NotificationImportExportListener.java
new file mode 100644
index 000000000..fb83cec1c
--- /dev/null
+++ b/src/com/android/contacts/vcard/NotificationImportExportListener.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.contacts.vcard;
+
+import com.android.contacts.R;
+import com.android.vcard.VCardEntry;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.ContactsContract.RawContacts;
+import android.widget.RemoteViews;
+import android.widget.Toast;
+
+public class NotificationImportExportListener implements VCardImportExportListener,
+ Handler.Callback {
+ /** The tag used by vCard-related notifications. */
+ /* package */ static final String DEFAULT_NOTIFICATION_TAG = "VCardServiceProgress";
+ /**
+ * The tag used by vCard-related failure notifications.
+ * <p>
+ * Use a different tag from {@link #DEFAULT_NOTIFICATION_TAG} so that failures do not get
+ * replaced by other notifications and vice-versa.
+ */
+ /* package */ static final String FAILURE_NOTIFICATION_TAG = "VCardServiceFailure";
+
+ private final NotificationManager mNotificationManager;
+ private final Activity mContext;
+ private final Handler mHandler;
+
+ public NotificationImportExportListener(Activity activity) {
+ mContext = activity;
+ mNotificationManager = (NotificationManager) activity.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ mHandler = new Handler(this);
+ }
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ String text = (String) msg.obj;
+ Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
+ return true;
+ }
+
+ @Override
+ public void onImportProcessed(ImportRequest request, int jobId, int sequence) {
+ // Show a notification about the status
+ final String displayName;
+ final String message;
+ if (request.displayName != null) {
+ displayName = request.displayName;
+ message = mContext.getString(R.string.vcard_import_will_start_message, displayName);
+ } else {
+ displayName = mContext.getString(R.string.vcard_unknown_filename);
+ message = mContext.getString(
+ R.string.vcard_import_will_start_message_with_default_name);
+ }
+
+ // We just want to show notification for the first vCard.
+ if (sequence == 0) {
+ // TODO: Ideally we should detect the current status of import/export and
+ // show "started" when we can import right now and show "will start" when
+ // we cannot.
+ mHandler.obtainMessage(0, message).sendToTarget();
+ }
+
+ final Notification notification = constructProgressNotification(mContext,
+ VCardService.TYPE_IMPORT, message, message, jobId, displayName, -1, 0);
+ mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
+ }
+
+ @Override
+ public void onImportParsed(ImportRequest request, int jobId, VCardEntry entry, int currentCount,
+ int totalCount) {
+ if (entry.isIgnorable()) {
+ return;
+ }
+
+ final String totalCountString = String.valueOf(totalCount);
+ final String tickerText =
+ mContext.getString(R.string.progress_notifier_message,
+ String.valueOf(currentCount),
+ totalCountString,
+ entry.getDisplayName());
+ final String description = mContext.getString(R.string.importing_vcard_description,
+ entry.getDisplayName());
+
+ final Notification notification = constructProgressNotification(
+ mContext.getApplicationContext(), VCardService.TYPE_IMPORT, description, tickerText,
+ jobId, request.displayName, totalCount, currentCount);
+ mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
+ }
+
+ @Override
+ public void onImportFinished(ImportRequest request, int jobId, Uri createdUri) {
+ final String description = mContext.getString(R.string.importing_vcard_finished_title,
+ request.displayName);
+ final Intent intent;
+ if (createdUri != null) {
+ final long rawContactId = ContentUris.parseId(createdUri);
+ final Uri contactUri = RawContacts.getContactLookupUri(
+ mContext.getContentResolver(), ContentUris.withAppendedId(
+ RawContacts.CONTENT_URI, rawContactId));
+ intent = new Intent(Intent.ACTION_VIEW, contactUri);
+ } else {
+ intent = null;
+ }
+ final Notification notification =
+ NotificationImportExportListener.constructFinishNotification(mContext,
+ description, null, intent);
+ mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
+ jobId, notification);
+ }
+
+ @Override
+ public void onImportFailed(ImportRequest request) {
+ // TODO: a little unkind to show Toast in this case, which is shown just a moment.
+ // Ideally we should show some persistent something users can notice more easily.
+ mHandler.obtainMessage(0,
+ mContext.getString(R.string.vcard_import_request_rejected_message)).sendToTarget();
+ }
+
+ @Override
+ public void onImportCanceled(ImportRequest request, int jobId) {
+ final String description = mContext.getString(R.string.importing_vcard_canceled_title,
+ request.displayName);
+ final Notification notification =
+ NotificationImportExportListener.constructCancelNotification(mContext, description);
+ mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
+ jobId, notification);
+ }
+
+ @Override
+ public void onExportProcessed(ExportRequest request, int jobId) {
+ final String displayName = request.destUri.getLastPathSegment();
+ final String message = mContext.getString(R.string.vcard_export_will_start_message,
+ displayName);
+
+ mHandler.obtainMessage(0, message).sendToTarget();
+ final Notification notification =
+ NotificationImportExportListener.constructProgressNotification(mContext,
+ VCardService.TYPE_EXPORT, message, message, jobId, displayName, -1, 0);
+ mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
+ }
+
+ @Override
+ public void onExportFailed(ExportRequest request) {
+ mHandler.obtainMessage(0,
+ mContext.getString(R.string.vcard_export_request_rejected_message)).sendToTarget();
+ }
+
+ @Override
+ public void onCancelRequest(CancelRequest request, int type) {
+ final String description = type == VCardService.TYPE_IMPORT ?
+ mContext.getString(R.string.importing_vcard_canceled_title, request.displayName) :
+ mContext.getString(R.string.exporting_vcard_canceled_title, request.displayName);
+ final Notification notification = constructCancelNotification(mContext, description);
+ mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, request.jobId, notification);
+ }
+
+ /**
+ * Constructs a {@link Notification} showing the current status of import/export.
+ * Users can cancel the process with the Notification.
+ *
+ * @param context
+ * @param type import/export
+ * @param description Content of the Notification.
+ * @param tickerText
+ * @param jobId
+ * @param displayName Name to be shown to the Notification (e.g. "finished importing XXXX").
+ * Typycally a file name.
+ * @param totalCount The number of vCard entries to be imported. Used to show progress bar.
+ * -1 lets the system show the progress bar with "indeterminate" state.
+ * @param currentCount The index of current vCard. Used to show progress bar.
+ */
+ /* package */ static Notification constructProgressNotification(
+ Context context, int type, String description, String tickerText,
+ int jobId, String displayName, int totalCount, int currentCount) {
+ final RemoteViews remoteViews =
+ new RemoteViews(context.getPackageName(),
+ R.layout.status_bar_ongoing_event_progress_bar);
+ remoteViews.setTextViewText(R.id.status_description, description);
+ remoteViews.setProgressBar(R.id.status_progress_bar, totalCount, currentCount,
+ totalCount == -1);
+ final String percentage;
+ if (totalCount > 0) {
+ percentage = context.getString(R.string.percentage,
+ String.valueOf(currentCount * 100/totalCount));
+ } else {
+ percentage = "";
+ }
+ remoteViews.setTextViewText(R.id.status_progress_text, percentage);
+ final int icon = (type == VCardService.TYPE_IMPORT ? android.R.drawable.stat_sys_download :
+ android.R.drawable.stat_sys_upload);
+ remoteViews.setImageViewResource(R.id.status_icon, icon);
+
+ final Notification notification = new Notification();
+ notification.icon = icon;
+ notification.tickerText = tickerText;
+ notification.contentView = remoteViews;
+ notification.flags |= Notification.FLAG_ONGOING_EVENT;
+
+ // Note: We cannot use extra values here (like setIntExtra()), as PendingIntent doesn't
+ // preserve them across multiple Notifications. PendingIntent preserves the first extras
+ // (when flag is not set), or update them when PendingIntent#getActivity() is called
+ // (See PendingIntent#FLAG_UPDATE_CURRENT). In either case, we cannot preserve extras as we
+ // expect (for each vCard import/export request).
+ //
+ // We use query parameter in Uri instead.
+ // Scheme and Authority is arbitorary, assuming CancelActivity never refers them.
+ final Intent intent = new Intent(context, CancelActivity.class);
+ final Uri uri = (new Uri.Builder())
+ .scheme("invalidscheme")
+ .authority("invalidauthority")
+ .appendQueryParameter(CancelActivity.JOB_ID, String.valueOf(jobId))
+ .appendQueryParameter(CancelActivity.DISPLAY_NAME, displayName)
+ .appendQueryParameter(CancelActivity.TYPE, String.valueOf(type)).build();
+ intent.setData(uri);
+
+ notification.contentIntent = PendingIntent.getActivity(context, 0, intent, 0);
+ return notification;
+ }
+
+ /**
+ * Constructs a Notification telling users the process is canceled.
+ *
+ * @param context
+ * @param description Content of the Notification
+ */
+ /* package */ static Notification constructCancelNotification(
+ Context context, String description) {
+ return new Notification.Builder(context)
+ .setAutoCancel(true)
+ .setSmallIcon(android.R.drawable.stat_notify_error)
+ .setContentTitle(description)
+ .setContentText(description)
+ .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0))
+ .getNotification();
+ }
+
+ /**
+ * Constructs a Notification telling users the process is finished.
+ *
+ * @param context
+ * @param description Content of the Notification
+ * @param intent Intent to be launched when the Notification is clicked. Can be null.
+ */
+ /* package */ static Notification constructFinishNotification(
+ Context context, String title, String description, Intent intent) {
+ return new Notification.Builder(context)
+ .setAutoCancel(true)
+ .setSmallIcon(android.R.drawable.stat_sys_download_done)
+ .setContentTitle(title)
+ .setContentText(description)
+ .setContentIntent(PendingIntent.getActivity(context, 0,
+ (intent != null ? intent : new Intent()), 0))
+ .getNotification();
+ }
+
+ /**
+ * 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();
+ }
+
+ @Override
+ public void onComplete() {
+ mContext.finish();
+ }
+}