首页 > 代码库 > 使用IntentService给自己的Android应用写一个文件下载器。

使用IntentService给自己的Android应用写一个文件下载器。

接着上一篇的http://www.cnblogs.com/zhengxt/p/3657833.html,当我们想给自己的APP写一个文件下载器时,可以用重写IntentService来实现。

使用IntentService有几个好处,IntentService继承于Service,适合拿来处理一些耗时又不需要去管它的任务。把要执行的任务用Intent加入到队列中,IntentService会有一个工作线程来取出队列中的Intent来处理。需要实现抽象方法onHandleIntent方法来执行这些任务。当所有任务都完成后,IntentService会自动停止。

同时使用Notification在通知栏让用户直观的知道下载进度,推荐使用Android3.0(API11)后提供的Notification.Builder来构建Notification。我这里为了让程序兼容Android2.1-2.3就没有使用Notification.Builder,用被废弃的Notification(int, CharSequence, long)来构建Notification。

还是按照上一篇一样,假设这是个版本更新文件的下载器,当更新文件下载完成后自动弹出安装界面。

IntentService代码:

  1 public class DownloadFileService extends IntentService {
  2     private static final String TAG = DownloadFileService.class.getSimpleName();
  3     public DownloadFileService() {
  4         super("com.test.download");
  5     }
  6     
  7     private NotificationManager notificationManager;
  8     private Notification notification;
  9     private RemoteViews rViews;
 10     protected void onHandleIntent(Intent intent) {
 11         Bundle bundle = intent.getExtras();
 12         // 获得下载文件的url
 13         String downloadUrl = bundle.getString("url");
 14         // 设置文件下载后的保存路径,保存在SD卡根目录的Download文件夹
 15         File dirs = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download");
 16         // 检查文件夹是否存在,不存在则创建
 17         if (!dirs.exists()) {
 18             dirs.mkdir();
 19         }
 20         File file = new File(dirs, "file.apk");
 21         // 设置Notification
 22         notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 23         notification = new Notification(R.drawable.ic_launcher, "版本更新下载", System.currentTimeMillis());
 24         Intent intentNotifi = new Intent(this, Main.class);
 25         PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intentNotifi, 0);
 26         notification.contentIntent = pendingIntent;
 27         // 加载Notification的布局文件
 28         rViews = new RemoteViews(getPackageName(), R.layout.downloadfile_layout);
 29         // 设置下载进度条
 30         rViews.setProgressBar(R.id.downloadFile_pb, 100, 0, false);
 31         notification.contentView = rViews;
 32         notificationManager.notify(0, notification);
 33         // 开始下载
 34         downloadFile(downloadUrl, file);
 35         // 移除通知栏
 36         notificationManager.cancel(0);
 37         // 广播出去,由广播接收器来处理下载完成的文件
 38         Intent sendIntent = new Intent("com.test.downloadComplete");
 39         // 把下载好的文件的保存地址加进Intent
 40         sendIntent.putExtra("downloadFile", file.getPath());
 41         sendBroadcast(sendIntent);
 42     }
 43     private int fileLength, downloadLength;
 44     private void downloadFile(String downloadUrl, File file){
 45         FileOutputStream fos = null;
 46         try {
 47             fos = new FileOutputStream(file);
 48         } catch (FileNotFoundException e) {
 49             Log.e(TAG, "找不到保存下载文件的目录");
 50             e.printStackTrace();
 51         }
 52         InputStream ips = null;
 53         try {
 54             URL url = new URL(downloadUrl);
 55             HttpURLConnection huc = (HttpURLConnection) url.openConnection();
 56             huc.setRequestMethod("GET");
 57             huc.setReadTimeout(10000);
 58             huc.setConnectTimeout(3000);
 59             fileLength = Integer.valueOf(huc.getHeaderField("Content-Length"));
 60             ips = huc.getInputStream();
 61             // 拿到服务器返回的响应码
 62             int hand = huc.getResponseCode();
 63             if (hand == 200) {
 64                 // 开始检查下载进度
 65                 handler.post(run);
 66                 // 建立一个byte数组作为缓冲区,等下把读取到的数据储存在这个数组
 67                 byte[] buffer = new byte[8192];
 68                 int len = 0;
 69                 while ((len = ips.read(buffer)) != -1) {
 70                     fos.write(buffer, 0, len);
 71                     downloadLength = downloadLength + len;
 72                 }
 73             } else {
 74                 Log.e(TAG, "服务器返回码" + hand);
 75             }
 76 
 77         } catch (ProtocolException e) {
 78             e.printStackTrace();
 79         } catch (MalformedURLException e) {
 80             e.printStackTrace();
 81         } catch (IOException e) {
 82             e.printStackTrace();
 83         } finally {
 84             try {
 85                 if (fos != null) {
 86                     fos.close();
 87                 }
 88                 if (ips != null) {
 89                     ips.close();
 90                 }
 91             } catch (IOException e) {
 92                 e.printStackTrace();
 93             }
 94         }
 95     }
 96     
 97     
 98     
 99     public void onDestroy() {
100         // 移除定時器
101         handler.removeCallbacks(run);
102         super.onDestroy();
103     }
104 
105     // 定时器,每隔一段时间检查下载进度,然后更新Notification上的ProgressBar
106     private Handler handler = new Handler();
107     private Runnable run = new Runnable() {
108         public void run() {
109             rViews.setProgressBar(R.id.downloadFile_pb, 100, downloadLength*100 / fileLength, false);
110             notification.contentView = rViews;
111             notificationManager.notify(0, notification);
112             handler.postDelayed(run, 1000);
113         }
114     };
115     
116 }

 

还要记得要在AndroidManifest.xml的application节点里注册Service。例如这样:

1 <service android:name="com.saetest.DownloadFileService"></service>

 

我们下载个谷歌地图来试试看。

 1    public void onClick(View v) {
 2         // new CheckedUpdate().execute();
 3         String url = "http://www.appchina.com/market/d/1603385/cop.baidu_0/com.google.android.apps.maps.apk";
 4         Intent downloadIntent = new Intent(this, DownloadFileService.class);
 5         Bundle bundle = new Bundle();
 6         bundle.putString("url", url);
 7         downloadIntent.putExtras(bundle);
 8         startService(downloadIntent);
 9         // 设置广播接收器,当新版本的apk下载完成后自动弹出安装界面
10         IntentFilter intentFilter = new IntentFilter("com.test.downloadComplete");
11         receiver = new BroadcastReceiver() {
12 
13             public void onReceive(Context context, Intent intent) {
14                 Intent install = new Intent(Intent.ACTION_VIEW);
15                 String pathString = intent.getStringExtra("downloadFile");
16                 install.setDataAndType(Uri.fromFile(new File(pathString)), "application/vnd.android.package-archive");
17                 install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
18                 context.startActivity(install);
19             }
20         };
21         registerReceiver(receiver, intentFilter);
22     }
23 
24     protected void onDestroy() {
25         // 移除广播接收器
26         if (receiver != null) {
27             unregisterReceiver(receiver);
28         }
29         super.onDestroy();
30     }