Notification使用詳解之四:由後臺服務向Activity發送進度信息

上次講到了如何在Activity中監聽後臺服務的進度信息,實現的方式是讓Activity與後臺服務綁定,經過中間對象Binder的實例操做 後臺服務。從效果上來說,這種方式是可行的,不過這種實現有個缺點,那就是Activity的任務過重了,爲了監聽服務的狀態,咱們不得不綁定服務,而後 還需不斷地定時的獲取最新的進度,咱們爲什麼不換一下形式呢,讓Service主動將進度發送給Activity,咱們在Activity中只需拿到進度數 據,而後更新UI界面。這種新形式就像上次結尾提到的,就像兩個男人同時喜歡一個女人,都經過本身的手段試圖從那個女人那裏獲取愛情,如今咱們要讓那個女 人變爲主動方,將愛情同時傳遞給那兩個男人。 java

要實現以上方式,咱們須要用到BroadcastReceiver,若是不太瞭解的朋友們,能夠查閱相關資料補充一下。 android

關於整個流程的的截圖,我在這裏就不在貼出了,你們能夠參看Notification詳解之三的流程截圖。佈局文件也沒有變化,因此這裏也不在貼出。 app

咱們主要看一下MainActivity、DownloadService、FileMgrActivity這幾個組件的實現形式。 ide

首先是MainActivity: 佈局

[java] view plain copy
  1. package com.scott.notification;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9. import android.view.View;  
  10. import android.widget.TextView;  
  11.   
  12. public class MainActivity extends Activity {  
  13.   
  14.     private MyReceiver receiver;  
  15.     private TextView text;  
  16.   
  17.     @Override  
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.main);  
  21.         text = (TextView) findViewById(R.id.text);  
  22.           
  23.         receiver = new MyReceiver();  
  24.         IntentFilter filter = new IntentFilter();  
  25.         filter.addAction("android.intent.action.MY_RECEIVER");  
  26.         //註冊  
  27.         registerReceiver(receiver, filter);  
  28.     }  
  29.       
  30.     @Override  
  31.     protected void onDestroy() {  
  32.         super.onDestroy();  
  33.         //不要忘了這一步  
  34.         unregisterReceiver(receiver);  
  35.     }  
  36.   
  37.     public void start(View view) {  
  38.         Intent intent = new Intent(this, DownloadService.class);  
  39.         //這裏再也不使用bindService,而使用startService  
  40.         startService(intent);  
  41.     }  
  42.   
  43.     /** 
  44.      * 廣播接收器 
  45.      * @author user 
  46.      * 
  47.      */  
  48.     private class MyReceiver extends BroadcastReceiver {  
  49.   
  50.         @Override  
  51.         public void onReceive(Context context, Intent intent) {  
  52.             Bundle bundle = intent.getExtras();  
  53.             int progress = bundle.getInt("progress");  
  54.             text.setText("downloading..." + progress + "%");  
  55.         }  
  56.     }  
  57. }  

上 面的代碼中,咱們的MyReceiver類是繼承了BroadcastReceiver,在onReceive方法中,定義了收到進度信息並更新UI的邏 輯,在onCreate中,咱們註冊了這個接受者,並指定action爲android.intent.action.MY_RECEIVER,如此一 來,若是其餘組件向這個指定的action發送消息,咱們就可以接收到;另外要注意的是,不要忘了在Activity被摧毀的時候調用 unregisterReceiver取消註冊。 this

而後再來看一下DownloadService有什麼變化: spa

[java] view plain copy
  1. package com.scott.notification;  
  2.   
  3. import android.app.Notification;  
  4. import android.app.NotificationManager;  
  5. import android.app.PendingIntent;  
  6. import android.app.Service;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.os.Handler;  
  10. import android.os.IBinder;  
  11. import android.os.Message;  
  12. import android.widget.RemoteViews;  
  13.   
  14. public class DownloadService extends Service {  
  15.   
  16.     private static final int NOTIFY_ID = 0;  
  17.     private boolean cancelled;  
  18.       
  19.     private Context mContext = this;  
  20.     private NotificationManager mNotificationManager;  
  21.     private Notification mNotification;  
  22.       
  23.     private Handler handler = new Handler() {  
  24.         public void handleMessage(android.os.Message msg) {  
  25.             switch (msg.what) {  
  26.             case 1:  
  27.                 int rate = msg.arg1;  
  28.                 if (rate < 100) {  
  29.                     //更新進度  
  30.                     RemoteViews contentView = mNotification.contentView;  
  31.                     contentView.setTextViewText(R.id.rate, rate + "%");  
  32.                     contentView.setProgressBar(R.id.progress, 100, rate, false);  
  33.                 } else {  
  34.                     //下載完畢後變換通知形式  
  35.                     mNotification.flags = Notification.FLAG_AUTO_CANCEL;  
  36.                     mNotification.contentView = null;  
  37.                     Intent intent = new Intent(mContext, FileMgrActivity.class);  
  38.                     // 告知已完成  
  39.                     intent.putExtra("completed""yes");  
  40.                     //更新參數,注意flags要使用FLAG_UPDATE_CURRENT  
  41.                     PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);  
  42.                     mNotification.setLatestEventInfo(mContext, "下載完成""文件已下載完畢", contentIntent);  
  43.                 }  
  44.   
  45.                 // 最後別忘了通知一下,不然不會更新  
  46.                 mNotificationManager.notify(NOTIFY_ID, mNotification);  
  47.                   
  48.                 if (rate >= 100) {  
  49.                     stopSelf(); //中止服務  
  50.                 }  
  51.                   
  52.                 break;  
  53.             case 0:  
  54.                 // 取消通知  
  55.                 mNotificationManager.cancel(NOTIFY_ID);  
  56.                 break;  
  57.             }  
  58.         };  
  59.     };  
  60.       
  61.     @Override  
  62.     public void onCreate() {  
  63.         super.onCreate();  
  64.         mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);  
  65.     }  
  66.       
  67.     @Override  
  68.     public void onStart(Intent intent, int startId) {  
  69.         super.onStart(intent, startId);  
  70.           
  71.         int icon = R.drawable.down;  
  72.         CharSequence tickerText = "開始下載";  
  73.         long when = System.currentTimeMillis();  
  74.         mNotification = new Notification(icon, tickerText, when);  
  75.   
  76.         // 放置在"正在運行"欄目中  
  77.         mNotification.flags = Notification.FLAG_ONGOING_EVENT;  
  78.   
  79.         RemoteViews contentView = new RemoteViews(mContext.getPackageName(), R.layout.download_notification_layout);  
  80.         contentView.setTextViewText(R.id.fileName, "AngryBird.apk");  
  81.         // 指定個性化視圖  
  82.         mNotification.contentView = contentView;  
  83.   
  84.         Intent intnt = new Intent(this, FileMgrActivity.class);  
  85.         PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intnt, PendingIntent.FLAG_UPDATE_CURRENT);  
  86.         // 指定內容意圖  
  87.         mNotification.contentIntent = contentIntent;  
  88.   
  89.         mNotificationManager.notify(NOTIFY_ID, mNotification);  
  90.           
  91.         new Thread() {  
  92.             public void run() {  
  93.                 startDownload();  
  94.             };  
  95.         }.start();  
  96.     }  
  97.       
  98.     @Override  
  99.     public void onDestroy() {  
  100.         super.onDestroy();  
  101.         cancelled = true;   //中止下載線程  
  102.     }  
  103.       
  104.     private void startDownload() {  
  105.         cancelled = false;  
  106.         int rate = 0;  
  107.         while (!cancelled && rate < 100) {  
  108.             try {  
  109.                 //模擬下載進度  
  110.                 Thread.sleep(500);  
  111.                 rate = rate + 5;  
  112.             } catch (InterruptedException e) {  
  113.                 e.printStackTrace();  
  114.             }  
  115.             Message msg = handler.obtainMessage();  
  116.             msg.what = 1;  
  117.             msg.arg1 = rate;  
  118.             handler.sendMessage(msg);  
  119.               
  120.             //發送特定action的廣播  
  121.             Intent intent = new Intent();  
  122.             intent.setAction("android.intent.action.MY_RECEIVER");  
  123.             intent.putExtra("progress", rate);  
  124.             sendBroadcast(intent);  
  125.         }  
  126.         if (cancelled) {  
  127.             Message msg = handler.obtainMessage();  
  128.             msg.what = 0;  
  129.             handler.sendMessage(msg);  
  130.         }  
  131.     }  
  132.       
  133.     @Override  
  134.     public IBinder onBind(Intent intent) {  
  135.         return null;  
  136.     }  
  137. }  

可 以看到,咱們在onBind方法裏不在返回自定義的Binder實例了,由於如今的Service和Activitys之間並無綁定關係了,他們是獨立 的;在下載過程當中,咱們會調用sendBroadcast方法,向指定的action發送一個附帶有進度信息的intent,這樣的話,全部註冊過 action爲android.intent.action.MY_RECEIVER的Activity都能收到這條進度消息了。 .net

最後再來看一下FileMgrActivity: 線程

[java] view plain copy
  1. package com.scott.notification;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9. import android.view.View;  
  10. import android.widget.ProgressBar;  
  11.   
  12. public class FileMgrActivity extends Activity {  
  13.       
  14.     private MyReceiver receiver;  
  15.     private ProgressBar progressBar;  
  16.       
  17.     @Override  
  18.     public void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.filemgr);  
  21.         progressBar = (ProgressBar) findViewById(R.id.progress);  
  22.           
  23.         if ("yes".equals(getIntent().getStringExtra("completed"))) {  
  24.             progressBar.setProgress(100);  
  25.         }  
  26.           
  27.         receiver = new MyReceiver();  
  28.         IntentFilter filter = new IntentFilter();  
  29.         filter.addAction("android.intent.action.MY_RECEIVER");  
  30.         //註冊  
  31.         registerReceiver(receiver, filter);  
  32.     }  
  33.       
  34.     public void cancel(View view) {  
  35.         Intent intent = new Intent(this, DownloadService.class);  
  36.         stopService(intent);  
  37.     }  
  38.       
  39.     @Override  
  40.     protected void onDestroy() {  
  41.         super.onDestroy();  
  42.         //不要忘了這一步  
  43.         unregisterReceiver(receiver);  
  44.     }  
  45.       
  46.     /** 
  47.      * 廣播接收器 
  48.      * @author user 
  49.      * 
  50.      */  
  51.     private class MyReceiver extends BroadcastReceiver {  
  52.   
  53.         @Override  
  54.         public void onReceive(Context context, Intent intent) {  
  55.             Bundle bundle = intent.getExtras();  
  56.             int progress = bundle.getInt("progress");  
  57.             progressBar.setProgress(progress);  
  58.         }  
  59.     }  
  60.       
  61. }  

我 們發現,FileMgrActivity的模式和MainActivity差很少,也是註冊了相同的廣播接收者,對於DownloadService來講 本身是廣播基站,MainActivity和FileMgrActivity就是聽衆,信號可以同時到達多個聽衆,對於代碼而言,與以前的代碼比較一下, 發現簡潔了許多,顯然這種方式更好一些。 對象

對於咱們上面提到的男女關係,DownloadService就是那個女人,而後兩個男人將本身的 手機號告知了女人,等於註冊了接收器,而後女人將短信羣發給兩個男人。不過在這種狀況下,兩個男人互相都不知道對方的存在,覺得女人深深的愛着本身,等到 發現一切的時候,就是痛苦的時候。相信你們若是遇到這種狀況都會很痛苦吧,至於大家信不信,我反正是信的。哈哈。

其實關於Notification的講解最後兩篇涉及到Notification的很少,主要是圍繞Notification作一些實際的應用示例,但願對於朋友們平時遇到的問題會有所幫助,若是這方面有了新的研究總結,我會再及時更新的,謝謝你們。
相關文章
相關標籤/搜索