对于下载任务,通常需要实时的更新任务进度
一般而言,最直接的方式是使用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;
- }
- }
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