具体实现通过单击一个按钮,将imooc.apk下载到手机上 storage/imooc/下
具体代码和运行结果如下:
DownloadActivity.java (主界面):
public class DownloadActivity extends Activity {
public static final int DOWNLOAD_MESSAGE_CODE = 10001;
private static final int DOWNLOAD_FAILURE_CODE = 10002;
public static final String APP_URL = "http://www.imooc.com/mobile/mukewang.apk";
private static final String TAG = "DownloadActivity";
private int contentLength;
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
/**
* 主线程
* 点击按钮
* 开启子线程下载
* 主线程更新进度条
*/
findViewById(R.id.download_apk).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//子线程执行网络请求
new Thread(new Runnable() {
@Override
public void run() {
download(APP_URL);
}
}).start();
}
});
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
final TextView errorText = (TextView) findViewById(R.id.fail_txt);
final TextView processText = (TextView) findViewById(R.id.progress);
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case DOWNLOAD_MESSAGE_CODE:
//更新进度
processText.setText(msg.arg1 + "/" + contentLength);
progressBar.setProgress((Integer) msg.obj);
break;
case DOWNLOAD_FAILURE_CODE:
errorText.setText("download Failed!");
}
}
};
}
private void download(String appUrl) {
try {
URL url = new URL(appUrl);
URLConnection urlConnection = url.openConnection();
InputStream is = urlConnection.getInputStream();
//获取文件总长度
contentLength = urlConnection.getContentLength();
//建立目录
String downloadFolderName = Environment.getExternalStorageDirectory()
+ File.separator + "imooc" + File.separator;
File file = new File(downloadFolderName);
if(!file.exists()){
file.mkdir();
Log.e(TAG, "no file");
}
String fileName = downloadFolderName + "imooc.apk";
//建立apk文件
File apkFile = new File(fileName);
if(apkFile.exists()){
apkFile.delete();
}
//记录下载进度
int downloadSize = 0;
byte[] bytes = new byte[1024];
int length = 0;
OutputStream os = new FileOutputStream(fileName);
while((length = is.read(bytes)) != -1){
os.write(bytes, 0, length);
downloadSize += length;
/**
* 更新 UI
*/
Message message = Message.obtain();
//通过message向UI线程发送进度条进度
message.obj = downloadSize * 100 / contentLength;
message.arg1 = downloadSize;
message.what = DOWNLOAD_MESSAGE_CODE;
mHandler.sendMessage(message);
}
is.close();
os.close();
Log.i(TAG, "success");
} catch (MalformedURLException e) {
notifyDownloadFailed();
e.printStackTrace();
} catch (IOException e) {
notifyDownloadFailed();
e.printStackTrace();
}
}
private void notifyDownloadFailed() {
Message message = Message.obtain();
message.what = DOWNLOAD_FAILURE_CODE;
mHandler.sendMessage(message);
}
}
具体运行结果如下:
在File Manager
主要的原理便是 利用 handler在子线程想UI线程发送message,在下载过程中UI线程收到message的进度信息进行ProgressBar更新。
但是handler定义为全局变量,可能引发内存泄漏。如下图:
定义为静态类就可避免内存泄漏的情况发生