实现思路:
- 获取文件的输入流
- 把输入流读入到缓存流中,并累积记录流的长度
- 通过Handler机制将长度传递给UI线程
- ProgressBar接到到读取长度以及文件总长度进行UI的更新。
界面效果:
布局代码:
<?xml version="1.0" encoding="utf-8"?>
<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.ycw.progresspro.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始下载"
android:id="@+id/btn_start"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progressBar"
android:max="100"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="已下载"
android:id="@+id/textView"
android:layout_below="@+id/progressBar"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="0%"
android:id="@+id/percent"
android:layout_below="@+id/progressBar"
android:layout_toRightOf="@+id/textView"
android:layout_toEndOf="@+id/textView" />
</RelativeLayout>
添加权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
PS:如果运行环境API>23的话(Android6.0及之后),需要动态申请权限,详情可以查看我的另一篇博客关于Android6.0读写文件权限问题
实现代码:
代码里面有非常详细的注释
public class MainActivity extends AppCompatActivity {
private static final int DOWNLOAD_FILE_CODE = 100001 ;
private static final String DOWNLOAD_URL ="http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk" ;
private static final int DOWNLOAD_FILE_FAILE_CODE = 100002;
private Button StartDownload;
private TextView percent;
private ProgressBar progressBar;
private Handler handler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
StartDownload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//执行下载程序
new Thread(new Runnable() {
@Override
public void run() {
download(DOWNLOAD_URL);
}
}).start();
}
});
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 100001:
//更新进度条
progressBar.setProgress((Integer) msg.obj);
percent.setText(String.valueOf(msg.arg1)+"%");
if (progressBar.getProgress()==100){
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
break;
case 100002:
Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
break;
}
}
};
}
private void download(String AppUrl) {
//实例化URL对象
try {
URL url = new URL(AppUrl);
//实例化一个URLConnection对象
URLConnection conn = url.openConnection();
//获取下载路径
String path = Environment.getExternalStorageDirectory()
+ File.separator + "ZerGen" + File.separator;
//创建目录
File PathName = new File(path);
//如果PathName不存在的话 就创建这个目录
if(!PathName.exists()){
PathName.mkdir();
}
//有了目录之后,就需要一个文件名
String ApkName = path+"ZerGen.apk";
//判断一下这个文件是否已经存在,存在的话就删除它
File ApkFile = new File(ApkName);
if(ApkFile.exists()){
ApkFile.delete();
}
//获取文件的总长度
int ContentLength = conn.getContentLength();
//获取输入流
InputStream in = conn.getInputStream();
byte[] b = new byte[1024];
int DownloadLength = 0; //用于保存实时下载长度
int len =0;
OutputStream out = new FileOutputStream(ApkName);
while((len = in.read(b))>-1){
out.write(b,0,len);
DownloadLength += len;
//将实时的下载长度传给UI线程
Message message=handler.obtainMessage();
message.what =DOWNLOAD_FILE_CODE;
message.obj = DownloadLength*100/ContentLength;
message.arg1 = DownloadLength*100/ContentLength;
handler.sendMessage(message);
}
} catch (java.io.IOException e) {
downloadfail();
e.printStackTrace();
}
}
private void downloadfail() {
Message message=handler.obtainMessage();
message.what =DOWNLOAD_FILE_FAILE_CODE;
handler.sendMessage(message);
}
private void initView() {
StartDownload = (Button) findViewById(R.id.btn_start);
percent = (TextView) findViewById(R.id.percent);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
}
}
最终效果: