Notification使用详解之二:可更新进度的通知

来源:互联网 发布:米德尔顿 知乎 编辑:程序博客网 时间:2024/04/24 02:32

上次和大家分享了关于Notification的基础应用,包括简单的通知和自定义视图的通知。今天和大家分享一下如何实现一个可更新进度的通知。

我们将会模拟一个下载任务,先启动一个线程负责模拟下载工作,在这个过程中更新进度信息,然后下载线程把最新的进度信息以消息的形式,发送到UI线程的消息队列中,最后UI线程负责根据最新的进度信息来更新进度通知的UI界面。

好,大概就是这个步骤。接下来我们根据具体的实例来演示一下这个过程。

我们新建一个notification项目,然后修改/res/layout/main.xml布局文件,代码如下:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent">  
  6.     <Button  
  7.         android:id="@+id/download"  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="download"  
  11.         android:onClick="download"/>  
  12.     <Button  
  13.         android:id="@+id/cancel"  
  14.         android:layout_width="fill_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:text="cancel"  
  17.         android:onClick="cancel"/>  
  18. </LinearLayout>  

注意,为了使示例中的Java代码看起来结构更加清晰,我们将按钮的点击事件都定义在布局文件中。

然后再来看一下MainActivity.java的代码:

[java] view plaincopy
  1. package com.scott.notification;  
  2.   
  3. import android.app.Activity;  
  4. import android.app.Notification;  
  5. import android.app.NotificationManager;  
  6. import android.app.PendingIntent;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.os.Bundle;  
  10. import android.os.Handler;  
  11. import android.os.Message;  
  12. import android.view.View;  
  13. import android.widget.RemoteViews;  
  14.   
  15. public class MainActivity extends Activity {  
  16.   
  17.     private static final int NOTIFY_ID = 0;  
  18.   
  19.     private boolean cancelled;  
  20.   
  21.     private NotificationManager mNotificationManager;  
  22.     private Notification mNotification;  
  23.   
  24.     private Context mContext = this;  
  25.   
  26.     private Handler handler = new Handler() {  
  27.         public void handleMessage(android.os.Message msg) {  
  28.             switch (msg.what) {  
  29.             case 1:  
  30.                 int rate = msg.arg1;  
  31.                 if (rate < 100) {  
  32.                     // 更新进度  
  33.                     RemoteViews contentView = mNotification.contentView;  
  34.                     contentView.setTextViewText(R.id.rate, rate + "%");  
  35.                     contentView.setProgressBar(R.id.progress, 100, rate, false);  
  36.                 } else {  
  37.                     // 下载完毕后变换通知形式  
  38.                     mNotification.flags = Notification.FLAG_AUTO_CANCEL;  
  39.                     mNotification.contentView = null;  
  40.                     Intent intent = new Intent(mContext, FileMgrActivity.class);  
  41.                     PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);  
  42.                     mNotification.setLatestEventInfo(mContext, "下载完成""文件已下载完毕", contentIntent);  
  43.                 }  
  44.   
  45.                 // 最后别忘了通知一下,否则不会更新  
  46.                 mNotificationManager.notify(NOTIFY_ID, mNotification);  
  47.                 break;  
  48.             case 0:  
  49.                 // 取消通知  
  50.                 mNotificationManager.cancel(NOTIFY_ID);  
  51.                 break;  
  52.             }  
  53.         };  
  54.     };  
  55.   
  56.     @Override  
  57.     public void onCreate(Bundle savedInstanceState) {  
  58.         super.onCreate(savedInstanceState);  
  59.         setContentView(R.layout.main);  
  60.     }  
  61.   
  62.     public void download(View view) {  
  63.         mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);  
  64.   
  65.         int icon = R.drawable.down;  
  66.         CharSequence tickerText = "开始下载";  
  67.         long when = System.currentTimeMillis();  
  68.         mNotification = new Notification(icon, tickerText, when);  
  69.   
  70.         // 放置在"正在运行"栏目中  
  71.         mNotification.flags = Notification.FLAG_ONGOING_EVENT;  
  72.   
  73.         RemoteViews contentView = new RemoteViews(mContext.getPackageName(), R.layout.download_notification_layout);  
  74.         contentView.setTextViewText(R.id.fileName, "AngryBird.apk");  
  75.         // 指定个性化视图  
  76.         mNotification.contentView = contentView;  
  77.   
  78.         // intent为null,表示点击通知时不跳转  
  79.         PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0null0);  
  80.         // 指定内容意图  
  81.         mNotification.contentIntent = contentIntent;  
  82.   
  83.         mNotificationManager.notify(NOTIFY_ID, mNotification);  
  84.   
  85.         new Thread() {  
  86.             public void run() {  
  87.                 startDownload();  
  88.             };  
  89.         }.start();  
  90.     }  
  91.   
  92.     public void cancel(View view) {  
  93.         cancelled = true;  
  94.     }  
  95.   
  96.     private void startDownload() {  
  97.         cancelled = false;  
  98.         int rate = 0;  
  99.         while (!cancelled && rate < 100) {  
  100.             try {  
  101.                 // 模拟下载进度  
  102.                 Thread.sleep(500);  
  103.                 rate = rate + 5;  
  104.             } catch (InterruptedException e) {  
  105.                 e.printStackTrace();  
  106.             }  
  107.             Message msg = handler.obtainMessage();  
  108.             msg.what = 1;  
  109.             msg.arg1 = rate;  
  110.             handler.sendMessage(msg);  
  111.         }  
  112.         if (cancelled) {  
  113.             Message msg = handler.obtainMessage();  
  114.             msg.what = 0;  
  115.             handler.sendMessage(msg);  
  116.         }  
  117.     }  
  118. }  

值得注意的是,在控制下载线程时使用了cancelled这个boolean值标志变量,对于线程的控制更好一些,不建议使用Thread.interrupt()去中断一个线程。另外,对于更新通知的UI界面时,要记住调用NotificationManager.notify(int id, Notification notification)方法通知一下,否则即使设置了新值,也不会起作用的。

程序中用到的带进度的通知布局/res/layout/download_notification_layout.xml布局文件代码如下:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.   android:layout_width="fill_parent"  
  4.   android:layout_height="fill_parent"  
  5.   android:padding="3dp">  
  6.   <ImageView  
  7.     android:id="@+id/imageView"  
  8.     android:layout_width="wrap_content"  
  9.     android:layout_height="wrap_content"  
  10.     android:layout_margin="3dp"  
  11.     android:src="@drawable/down"/>  
  12.   <TextView  
  13.     android:id="@+id/fileName"  
  14.     android:layout_width="fill_parent"  
  15.     android:layout_height="fill_parent"  
  16.     android:layout_toRightOf="@id/imageView"  
  17.     android:layout_alignBottom="@id/imageView"  
  18.     android:gravity="center_vertical"  
  19.     android:textColor="#000"/>  
  20.   <TextView  
  21.     android:id="@+id/rate"  
  22.     android:layout_width="fill_parent"  
  23.     android:layout_height="wrap_content"  
  24.     android:layout_below="@id/imageView"  
  25.     android:layout_alignRight="@id/imageView"  
  26.     android:gravity="center"  
  27.     android:text="0%"  
  28.     android:textColor="#000"/>  
  29.   <ProgressBar   
  30.     android:id="@+id/progress"  
  31.     style="?android:attr/progressBarStyleHorizontal"  
  32.     android:layout_width="fill_parent"  
  33.     android:layout_height="wrap_content"  
  34.     android:layout_below="@id/fileName"  
  35.     android:layout_alignLeft="@id/fileName"  
  36.     android:max="100"  
  37.     android:progress="0"/>  
  38. </RelativeLayout>  

该通知的布局使用了相对布局,更加灵活易用,所以推荐大家多使用相对布局。

对于MainActivity.java中涉及到的FileMgrActivity,它是一个简单的界面,这里就不在介绍了,that's not the point。

最后我们跑一下程序,看看效果如何:

貌似还不错,好了,今天先到这里,下次再找机会分享

原创粉丝点击