Notification使用详解之四:由后台服务向Activity发送进度信息

上次讲到了如何在Activity中监听后台服务的进度信息,实现的方式是让Activity与后台服务绑定,,通过中间对象Binder的实例操作后台服务。从效果上来讲,这种方式是可行的,不过这种实现有个缺点,那就是Activity的任务太重了,为了监听服务的状态,我们不得不绑定服务,然后还需不断地定时的获取最新的进度,我们为何不换一下形式呢,让Service主动将进度发送给Activity,我们在Activity中只需拿到进度数据,然后更新UI界面。这种新形式就像上次结尾提到的,就像两个男人同时喜欢一个女人,都通过自己的手段试图从那个女人那里获取爱情,现在我们要让那个女人变为主动方,将爱情同时传递给那两个男人。

要实现以上方式,我们需要用到BroadcastReceiver,如果不太了解的朋友们,可以查阅相关资料补充一下。

关于整个流程的的截图,我在这里就不在贴出了,大家可以参看Notification详解之三的流程截图。布局文件也没有变化,所以这里也不在贴出。

我们主要看一下MainActivity、DownloadService、FileMgrActivity这几个组件的实现形式。

首先是MainActivity:

package com.scott.notification;import android.app.Activity;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Bundle;import android.view.View;import android.widget.TextView;public class MainActivity extends Activity {private MyReceiver receiver;private TextView text;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);text = (TextView) findViewById(R.id.text);receiver = new MyReceiver();IntentFilter filter = new IntentFilter();filter.addAction("android.intent.action.MY_RECEIVER");//注册registerReceiver(receiver, filter);}@Overrideprotected void onDestroy() {super.onDestroy();//不要忘了这一步unregisterReceiver(receiver);}public void start(View view) {Intent intent = new Intent(this, DownloadService.class);//这里不再使用bindService,而使用startServicestartService(intent);}/** * 广播接收器 * @author user * */private class MyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Bundle bundle = intent.getExtras();int progress = bundle.getInt("progress");text.setText("downloading…" + progress + "%");}}}

上面的代码中,我们的MyReceiver类是继承了BroadcastReceiver,在onReceive方法中,定义了收到进度信息并更新UI的逻辑,在onCreate中,我们注册了这个接受者,并指定action为android.intent.action.MY_RECEIVER,如此一来,如果其他组件向这个指定的action发送消息,我们就能够接收到;另外要注意的是,不要忘了在Activity被摧毁的时候调用unregisterReceiver取消注册。

然后再来看一下DownloadService有什么变化:

package com.scott.notification;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Context;import android.content.Intent;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.widget.RemoteViews;public class DownloadService extends Service {private static final int NOTIFY_ID = 0;private boolean cancelled;private Context mContext = this;private NotificationManager mNotificationManager;private Notification mNotification;private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {switch (msg.what) {case 1:int rate = msg.arg1;if (rate < 100) {//更新进度RemoteViews contentView = mNotification.contentView;contentView.setTextViewText(R.id.rate, rate + "%");contentView.setProgressBar(R.id.progress, 100, rate, false);} else {//下载完毕后变换通知形式mNotification.flags = Notification.FLAG_AUTO_CANCEL;mNotification.contentView = null;Intent intent = new Intent(mContext, FileMgrActivity.class);// 告知已完成intent.putExtra("completed", "yes");//更新参数,注意flags要使用FLAG_UPDATE_CURRENTPendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);mNotification.setLatestEventInfo(mContext, "下载完成", "文件已下载完毕", contentIntent);}// 最后别忘了通知一下,否则不会更新mNotificationManager.notify(NOTIFY_ID, mNotification);if (rate >= 100) {stopSelf();//停止服务}break;case 0:// 取消通知mNotificationManager.cancel(NOTIFY_ID);break;}};};@Overridepublic void onCreate() {super.onCreate();mNotificationManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);int icon = R.drawable.down;CharSequence tickerText = "开始下载";long when = System.currentTimeMillis();mNotification = new Notification(icon, tickerText, when);// 放置在"正在运行"栏目中mNotification.flags = Notification.FLAG_ONGOING_EVENT;RemoteViews contentView = new RemoteViews(mContext.getPackageName(), R.layout.download_notification_layout);contentView.setTextViewText(R.id.fileName, "AngryBird.apk");// 指定个性化视图mNotification.contentView = contentView;Intent intnt = new Intent(this, FileMgrActivity.class);PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intnt, PendingIntent.FLAG_UPDATE_CURRENT);// 指定内容意图mNotification.contentIntent = contentIntent;mNotificationManager.notify(NOTIFY_ID, mNotification);new Thread() {public void run() {startDownload();};}.start();}@Overridepublic void onDestroy() {super.onDestroy();cancelled = true;//停止下载线程}private void startDownload() {cancelled = false;int rate = 0;while (!cancelled && rate < 100) {try {//模拟下载进度Thread.sleep(500);rate = rate + 5;} catch (InterruptedException e) {e.printStackTrace();}Message msg = handler.obtainMessage();msg.what = 1;msg.arg1 = rate;handler.sendMessage(msg);//发送特定action的广播Intent intent = new Intent();intent.setAction("android.intent.action.MY_RECEIVER");intent.putExtra("progress", rate);sendBroadcast(intent);}if (cancelled) {Message msg = handler.obtainMessage();msg.what = 0;handler.sendMessage(msg);}}@Overridepublic IBinder onBind(Intent intent) {return null;}}原来和文字沾上边的孩子从来都是不快乐的,

Notification使用详解之四:由后台服务向Activity发送进度信息

相关文章:

你感兴趣的文章:

标签云: