主要任务
1.下载apk保存到sd卡指定目录
2.下载时显示下载的进度
3.下载完成后弹出对话框提示安装
分析过程:
- 联网操作不能在UI线程(主线程)进行 需要开启线程下载,为了效率我们这里采用异步线程(AsyncTask)。
- 异步下载的同时需要在主界面更新UI,所以利用接口回调设置一个DialogProgress的进度条展示。
- 下载完成提示安装。
下面是完整代码:
先创建异步任务执行下载操作
package com.android.download;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.os.AsyncTask;
import android.os.Environment;
/**
* 下载apk任务
* 泛型一:String:表示下载的URL
* 泛型二:Integer:每次读取进度条的返回值,用于界面更新
* 泛型三:String:表示返回值类型,返回被下载的apk文件 的路径,为启动apk安装做准备
*
*/
public class MyTask extends AsyncTask<String, Integer, String> {
public interface CallBack {
public void start(); //任务开始这里面应该弹出进度条对话框
public void updataProgress(int progress);//获取到更新的进度值为进度条对话框设置值
/**
* 下载完成,
*
* 1.对话框消失
*
* 2.启动安装apk界面,需要apk路径
*/
public void finish(String apkPath);
}
CallBack cb;
public MyTask(CallBack cb) {
super();
this.cb = cb;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
if (cb != null) {
cb.start();
}
}
@Override
protected String doInBackground(String... params) {
// 1.HttpURLConnection
HttpURLConnection conn = null;
String apkPath = null;
// 2.URL
try {
URL url = new URL(params[0]);
// 3.url.openConnection
conn = (HttpURLConnection) url.openConnection();
// 4.InputStream
InputStream in = conn.getInputStream();
// 获取该文件的总长度
int total = conn.getContentLength();
// 5.获取保存文件的路径及文件 名/sdcard/abcdefg/tmp.apk
String path_sdcard = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/abcdefg";
File fileParent = new File(path_sdcard);
// 判断该目录是否存在,如果不存在,创建该目录
if (!fileParent.exists()) {
// 创建目录
fileParent.mkdirs();
}
// 6.创建File对象,再拿到OutputStream
File file = new File(path_sdcard, "tmp.apk");
//用来返回该apk路径
apkPath = file.getAbsolutePath();
OutputStream out = new FileOutputStream(file);
// 7.创建byte[] buffer
byte[] buffer = new byte[4096];
// 8.inputStream==>OutputStream
// 循环读写时,应该要把每次读入的长度进行累加,再把累加的值与总长度除一下,得到百分比用于更新进度条的值
int sum = 0;
int len = 0;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
// 累加
sum = sum + len;
// 计算百分比
int per = (int) (sum * 100f / total);
// 发布进度值
publishProgress(per);
}
out.flush();
// 收尾
out.close();
in.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();
}
}
// 返回当前被保存的apk的绝对路径
return apkPath;
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
if (cb != null) {
cb.updataProgress(values[0]);
}
}
/*
* result表示的是apk的路径
*/
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (cb != null) {
cb.finish(result);
}
}
}
package com.android.download;
import java.io.File;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import com.android.download.MyTask.CallBack;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
ProgressDialog pd;
// 点击下载apk
public void downlaod(View view) {
// 1.启动下载任务
MyTask task = new MyTask(new CallBack() {
@Override
public void updataProgress(int progress) {
pd.setProgress(progress);
}
@Override
public void start() {
pd = new ProgressDialog(MainActivity.this);
pd.setTitle("下载提示");
pd.setMessage("正在下载apk...");
pd.setCancelable(false); //设置下载过程对话框不能消失
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.show();
}
@Override
public void finish(String apkPath) {
// 消失对话框
pd.dismiss();
// 启动安装
installApk(apkPath);
}
});
task.execute("apkPath");//需要下载的apk链接
}
/**
* 安装apk
*
* @param url
*/
private void installApk(String apkFilePath) {
File apkfile = new File(apkFilePath);
if (!apkfile.exists()) {
return;
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + apkfile.toString()),
"application/vnd.android.package-archive");
startActivity(i);
}
}
xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.day012_downloadapk.MainActivity" >
<Button
android:onClick="downlaod"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="下载apk" />
</RelativeLayout>
不要忘了添加联网权限和读写sd卡权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
界面效果图:
最后读者可以自己加个判断文件是否已经存在 如果已经存在启动安装即可