上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
1.1.5 下载服务端的apk文件
当程序连接服务器检测到新版本并弹出升级对话框的提示时,我们可以单击“下载”按钮将服务器端的最新apk下载到本地的Sdcard上。单击“取消”按钮时,直接进入当前版本程序的主界面。显示升级提示对话框的核心代码如下:
/** * 显示升级提示的对话框 */ protected void showUpdateDialog() { //创建对话框的构造器 AlertDialog.Builder builder = new Builder(this); //设置对话框的提示内容 builder.setIcon(getResources().getDrawable(R.drawable.notification)); //设置升级标题 builder.setTitle("升级提示"); //设置升级提示内容 builder.setMessage(info.getDescription()); //创建下载进度条 pd = new ProgressDialog(SplashActivity.this); //设置进度条在显示时的提示消息 pd.setMessage("正在下载");
//指定显示下载进度条为水平形状 pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //设置升级按钮 builder.setPositiveButton("升级", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { Log.i(TAG, "升级,下载" + info.getApkurl()); //判断Sdcard是否存在 if (Environment.MEDIA_MOUNTED.equals(Environment .getExternalStorageState())) { pd.show();//显示下载进度条 //开启子线程下载apk new Thread() { public void run() { //获取服务端新版本apk的下载地址 String path = info.getApkurl(); //获取最新apk的文件名 String filename = DownLoadUtil.getFilename(path); //在Sdcard上创建一个文件 File file = new File(Environment .getExternalStorageDirectory(), filename); //得到下载后的apk文件 file = DownLoadUtil.getFile(path, file.getAbsolutePath(), pd); if (file != null) { //向主线程发送下载成功的消息 Message msg = Message.obtain(); msg.what = DOWNLOAD_SUCCESS; msg.obj = file; handler.sendMessage(msg); } else { //向主线程发送下载失败的消息 Message msg = Message.obtain(); msg.what = DOWNLOAD_ERROR; handler.sendMessage(msg); } pd.dismiss();//下载结束后,将下载的进度条关闭 }; }.start(); } else { Toast.makeText(getApplicationContext(), "sd卡不可用", 1).show(); loadMainUI();//进入程序主界面 } } }); builder.setNegativeButton("取消", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) { loadMainUI(); } }); builder.create().show(); }
说明:由于该方法在主线程中执行,而下载文件又是一个比较耗时的操作,所以我们开启一个新的线程来执行该任务。而且,在下载完成后,我们必须调用 pd 对象的 dismiss()方法,否则该进度条不会自动消失。
下载apk的工具类位于“com.guoshisp.mobilesafe.utils”包下的 ownLoadUtil,该类的具体实现代码如下:
package com.guoshisp.mobilesafe.utils; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import android.app.ProgressDialog; import android.content.Context; import android.os.Environment; /** * 下载的工具类:下载文件的路径;下载文件后保存的路径;关心进度条;上、下文 */ public class DownLoadUtil { /** * 下载一个文件 * * @param urlpath * 路径 * @param filepath * 保存到本地的文件路径 * @param pd * 进度条对话框 * @return 下载后的apk */ public static File getFile(String urlpath, String filepath, ProgressDialog pd) { try { URL url = new URL(urlpath); File file = new File(filepath); FileOutputStream fos = new FileOutputStream(file); HttpURLConnection conn = (HttpURLConnection) url. openConnection();
//下载的请求是GET方式,conn的默认方式也是GET请求 conn.setRequestMethod("GET"); //服务端的响应时间 conn.setConnectTimeout(5000); //获取服务端的文件总长度 int max = conn.getContentLength(); //将进度条的最大值设置为要下载的文件的总长度 pd.setMax(max); //获取要下载的apk的文件的输入流 InputStream is = conn.getInputStream(); //设置一个缓存区 byte[] buffer = new byte[1024]; int len = 0; int process = 0; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); //每读取一次输入流,就刷新一次下载进度 process+=len; pd.setProgress(process); //设置睡眠时间,便于观察下载进度 Thread.sleep(30); } //刷新缓存数据到文件中 fos.flush(); //关流 fos.close(); is.close(); return file; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取一个路径中的文件名。例如:mobilesafe.apk * * @param urlpath * @return */ public static String getFilename(String urlpath) { return urlpath .substring(urlpath.lastIndexOf("/") + 1, urlpath.length()); } }
由于涉及对Sdcard的操作,所以我们需要在清单文件中配置相应的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_ FILESYSTEMS" />
当再次运行并单击“升级”按钮时,界面效果如图1-10所示。
图1-10