diff options
author | Jeff Hamilton <jham@android.com> | 2011-08-03 09:38:47 -0500 |
---|---|---|
committer | Jeff Hamilton <jham@android.com> | 2011-08-09 15:59:37 -0500 |
commit | 1167da421b68952a590b050c32def7e0eff7cca6 (patch) | |
tree | 9bc488fe65ebc8a41160a026891ee2a8d4fd23c1 /src/com/android/contacts/vcard/NotificationImportExportListener.java | |
parent | 3572293500a7406813e61e6fedd63ca606debc19 (diff) | |
download | android_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.java | 302 |
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(); + } +} |