Android下载apk并安装,实时刷新进度条
2015-09-12 23:23
537 查看
一个从服务器端下载apk 的小例子。下载过程中会实时的刷新进度条。这里使用了两种方法,一种是利用第三方的框架xutils中的HttpUtils来进行下载的,另一种是自己写的一个单线程下载的方法。
注意:
1、自己开子线程下载时不要在子线程中操作和UI有关的事情,否则会报错。这里利用发handler来对UI操作,保证在主线程(UI线程中)来操作刷新UI;
2、获取下载apk包大小的时候也要注意HttpURLConnection.getContentLength()获取的size跟下载下来的file的legth有可能不相等,这个和服务器端有关,也有可能getContentLength()返回的结果是-1.原因是:HttpURLConnection跟服务交互采用了"gzip"压缩。所以下载的fileLegth > HttpURLConnection.getContentLength().
api上也不推荐是用该方法来验证文件的完整性。可目前项目有不能修改服务器。通过继续研究api发现这种gzip压缩方式是可以取消的。取消办法这http
request的head中设置如下参数即可:urlConnection.setRequestProperty("Accept-Encoding", "identity");
至此基本上面诡异的问题修复。2.2以上的版本默认都是采用压缩优化希望大家注意。
主要的代码如下:
如果需要源码可以在此下载:
点击下载源码
注意:
1、自己开子线程下载时不要在子线程中操作和UI有关的事情,否则会报错。这里利用发handler来对UI操作,保证在主线程(UI线程中)来操作刷新UI;
2、获取下载apk包大小的时候也要注意HttpURLConnection.getContentLength()获取的size跟下载下来的file的legth有可能不相等,这个和服务器端有关,也有可能getContentLength()返回的结果是-1.原因是:HttpURLConnection跟服务交互采用了"gzip"压缩。所以下载的fileLegth > HttpURLConnection.getContentLength().
api上也不推荐是用该方法来验证文件的完整性。可目前项目有不能修改服务器。通过继续研究api发现这种gzip压缩方式是可以取消的。取消办法这http
request的head中设置如下参数即可:urlConnection.setRequestProperty("Accept-Encoding", "identity");
至此基本上面诡异的问题修复。2.2以上的版本默认都是采用压缩优化希望大家注意。
主要的代码如下:
<pre name="code" class="java">package cn.hjking.mydownloadeapkdemo; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.DecimalFormat; import android.app.Activity; import android.app.AlertDialog; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import cn.hjking.mydownloadapkdemo.R; import com.lidroid.xutils.HttpUtils; import com.lidroid.xutils.exception.HttpException; import com.lidroid.xutils.http.HttpHandler; import com.lidroid.xutils.http.ResponseInfo; import com.lidroid.xutils.http.callback.RequestCallBack; public class MainActivity extends Activity { private Activity act; private HttpHandler httpHandler; private AlertDialog downloadDialog;//正在下载的对话框 private TextView tvCur;//当前下载的百分比 private ProgressBar pb;//下载的进度条 private TextView tvCanCel;//停止下载 private TextView tvHidden;//隐藏对话框的按钮 private int contentLength;//要下载文件的大小 private boolean isDownloading = false;//是否正在下载 private boolean isCancel = false;//是否取消升级 private DecimalFormat df = new DecimalFormat("###.00");//设置结果保留两位小数 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); act = this; } /** * 打开下载对话框的按钮单击事件 * @param v */ public void showDialog(View v){ if(isDownloading){ //如果正在下载,显示正在下载的对话框 if(!downloadDialog.isShowing()){ downloadDialog.show(); } return; } isCancel = false;//设置当前没有进行取消下载 AlertDialog.Builder adb = new AlertDialog.Builder(this); final AlertDialog alertDialog = adb.create(); View view = View.inflate(this, R.layout.dialog_layout, null); alertDialog.setView(view, 0, 0, 0, 0); TextView tvCancle = (TextView) view.findViewById(R.id.cancle_tv); TextView tvOk = (TextView) view.findViewById(R.id.ok_tv); tvCancle.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { alertDialog.dismiss(); } }); tvOk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 开始下载 // downLoadApk();//利用第三方框架下载 MyDownload();//自己写的单线程下载方法 alertDialog.dismiss(); } }); alertDialog.show(); } /** * * 下载apk利用第三方框架xutils下载 */ protected void downLoadApk() { //判断sd卡是否存在。下载的文件存放至sd卡中 if(!isSDcardExist()){ Toast.makeText(this, "SD卡不存在,下载失败", 1).show(); return; } HttpUtils httpUtils = new HttpUtils(); String downloadUrl = "http://www.online-cmcc.com/gfms/app/apk/4GTraffic2MM.apk"; final String target = getDowloadPath() + File.separator +"4GTraffic2MM.apk"; httpHandler = httpUtils.download(downloadUrl, target, new RequestCallBack<File>() { @Override public void onSuccess(ResponseInfo<File> arg0) { Toast.makeText(act, "下载成功", 1).show(); isDownloading = false; if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } InstallAPK(target); } @Override public void onFailure(HttpException arg0, String arg1) { Toast.makeText(act, "访问服务器失败", 1).show(); if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } isDownloading = false; } @Override public void onStart() { super.onStart(); showDownloadDialog(); tvCanCel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //停止下载 // httpHandler.stop(); httpHandler.cancel(); if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } isDownloading = false; } }); tvHidden.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } } }); System.out.println("onStart"); } @Override public void onLoading(long total, long current, boolean isUploading) { super.onLoading(total, current, isUploading); isDownloading = true; pb.setMax((int)total); pb.setProgress((int)current); tvCur.setText(df.format((float)current/(float)total * 100) + "%"); if(current == total){ pb.setProgress(pb.getMax()); } } }); } /** * 自己写的一个单线程下载 * 如果想要刷新要发handler(保证在UI线程中), * 利用状态isDownloading或isCancel来判断当前是否停止下载等操作 */ private void MyDownload(){ final String downloadUrl = "http://www.online-cmcc.com/gfms/app/apk/4GTraffic2MM.apk"; if(!isSDcardExist()){ Toast.makeText(act, "SD卡不可用", 1).show(); return; } final String filePath = getDowloadPath() + File.separator +"4GTraffic2MM.apk"; //自己开线程下载 new Thread(){ private InputStream inputStream; private FileOutputStream fos; public void run() { try { URL url = new URL(downloadUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(30000); //http请求不要gzip压缩,否则获取的文件大小可以小于文件的实际大小 conn .setRequestProperty("Accept-Encoding", "identity"); int responseCode = conn.getResponseCode(); if(responseCode == 200){ inputStream = conn.getInputStream(); File file = new File(filePath); fos = new FileOutputStream(file); contentLength = conn.getContentLength(); System.out.println("文件的大小::" + contentLength); int fileLengthFromHeader = Integer.parseInt(conn.getHeaderField("Content-Length")); System.out.println("根据头文件获取文件的大小::" + fileLengthFromHeader); //子线程不能显示和刷新UI Message msg = Message.obtain(); msg.what = SHOWDOWNLOADDIALOG; handler.sendMessage(msg); byte[] buffer = new byte[1024]; int len = 0; while(((len = inputStream.read(buffer)) != -1) && !isCancel ){ isDownloading = true; fos.write(buffer, 0, len); int curlength = (int) file.length(); Message updateMsg = Message.obtain(); updateMsg.what = UPDATEDOWNLOADDIALOG; updateMsg.obj = curlength; handler.sendMessage(updateMsg); System.out.println("file.length()::" + curlength); } if(file.length() == contentLength){ //下载完成 Message finishedMsg = Message.obtain(); finishedMsg.what = DOWNLOADFINISHED; finishedMsg.obj = filePath; handler.sendMessage(finishedMsg); } }else{ Toast.makeText(act, "访问服务器失败", 1).show(); if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } isDownloading = false; } } catch (MalformedURLException e) { e.printStackTrace(); System.out.println("MalformedURLException:" + e.getMessage()); } catch (IOException e2) { e2.printStackTrace(); System.out.println("IOException:" + e2.getMessage()); }finally{ try { if(inputStream != null){ inputStream.close(); } if(fos != null){ fos.close(); } } catch (IOException e) { e.printStackTrace(); System.out.println("IOException:" + e.getMessage()); } } }; }.start(); } /** * 显示正在下载的对话框 * */ private void showDownloadDialog(){ AlertDialog.Builder adb = new AlertDialog.Builder(act); downloadDialog = adb.create(); View view = View.inflate(act, R.layout.download_dialog_layout, null); downloadDialog.setView(view, 0, 0, 0, 0); tvCur = (TextView) view.findViewById(R.id.tv_cursize); tvCanCel = (TextView) view.findViewById(R.id.tv_cancel); tvHidden = (TextView) view.findViewById(R.id.tv_hidden); pb = (ProgressBar) view.findViewById(R.id.download_pb); downloadDialog.show(); } private final int SHOWDOWNLOADDIALOG = 88; private final int UPDATEDOWNLOADDIALOG = 99; private final int DOWNLOADFINISHED = 66; /** * 子线程不能刷新UI需要在这里处理 */ private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case SHOWDOWNLOADDIALOG://显示正在下载的对话框 showDownloadDialog(); pb.setMax(contentLength); tvCanCel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //取消下载 isCancel = true; isDownloading = false; if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } } }); tvHidden.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } } }); break; case UPDATEDOWNLOADDIALOG://刷新正在下载对话框的内容 int curSize = (int)msg.obj; pb.setProgress(curSize); tvCur.setText(df.format((float)curSize / (float)contentLength * 100) + "%"); break; case DOWNLOADFINISHED://下载完成后进行的操作 Toast.makeText(act, "下载成功", 1).show(); isDownloading = false; if(downloadDialog.isShowing()){ downloadDialog.dismiss(); } InstallAPK((String) msg.obj); break; default: break; } }; }; /** * * 判断sd卡是否存在 * @return */ private boolean isSDcardExist(){ return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } private String getDowloadPath(){ return Environment.getExternalStorageDirectory().getAbsolutePath(); } /** * 安装apk * @param filePath */ private void InstallAPK(String filePath){ Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse("file://" + filePath),"application/vnd.android.package-archive"); startActivity(i); } }
如果需要源码可以在此下载:
点击下载源码
相关文章推荐
- Android学习记录:获取联系人
- Android SQLiteOpenHelper onUpgrade使用注意事项
- 浅谈Android的三种持久化技术之SharedPreferences存储
- android学习——View之二
- 第一行代码学习笔记-第一章 开始启程-1.android简介
- Android系统自带样式(android:theme)(转)
- Android学习之自定义view(三)
- Android 学习第15课,Android 开发的单元测试、及输出错误信息
- Android中获取屏幕相关信息(屏幕大小,状态栏、标题栏高度)
- Android 单线程下载与多线程下载
- Android:LayoutInflater介绍
- Android屏幕适配
- 2. Android系统结构
- Android0909<十四>(Service、Android线程)
- Android中AIDL使用例子
- Android 动画深入分析
- 如何在Android模拟器上安装apk文件
- android获取asset文件存到SD卡
- Glide图片加载器详解(PPT转录)
- android---AlertDialog对话框解析