android多任务下载的状态更新
2014-04-03 17:25
351 查看
对于下载任务,通常需要实时的更新任务进度
一般而言,最直接的方式是使用AsyncTask对进度进行实时更新
但对于多个任务并且界面切换后,AsyncTask并不能满足要求
此时需要使用service,进行独立的下载操作,而进度的更新可以通过不断的广播来更新需要展示的进度
代码片段
一般而言,最直接的方式是使用AsyncTask对进度进行实时更新
但对于多个任务并且界面切换后,AsyncTask并不能满足要求
此时需要使用service,进行独立的下载操作,而进度的更新可以通过不断的广播来更新需要展示的进度
代码片段
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; } }
相关文章推荐
- [Android学习笔记]SeekBar的使用
- 移植SDL到android
- 有些Android手机拍照上传被旋转90度的处理方法
- Android初试--自定义ListView的使用
- Android XML解析
- Android中的View事件传递机制
- Android多媒体分析(三)通过MediaStore获取Audio信息
- android定时唤醒_消息通知
- 【TimerTask】android TimerTask 的简单应用
- Android 存取数据之SharedPreferences
- Android使用TableLayout之固定表头(标题栏)
- Android编程之手绘 ,画图
- Android软键盘与界面
- android静默安装apk
- Android init进程启动
- android:backgroundDimEnabled的作用
- android自学总结3
- android应用开发之intent的妙用一
- [Android学习笔记]ScrollView的使用
- 【自定义Android带图片和文字的ImageButton】