android多任务下载的状态更新

本文介绍了一种使用Android Service实现后台下载任务的方法,并通过广播更新UI显示下载进度。该方案适用于多任务并能在应用退出后继续运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于下载任务,通常需要实时的更新任务进度


一般而言,最直接的方式是使用AsyncTask对进度进行实时更新

但对于多个任务并且界面切换后,AsyncTask并不能满足要求

此时需要使用service,进行独立的下载操作,而进度的更新可以通过不断的广播来更新需要展示的进度


代码片段

  1. package com.exam;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.RandomAccessFile;  
  7. import java.net.HttpURLConnection;  
  8. import java.net.URL;  
  9. import java.util.concurrent.Executors;  
  10. import java.util.concurrent.ThreadPoolExecutor;  
  11.   
  12. import android.app.Service;  
  13. import android.content.Intent;  
  14. import android.net.Uri;  
  15. import android.os.Handler;  
  16. import android.os.IBinder;  
  17. import android.text.TextUtils;  
  18. import android.util.Log;  
  19.   
  20. import com.exam.utils.FileUtils;  
  21.   
  22. public class DownloadService extends Service {  
  23.   
  24.     private boolean stop;  
  25.     public static final String ACTION_DOWNLOAD = "com.exam.downloadservice";  
  26.     private static ThreadPoolExecutor sExecutorService = (ThreadPoolExecutor) Executors  
  27.             .newFixedThreadPool(3);  
  28.     private String sAppId;  
  29.     private Handler mHandler = new Handler() {  
  30.         public void handleMessage(android.os.Message msg) {  
  31.             int what = msg.what;  
  32.             if (stop) {  
  33.                 return;  
  34.             }  
  35.             if (what == 0) {  
  36.                 if (msg.obj != null && msg.obj instanceof Intent) {  
  37.                     Intent intent = (Intent) msg.obj;  
  38.                     DownloadService.this.sendBroadcast(intent);  
  39.                 }  
  40.             } else if (what == 2) {  
  41.                 try {  
  42.                     Intent instIntent = new Intent(Intent.ACTION_VIEW);  
  43.                     instIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  44.                     instIntent.setDataAndType(  
  45.                             Uri.fromFile(new File(msg.obj.toString())),  
  46.                             "application/vnd.android.package-archive");  
  47.                     startActivity(instIntent);  
  48.                 } catch (Exception e) {  
  49.                     e.printStackTrace();  
  50.                 }  
  51.             }  
  52.         }  
  53.     };  
  54.   
  55.     private class DownloadTask implements Runnable {  
  56.         private String mLocalPath = FileUtils.SDCARD_BACKUP_APP;  
  57.         private String mAppId;  
  58.         private String mDownloadUrl;  
  59.         private String mLocalName = "tmp.apk";  
  60.         private String mFileSize;  
  61.         /** 
  62.          * -2等待-1失败,0执行前, 1执行中 ,2成功 
  63.          */  
  64.         // private int flag = -2;   
  65.   
  66.         private long mTotalSize;  
  67.         private long mDownloadedSize;  
  68.         private long mDownloadedSpeed;  
  69.         private int mProgress;  
  70.   
  71.         public DownloadTask(String appId, String appName, String downloadUrl,  
  72.                 long size) {  
  73.             this.mAppId = appId;  
  74.             this.mLocalName = appName + ".apk";  
  75.             this.mDownloadUrl = downloadUrl;  
  76.             this.mFileSize = FileUtils.getFormatSize(size);  
  77.         }  
  78.   
  79.         protected void onPreExecute(int flag) {  
  80.             mTotalSize = 0;  
  81.             mDownloadedSize = 0;  
  82.             mDownloadedSpeed = 1;  
  83.             mProgress = 0;  
  84.             publishProgress(flag);  
  85.         }  
  86.   
  87.         protected void onPostExecute(int flag) {  
  88.             publishProgress(flag);  
  89.         }  
  90.   
  91.         private void publishProgress(int flag) {  
  92.             if (mProgress > 100) {  
  93.                 mProgress = 100;  
  94.             }  
  95.             if (mProgress < 0) {  
  96.                 mProgress = 0;  
  97.             }  
  98.   
  99.             StringBuffer bufferState = new StringBuffer();  
  100.             bufferState.append(FileUtils.getFormatSize(mDownloadedSize))  
  101.                     .append("/").append(mFileSize);  
  102.   
  103.             StringBuffer bufferSpeed = new StringBuffer();  
  104.             bufferSpeed.append(FileUtils.getFormatSize(mDownloadedSpeed))  
  105.                     .append("/s");  
  106.   
  107.             Intent intent = new Intent(ACTION_DOWNLOAD);  
  108.             intent.putExtra("appId", mAppId);  
  109.             intent.putExtra("state", bufferState.toString());  
  110.             intent.putExtra("speed", bufferSpeed.toString());  
  111.             intent.putExtra("progress"this.mProgress);  
  112.             // -2等待-1失败,0执行前, 1执行中 ,2成功   
  113.             intent.putExtra("flag", flag);  
  114.             mHandler.sendMessage(mHandler.obtainMessage(0, intent));  
  115.             if (flag == 2) {  
  116.                 String path = FileUtils.SDCARD_BACKUP_APP + mLocalName;  
  117.                 mHandler.sendMessage(mHandler.obtainMessage(2, path));  
  118.             }  
  119.         }  
  120.   
  121.         public void execute() {  
  122.             int flag = 0;  
  123.             onPreExecute(flag);  
  124.             flag = 1;  
  125.             boolean result = downloadFile(flag);  
  126.             if (result) {  
  127.                 flag = 2;  
  128.             } else {  
  129.                 flag = -1;  
  130.             }  
  131.             onPostExecute(flag);  
  132.         }  
  133.   
  134.         private boolean downloadFile(int flag) {  
  135.             InputStream inputStream = null;  
  136.             RandomAccessFile raf = null;  
  137.             try {  
  138.                 // 检查文件夹是否存在,如果不存在就创建   
  139.                 File dir = new File(mLocalPath);  
  140.                 if (!dir.exists()) {  
  141.                     dir.mkdirs();  
  142.                 }  
  143.   
  144.                 File file = new File(mLocalPath, mLocalName);  
  145.                 if (file.exists()) {  
  146.                     // downloadedSize = file.length();   
  147.                     // raf.seek(downloadedSize);   
  148.                     file.delete();  
  149.                 }  
  150.                 raf = new RandomAccessFile(file, "rw");  
  151.   
  152.                 URL url = new URL(mDownloadUrl);  
  153.                 HttpURLConnection urlConnection = (HttpURLConnection) url  
  154.                         .openConnection();  
  155.                 urlConnection.setRequestMethod("GET");  
  156.                 // urlConnection   
  157.                 // .setRequestProperty("RANGE", "bytes=" + downloadedSize);   
  158.                 urlConnection.setDoOutput(true);  
  159.                 urlConnection.connect();  
  160.                 inputStream = urlConnection.getInputStream();  
  161.                 mTotalSize = urlConnection.getContentLength();  
  162.                 byte[] buffer = new byte[1024];  
  163.                 int bufferLength = 0;  
  164.   
  165.                 // kb   
  166.                 long beginTime = System.currentTimeMillis();  
  167.                 long endTime = beginTime;  
  168.                 long size = 0;  
  169.                 while ((bufferLength = inputStream.read(buffer)) > 0) {  
  170.                     if (mAppId.equals(sAppId) || stop) {  
  171.                         inputStream.close();  
  172.                         inputStream = null;  
  173.                         sAppId = null;  
  174.                         return false;  
  175.                     }  
  176.                     raf.write(buffer, 0, bufferLength);  
  177.                     mDownloadedSize += bufferLength;  
  178.   
  179.                     size += bufferLength;  
  180.                     endTime = System.currentTimeMillis();  
  181.                     if (endTime - beginTime >= 1000) {  
  182.                         // kb   
  183.                         mDownloadedSpeed = size;  
  184.                         mProgress = (int) (100 * mDownloadedSize / mTotalSize);  
  185.                         publishProgress(flag);  
  186.   
  187.                         beginTime = endTime;  
  188.                         size = 0;  
  189.                     }  
  190.   
  191.                 }  
  192.                 raf.close();  
  193.                 raf = null;  
  194.                 inputStream.close();  
  195.                 inputStream = null;  
  196.             } catch (Exception e) {  
  197.                 e.printStackTrace();  
  198.                 return false;  
  199.             } finally {  
  200.                 try {  
  201.                     if (raf != null) {  
  202.                         raf.close();  
  203.                         raf = null;  
  204.                     }  
  205.                     if (inputStream != null) {  
  206.                         inputStream.close();  
  207.                         inputStream = null;  
  208.                     }  
  209.                 } catch (IOException e) {  
  210.                     e.printStackTrace();  
  211.                 }  
  212.             }  
  213.   
  214.             return true;  
  215.         }  
  216.   
  217.         @Override  
  218.         public void run() {  
  219.             execute();  
  220.         }  
  221.     }  
  222.   
  223.     private void execute(Runnable runnable) {  
  224.         sExecutorService.execute(runnable);  
  225.     }  
  226.   
  227.     @Override  
  228.     public void onCreate() {  
  229.         super.onCreate();  
  230.         stop = false;  
  231.   
  232.     }  
  233.   
  234.     @Override  
  235.     public void onDestroy() {  
  236.         super.onDestroy();  
  237.         stop = true;  
  238.         mHandler.removeMessages(0);  
  239.         new Thread() {  
  240.             @Override  
  241.             public void run() {  
  242.                 FileUtils.deleteFiles(new File(FileUtils.SDCARD_BACKUP_APP));  
  243.             }  
  244.         }.start();  
  245.     }  
  246.   
  247.     @Override  
  248.     public int onStartCommand(Intent intent, int flags, int startId) {  
  249.         Log.v("DownloadService""onStartCommand.intent=" + intent);  
  250.         if (intent != null) {  
  251.             String appId = intent.getStringExtra("appId");  
  252.             String appName = intent.getStringExtra("appName");  
  253.             String downloadUrl = intent.getStringExtra("downloadUrl");  
  254.             long fileSize = intent.getLongExtra("fileSize"0);  
  255.             boolean stop = intent.getBooleanExtra("stop"false);  
  256.             if (!TextUtils.isEmpty(appId)) {  
  257.                 if (stop) {  
  258.                     sAppId = appId;  
  259.                 } else {  
  260.                     if (sExecutorService.getActiveCount() == 3) {  
  261.                         // 超出最大线程池数,提示稍后下载   
  262.                         Intent intent2 = new Intent(ACTION_DOWNLOAD);  
  263.                         intent2.putExtra("appId", appId);  
  264.                         intent2.putExtra("state""");  
  265.                         intent2.putExtra("speed""");  
  266.                         intent2.putExtra("progress"0);  
  267.                         // -2等待-1失败,0执行前, 1执行中 ,2成功   
  268.                         intent2.putExtra("flag", -2);  
  269.                         mHandler.sendMessage(mHandler.obtainMessage(0, intent2));  
  270.                     } else {  
  271.                         DownloadTask task = new DownloadTask(appId, appName,  
  272.                                 downloadUrl, fileSize);  
  273.                         execute(task);  
  274.                     }  
  275.                 }  
  276.             }  
  277.         }  
  278.         return super.onStartCommand(intent, flags, startId);  
  279.     }  
  280.   
  281.     @Override  
  282.     public IBinder onBind(Intent intent) {  
  283.         return null;  
  284.     }  
  285. }  
package com.exam;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import com.exam.utils.FileUtils;

public class DownloadService extends Service {

	private boolean stop;
	public static final String ACTION_DOWNLOAD = "com.exam.downloadservice";
	private static ThreadPoolExecutor sExecutorService = (ThreadPoolExecutor) Executors
			.newFixedThreadPool(3);
	private String sAppId;
	private Handler mHandler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			int what = msg.what;
			if (stop) {
				return;
			}
			if (what == 0) {
				if (msg.obj != null && msg.obj instanceof Intent) {
					Intent intent = (Intent) msg.obj;
					DownloadService.this.sendBroadcast(intent);
				}
			} else if (what == 2) {
				try {
					Intent instIntent = new Intent(Intent.ACTION_VIEW);
					instIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					instIntent.setDataAndType(
							Uri.fromFile(new File(msg.obj.toString())),
							"application/vnd.android.package-archive");
					startActivity(instIntent);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	};

	private class DownloadTask implements Runnable {
		private String mLocalPath = FileUtils.SDCARD_BACKUP_APP;
		private String mAppId;
		private String mDownloadUrl;
		private String mLocalName = "tmp.apk";
		private String mFileSize;
		/**
		 * -2等待-1失败,0执行前, 1执行中 ,2成功
		 */
		// private int flag = -2;

		private long mTotalSize;
		private long mDownloadedSize;
		private long mDownloadedSpeed;
		private int mProgress;

		public DownloadTask(String appId, String appName, String downloadUrl,
				long size) {
			this.mAppId = appId;
			this.mLocalName = appName + ".apk";
			this.mDownloadUrl = downloadUrl;
			this.mFileSize = FileUtils.getFormatSize(size);
		}

		protected void onPreExecute(int flag) {
			mTotalSize = 0;
			mDownloadedSize = 0;
			mDownloadedSpeed = 1;
			mProgress = 0;
			publishProgress(flag);
		}

		protected void onPostExecute(int flag) {
			publishProgress(flag);
		}

		private void publishProgress(int flag) {
			if (mProgress > 100) {
				mProgress = 100;
			}
			if (mProgress < 0) {
				mProgress = 0;
			}

			StringBuffer bufferState = new StringBuffer();
			bufferState.append(FileUtils.getFormatSize(mDownloadedSize))
					.append("/").append(mFileSize);

			StringBuffer bufferSpeed = new StringBuffer();
			bufferSpeed.append(FileUtils.getFormatSize(mDownloadedSpeed))
					.append("/s");

			Intent intent = new Intent(ACTION_DOWNLOAD);
			intent.putExtra("appId", mAppId);
			intent.putExtra("state", bufferState.toString());
			intent.putExtra("speed", bufferSpeed.toString());
			intent.putExtra("progress", this.mProgress);
			// -2等待-1失败,0执行前, 1执行中 ,2成功
			intent.putExtra("flag", flag);
			mHandler.sendMessage(mHandler.obtainMessage(0, intent));
			if (flag == 2) {
				String path = FileUtils.SDCARD_BACKUP_APP + mLocalName;
				mHandler.sendMessage(mHandler.obtainMessage(2, path));
			}
		}

		public void execute() {
			int flag = 0;
			onPreExecute(flag);
			flag = 1;
			boolean result = downloadFile(flag);
			if (result) {
				flag = 2;
			} else {
				flag = -1;
			}
			onPostExecute(flag);
		}

		private boolean downloadFile(int flag) {
			InputStream inputStream = null;
			RandomAccessFile raf = null;
			try {
				// 检查文件夹是否存在,如果不存在就创建
				File dir = new File(mLocalPath);
				if (!dir.exists()) {
					dir.mkdirs();
				}

				File file = new File(mLocalPath, mLocalName);
				if (file.exists()) {
					// downloadedSize = file.length();
					// raf.seek(downloadedSize);
					file.delete();
				}
				raf = new RandomAccessFile(file, "rw");

				URL url = new URL(mDownloadUrl);
				HttpURLConnection urlConnection = (HttpURLConnection) url
						.openConnection();
				urlConnection.setRequestMethod("GET");
				// urlConnection
				// .setRequestProperty("RANGE", "bytes=" + downloadedSize);
				urlConnection.setDoOutput(true);
				urlConnection.connect();
				inputStream = urlConnection.getInputStream();
				mTotalSize = urlConnection.getContentLength();
				byte[] buffer = new byte[1024];
				int bufferLength = 0;

				// kb
				long beginTime = System.currentTimeMillis();
				long endTime = beginTime;
				long size = 0;
				while ((bufferLength = inputStream.read(buffer)) > 0) {
					if (mAppId.equals(sAppId) || stop) {
						inputStream.close();
						inputStream = null;
						sAppId = null;
						return false;
					}
					raf.write(buffer, 0, bufferLength);
					mDownloadedSize += bufferLength;

					size += bufferLength;
					endTime = System.currentTimeMillis();
					if (endTime - beginTime >= 1000) {
						// kb
						mDownloadedSpeed = size;
						mProgress = (int) (100 * mDownloadedSize / mTotalSize);
						publishProgress(flag);

						beginTime = endTime;
						size = 0;
					}

				}
				raf.close();
				raf = null;
				inputStream.close();
				inputStream = null;
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			} finally {
				try {
					if (raf != null) {
						raf.close();
						raf = null;
					}
					if (inputStream != null) {
						inputStream.close();
						inputStream = null;
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			return true;
		}

		@Override
		public void run() {
			execute();
		}
	}

	private void execute(Runnable runnable) {
		sExecutorService.execute(runnable);
	}

	@Override
	public void onCreate() {
		super.onCreate();
		stop = false;

	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		stop = true;
		mHandler.removeMessages(0);
		new Thread() {
			@Override
			public void run() {
				FileUtils.deleteFiles(new File(FileUtils.SDCARD_BACKUP_APP));
			}
		}.start();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.v("DownloadService", "onStartCommand.intent=" + intent);
		if (intent != null) {
			String appId = intent.getStringExtra("appId");
			String appName = intent.getStringExtra("appName");
			String downloadUrl = intent.getStringExtra("downloadUrl");
			long fileSize = intent.getLongExtra("fileSize", 0);
			boolean stop = intent.getBooleanExtra("stop", false);
			if (!TextUtils.isEmpty(appId)) {
				if (stop) {
					sAppId = appId;
				} else {
					if (sExecutorService.getActiveCount() == 3) {
						// 超出最大线程池数,提示稍后下载
						Intent intent2 = new Intent(ACTION_DOWNLOAD);
						intent2.putExtra("appId", appId);
						intent2.putExtra("state", "");
						intent2.putExtra("speed", "");
						intent2.putExtra("progress", 0);
						// -2等待-1失败,0执行前, 1执行中 ,2成功
						intent2.putExtra("flag", -2);
						mHandler.sendMessage(mHandler.obtainMessage(0, intent2));
					} else {
						DownloadTask task = new DownloadTask(appId, appName,
								downloadUrl, fileSize);
						execute(task);
					}
				}
			}
		}
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
}

转载地址:http://blog.youkuaiyun.com/hknock/article/details/22884325



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值