勤能补拙,熟能生巧,宁静致远

记录工作中的点滴积累,总结成长的步伐里程。

博客园 首页 新随笔 联系 订阅 管理

导入/导出联系人过程,notification创建都是在com.android.contacts.common.vcard.NotificationImportExportListener中。

  1 /*
  2  * Copyright (C) 2011 The Android Open Source Project
  3  *
  4  * Licensed under the Apache License, Version 2.0 (the "License");
  5  * you may not use this file except in compliance with the License.
  6  * You may obtain a copy of the License at
  7  *
  8  *        http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License
 15  */
 16 
 17 package com.android.contacts.common.vcard;
 18 
 19 import android.app.Activity;
 20 import android.app.Notification;
 21 import android.app.NotificationManager;
 22 import android.app.PendingIntent;
 23 import android.content.ContentUris;
 24 import android.content.Context;
 25 import android.content.Intent;
 26 import android.net.Uri;
 27 import android.os.Handler;
 28 import android.os.Message;
 29 import android.provider.ContactsContract.RawContacts;
 30 import android.widget.Toast;
 31 
 32 import com.android.contacts.common.R;
 33 import com.android.vcard.VCardEntry;
 34 
 35 public class NotificationImportExportListener implements VCardImportExportListener,
 36         Handler.Callback {
 37     /** The tag used by vCard-related notifications. */
 38     /* package */ static final String DEFAULT_NOTIFICATION_TAG = "VCardServiceProgress";
 39     /**
 40      * The tag used by vCard-related failure notifications.
 41      * <p>
 42      * Use a different tag from {@link #DEFAULT_NOTIFICATION_TAG} so that failures do not get
 43      * replaced by other notifications and vice-versa.
 44      */
 45     /* package */ static final String FAILURE_NOTIFICATION_TAG = "VCardServiceFailure";
 46 
 47     private final NotificationManager mNotificationManager;
 48     private final Activity mContext;
 49     private final Handler mHandler;
 50 
 51     public NotificationImportExportListener(Activity activity) {
 52         mContext = activity;
 53         mNotificationManager = (NotificationManager) activity.getSystemService(
 54                 Context.NOTIFICATION_SERVICE);
 55         mHandler = new Handler(this);
 56     }
 57 
 58     @Override
 59     public boolean handleMessage(Message msg) {
 60         String text = (String) msg.obj;
 61         Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
 62         return true;
 63     }
 64 
 65     @Override
 66     public void onImportProcessed(ImportRequest request, int jobId, int sequence) {
 67         // Show a notification about the status
 68         final String displayName;
 69         final String message;
 70         if (request.displayName != null) {
 71             displayName = request.displayName;
 72             message = mContext.getString(R.string.vcard_import_will_start_message, displayName);
 73         } else {
 74             displayName = mContext.getString(R.string.vcard_unknown_filename);
 75             message = mContext.getString(
 76                     R.string.vcard_import_will_start_message_with_default_name);
 77         }
 78 
 79         // We just want to show notification for the first vCard.
 80         if (sequence == 0) {
 81             // TODO: Ideally we should detect the current status of import/export and
 82             // show "started" when we can import right now and show "will start" when
 83             // we cannot.
 84             mHandler.obtainMessage(0, message).sendToTarget();
 85         }
 86 
 87         final Notification notification = constructProgressNotification(mContext,
 88                 VCardService.TYPE_IMPORT, message, message, jobId, displayName, -1, 0);
 89         mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
 90     }
 91 
 92     @Override
 93     public void onImportParsed(ImportRequest request, int jobId, VCardEntry entry, int currentCount,
 94             int totalCount) {
 95         if (entry.isIgnorable()) {
 96             return;
 97         }
 98         
 99         if(currentCount!=totalCount && currentCount%100 !=1 ) return ;//for  slow down the notification speed
100 
101         final String totalCountString = String.valueOf(totalCount);
102         //modified ------
103         /*final String tickerText =
104                 mContext.getString(R.string.progress_notifier_message,
105                         String.valueOf(currentCount),
106                         totalCountString,
107                         entry.getDisplayName());
108         final String description = mContext.getString(R.string.importing_vcard_description,
109                 entry.getDisplayName());*/
110         final String tickerText =mContext.getString(R.string.progress_notifier_message_importing);
111         final String description = tickerText;
112         //end modified ------
113         final Notification notification = constructProgressNotification(
114                 mContext.getApplicationContext(), VCardService.TYPE_IMPORT, description, tickerText,
115                 jobId, request.displayName, totalCount, currentCount);
116         mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
117     }
118 
119     @Override
120     public void onImportFinished(ImportRequest request, int jobId, Uri createdUri) {
121         final String description = mContext.getString(R.string.importing_vcard_finished_title,
122                 request.displayName);
123         final Intent intent;
124         if (createdUri != null) {
125             final long rawContactId = ContentUris.parseId(createdUri);
126             final Uri contactUri = RawContacts.getContactLookupUri(
127                     mContext.getContentResolver(), ContentUris.withAppendedId(
128                             RawContacts.CONTENT_URI, rawContactId));
129             intent = new Intent(Intent.ACTION_VIEW, contactUri);
130         } else {
131             intent = null;
132         }
133         final Notification notification =
134                 NotificationImportExportListener.constructFinishNotification(mContext,
135                         VCardService.TYPE_IMPORT, description, null, intent);
136         mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
137                 jobId, notification);
138     }
139 
140     @Override
141     public void onImportFailed(ImportRequest request) {
142         // TODO: a little unkind to show Toast in this case, which is shown just a moment.
143         // Ideally we should show some persistent something users can notice more easily.
144         mHandler.obtainMessage(0,
145                 mContext.getString(R.string.vcard_import_request_rejected_message)).sendToTarget();
146     }
147 
148     @Override
149     public void onImportCanceled(ImportRequest request, int jobId) {
150         final String description = mContext.getString(R.string.importing_vcard_canceled_title,
151                 request.displayName);
152         final Notification notification =
153                 NotificationImportExportListener.constructCancelNotification(mContext, description);
154         mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
155                 jobId, notification);
156     }
157 
158     @Override
159     public void onExportProcessed(ExportRequest request, int jobId) {
160         final String displayName = request.destUri.getLastPathSegment();
161         final String message = mContext.getString(R.string.vcard_export_will_start_message,
162                 displayName);
163 
164         mHandler.obtainMessage(0, message).sendToTarget();
165         final Notification notification =
166                 NotificationImportExportListener.constructProgressNotification(mContext,
167                         VCardService.TYPE_EXPORT, message, message, jobId, displayName, -1, 0);
168         mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
169     }
170 
171     @Override
172     public void onExportFailed(ExportRequest request) {
173         mHandler.obtainMessage(0,
174                 mContext.getString(R.string.vcard_export_request_rejected_message)).sendToTarget();
175     }
176 
177     @Override
178     public void onCancelRequest(CancelRequest request, int type) {
179         final String description = type == VCardService.TYPE_IMPORT ?
180                 mContext.getString(R.string.importing_vcard_canceled_title, request.displayName) :
181                 mContext.getString(R.string.exporting_vcard_canceled_title, request.displayName);
182         final Notification notification = constructCancelNotification(mContext, description);
183         mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, request.jobId, notification);
184     }
185 
186     /**
187      * Constructs a {@link Notification} showing the current status of import/export.
188      * Users can cancel the process with the Notification.
189      *
190      * @param context
191      * @param type import/export
192      * @param description Content of the Notification.
193      * @param tickerText
194      * @param jobId
195      * @param displayName Name to be shown to the Notification (e.g. "finished importing XXXX").
196      * Typycally a file name.
197      * @param totalCount The number of vCard entries to be imported. Used to show progress bar.
198      * -1 lets the system show the progress bar with "indeterminate" state.
199      * @param currentCount The index of current vCard. Used to show progress bar.
200      */
201     /* package */ static Notification constructProgressNotification(
202             Context context, int type, String description, String tickerText,
203             int jobId, String displayName, int totalCount, int currentCount) {
204         // Note: We cannot use extra values here (like setIntExtra()), as PendingIntent doesn't
205         // preserve them across multiple Notifications. PendingIntent preserves the first extras
206         // (when flag is not set), or update them when PendingIntent#getActivity() is called
207         // (See PendingIntent#FLAG_UPDATE_CURRENT). In either case, we cannot preserve extras as we
208         // expect (for each vCard import/export request).
209         //
210         // We use query parameter in Uri instead.
211         // Scheme and Authority is arbitorary, assuming CancelActivity never refers them.
212         final Intent intent = new Intent(context, CancelActivity.class);
213         final Uri uri = (new Uri.Builder())
214                 .scheme("invalidscheme")
215                 .authority("invalidauthority")
216                 .appendQueryParameter(CancelActivity.JOB_ID, String.valueOf(jobId))
217                 .appendQueryParameter(CancelActivity.DISPLAY_NAME, displayName)
218                 .appendQueryParameter(CancelActivity.TYPE, String.valueOf(type)).build();
219         intent.setData(uri);
220 
221         final Notification.Builder builder = new Notification.Builder(context);
222         builder.setOngoing(true)
223                 .setProgress(totalCount, currentCount, totalCount == - 1)
224                 .setTicker(tickerText)
225                 .setContentTitle(description)
226                 .setSmallIcon(type == VCardService.TYPE_IMPORT
227                         ? android.R.drawable.stat_sys_download
228                         : android.R.drawable.stat_sys_upload)
229                 .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0));
230         if (totalCount > 0) {
231             builder.setContentText(context.getString(R.string.percentage,
232                     String.valueOf(currentCount * 100 / totalCount)));
233         }
234         return builder.getNotification();
235     }
236 
237     /**
238      * Constructs a Notification telling users the process is canceled.
239      *
240      * @param context
241      * @param description Content of the Notification
242      */
243     /* package */ static Notification constructCancelNotification(
244             Context context, String description) {
245         return new Notification.Builder(context)
246                 .setAutoCancel(true)
247                 .setSmallIcon(android.R.drawable.stat_notify_error)
248                 .setContentTitle(description)
249                 .setContentText(description)
250                 .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0))
251                 .getNotification();
252     }
253 
254     /**
255      * Constructs a Notification telling users the process is finished.
256      *
257      * @param context
258      * @param description Content of the Notification
259      * @param intent Intent to be launched when the Notification is clicked. Can be null.
260      */
261     /* package */ static Notification constructFinishNotification(
262             Context context, int type, String title, String description, Intent intent) {
263         return new Notification.Builder(context)
264                 .setAutoCancel(true)
265                 .setSmallIcon(type == VCardService.TYPE_IMPORT
266                         ? android.R.drawable.stat_sys_download_done
267                         : android.R.drawable.stat_sys_upload_done)
268                 .setContentTitle(title)
269                 .setContentText(description)
270                 .setContentIntent(PendingIntent.getActivity(context, 0,
271                         (intent != null ? intent : new Intent()), 0))
272                 .getNotification();
273     }
274 
275     /**
276      * Constructs a Notification telling the vCard import has failed.
277      *
278      * @param context
279      * @param reason The reason why the import has failed. Shown in description field.
280      */
281     /* package */ static Notification constructImportFailureNotification(
282             Context context, String reason) {
283         return new Notification.Builder(context)
284                 .setAutoCancel(true)
285                 .setSmallIcon(android.R.drawable.stat_notify_error)
286                 .setContentTitle(context.getString(R.string.vcard_import_failed))
287                 .setContentText(reason)
288                 .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0))
289                 .getNotification();
290     }
291 
292     @Override
293     public void onComplete() {
294         mContext.finish();
295     }
296 }
View Code

导入联系人:

处理每个Vcard文件时的通知(每个Vcard对应一条单独的通知,排队Import)

 1  public void onImportProcessed(ImportRequest request, int jobId, int sequence) {
 2         // Show a notification about the status
 3         final String displayName;
 4         final String message;
 5         if (request.displayName != null) {
 6             displayName = request.displayName;
 7             message = mContext.getString(R.string.vcard_import_will_start_message, displayName);
 8         } else {
 9             displayName = mContext.getString(R.string.vcard_unknown_filename);
10             message = mContext.getString(
11                     R.string.vcard_import_will_start_message_with_default_name);
12         }
13 
14         // We just want to show notification for the first vCard.
15         if (sequence == 0) {
16             // TODO: Ideally we should detect the current status of import/export and
17             // show "started" when we can import right now and show "will start" when
18             // we cannot.
19             mHandler.obtainMessage(0, message).sendToTarget();
20         }
21 
22         final Notification notification = constructProgressNotification(mContext,
23                 VCardService.TYPE_IMPORT, message, message, jobId, displayName, -1, 0);
24         mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
25     }

处理具体Vcard文件中每个contact时的通知(百分比进度条显示):

 1 public void onImportParsed(ImportRequest request, int jobId, VCardEntry entry, int currentCount,
 2             int totalCount) {
 3         if (entry.isIgnorable()) {
 4             return;
 5         }
 6         
 7         if(currentCount!=totalCount && currentCount%100 !=1 ) return ;//slow down the notification speed
 8 
 9         final String totalCountString = String.valueOf(totalCount);
10         //modified 
11         /*final String tickerText =
12                 mContext.getString(R.string.progress_notifier_message,
13                         String.valueOf(currentCount),
14                         totalCountString,
15                         entry.getDisplayName());
16         final String description = mContext.getString(R.string.importing_vcard_description,
17                 entry.getDisplayName());*/
18         final String tickerText =mContext.getString(R.string.progress_notifier_message_importing);
19         final String description = tickerText;
20         //end modified
21         final Notification notification = constructProgressNotification(
22                 mContext.getApplicationContext(), VCardService.TYPE_IMPORT, description, tickerText,
23                 jobId, request.displayName, totalCount, currentCount);
24         mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
25     }

----------------------------------------------------分割线----------------------------------------------------

导出联系人:

总的提示

 1 public void onExportProcessed(ExportRequest request, int jobId) {
 2         final String displayName = request.destUri.getLastPathSegment();
 3         final String message = mContext.getString(R.string.vcard_export_will_start_message,
 4                 displayName);
 5 
 6         mHandler.obtainMessage(0, message).sendToTarget();
 7         final Notification notification =
 8                 NotificationImportExportListener.constructProgressNotification(mContext,
 9                         VCardService.TYPE_EXPORT, message, message, jobId, displayName, -1, 0);
10         mNotificationManager.notify(DEFAULT_NOTIFICATION_TAG, jobId, notification);
11     }

具体每个Contact导出提示(百分比进度条显示):

在com.android.contacts.common.vcard.ExportProcessor中处理

 1 private void doProgressNotification(Uri uri, int totalCount, int currentCount) {
 2         final String displayName = uri.getLastPathSegment();
 3         final String description =
 4                 mService.getString(R.string.exporting_contact_list_message, displayName);
 5         final String tickerText =
 6                 mService.getString(R.string.exporting_contact_list_title);
 7         final Notification notification =
 8                 NotificationImportExportListener.constructProgressNotification(mService,
 9                         VCardService.TYPE_EXPORT, description, tickerText, mJobId, displayName,
10                         totalCount, currentCount);
11         mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
12                 mJobId, notification);
13     }

总结:导入导出联系人notification显示——对contacts总数进行while循环,每次循环都会new一个notificaiton,所以通知栏可以看到notification一闪一闪的显示。

         而通知栏下载进度条却是进度条更新显示,notification条不闪烁,UI效果更好。

posted on 2015-03-27 19:24  ^-^antoon^-^  阅读(530)  评论(0编辑  收藏  举报