四. 下载安装apk文件
1. 更新对话框
(1) 更新流程
先弹出更新对话框提示, 点击确定就弹出进度条对话框, 下载apk文件 . 如果点击取消, 直接进入主界面
更新对话框 : 这是一个AlertDialog , 先创建builder, 然后设置标题, 显示内容, 设置积极消极按钮, 创建对话框 之后显示对话框;
进度条对话框 : 这是一个ProgressDialog, 直接使用new创建, 设置信息与显示样式, 最后显示对话框.
(2) 创建对话框流程
创建一个对话框的流程 :
a. 创建builder对象 : Builder builder = new Builder(context);
b. 设置标题 : builder.setTittle("");
c. 设置显示信息 : builder.setMessage("");
d. 设置按钮 : builder.setPositiveButton("", onClickListener);
e. 创建对话框 : Dialog dialog = builder.create();
f. 显示对话框 : dialog.show();
创建进度条对话框流程 :
a. 创建进度条对话框 : ProgressDialog progressDialog = new ProgressDialog(context);
b. 设置进度条对话框样式 : progressDialog.setProgressStyle();
c. 设置显示信息 : progressDialog.setMessage();
d. 显示对话框 : progressDialog.show();
(3) 源码
/** * 弹出更新对话框 * * a. 创建builder对象 * b. 设置标题 * c. 设置对话框显示信息 * d. 设置该对话框不可回退, 如果回退的话就会卡在本界面 * e. 设置确定按钮 * f. 设置取消按钮 * g. 创建对话框 * h. 显示对话框 * * 确定按钮按下显示进度条对话框 * a. 创建一个进度条对话框 * b. 设置该对话框不能回退 * c. 设置进度条样式 * d. 设置进度条的信息 * e. 显示进度条对话框 * f. 开启一个线程, 下载apk文件 */ protected void showUpdateDialog() { //创建builder对象 AlertDialog.Builder builder = new AlertDialog.Builder(this); //设置标题 builder.setTitle(getString(R.string.update_dialog_tittle)); //设置对话框信息 builder.setMessage(updateInfo.getDescription()); //设置不可回退 builder.setCancelable(false); //设置确定按钮 builder.setPositiveButton(getString(R.string.confirm), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //创建进度条对话框 mPb = new ProgressDialog(SplashActivity.this); //设置进度条对话框不可回退 mPb.setCancelable(false); //设置进度条对话框样式 mPb.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //设置进度条对话框的信息 mPb.setMessage(getString(R.string.update_dialog_messsage)); //显示进度条对话框 mPb.show(); //开启显示进度条对话框线程 new Thread(new DownloadApkTask()).start(); } }); builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { loadMainUI(); } }); //创建更新信息提示对话框 mUpdateInfoDialog = builder.create(); //显示更新信息提示对话框 mUpdateInfoDialog.show(); }
2. 下载apk线程
/** * 在这个线程中主要执行downloadApk方法, 这个方法传入apk路径和进度条对话框 * 注意 : 下载的前提是sd卡的状态是挂载的 */ private final class DownloadApkTask implements Runnable{ public void run() { if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ try { SystemClock.sleep(2000); apkFile = downloadApk(SettingsFactory.readWebLoadUrl(getApplicationContext()) + UPDATE_FOLDER_DIRECTORY + updateInfo.url,mPb); Message msg = new Message(); msg.what = SUCCESS_DOWNLOAD_APK; mHandler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); Message msg = new Message(); msg.what = ERROR_DOWNLOAD_APK; mHandler.sendMessage(msg); } } } }
3. 下载apk核心方法
从网络下载文件流程 :
a. 创建URL对象 : 这个对象一般根据字符串地址创建, URL url = new URL(path);
b. 创建HttpURLConnection对象 : 这个对象根据URL对象创建, HttpURLConnection conn = (HttpURLConnection)url.openConnection();
c. 设置超时时间 : 单位是毫秒, conn.setConnectionTimeout(5000);
d. 设置请求方式 : conn.setRequestMethod("GET");
e. 成功连接 : 如果成功连接, 那么conn.getResponseCode()的值为200;
进度条对话框设置 :
a. 设置进度条最大值 : mProgressDialog.setMax(int max);
b. 设置进度条当前值 : mProgressDialog.setProgress(int curr);
/** * 下载apk更新文件 * * a. 根据SD卡路径创建文件对象, 这个文件用来保存下载的文件 * b. 创建URL对象 * c. 创建HttpUrlConnection对象 * d. 设置链接对象超时时间 * e. 设置请求方式 get * f. 如果请求成功执行下面的操作 * * g. 通过链接对象获取网络资源的大小 * h. 将文件大小设置给进度条对话框 * i. 获取输入流, 并且读取输入流信息 * j. 根据读取到的字节数, 将已经读取的数据设置给进度条对话框 */ public File downloadApk(String path,ProgressDialog pb) throws Exception{ //创建本地文件对象 File file = new File(Environment.getExternalStorageDirectory(), getFileName(path)); //创建HttpURL连接 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); if(conn.getResponseCode() == 200){ int max = conn.getContentLength(); //设置进度条对话框的最大值 pb.setMax(max); int count = 0; InputStream is = conn.getInputStream(); FileOutputStream fos = new FileOutputStream(file); byte[] buffer = new byte[1024]; int len = 0; while((len = is.read(buffer)) != -1){ fos.write(buffer, 0, len); //设置进度条对话框进度 count = count + len; pb.setProgress(count); } is.close(); fos.close(); } return file; } 4. 安装apk文件 /** * 安装apk文件流程 * * a. 设置Action : Intent.ACTION_VIEW. * b. 设置数据和类型 : 设置apk文件的uri 和 MIME类型 * c. 开启安装文件的Activity. */ protected void installApk() { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); startActivity(intent); } 五. 相关的源码 (1) 布局文件 splash.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/ivt_splash" android:id="@+id/splash_rl"> <ProgressBar android:id="@+id/pb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:layout_marginBottom="30dip"/> <TextView android:id="@+id/tv_version" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_above="@id/pb" android:layout_marginBottom="60dip" android:textSize="30sp" android:textColor="#17A6E8" android:text="version" /> </RelativeLayout>
(2) Activity页面切换动画
main_in.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:fromXDelta="100%p" android:toXDelta="0" android:fromYDelta="0" android:toYDelta="0" android:duration="200" /> </set> splash_out.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:fromXDelta="0" android:toXDelta="-100%p" android:fromYDelta="0" android:toYDelta="0" android:duration="200" /> </set> (3) SplashActivity源码 SplashActivity.java public class SplashActivity extends Activity { private static final String TAG = "SplashActivity"; public static final int ERROR_GET_UPDATEINOF = 0; public static final int SUCESS_GET_UPDATEINOF = 1; public static final int ERROR_DOWNLOAD_APK = 2; public static final int SUCCESS_DOWNLOAD_APK = 3; private static final String XML_FILE_DIRECTORY = "updateinfo.xml"; private static final String UPDATE_FOLDER_DIRECTORY = "/webupdate/"; private TextView tv_version; private PackageManager pm; private String version; private UpdateInfo updateInfo; private Dialog mUpdateInfoDialog; private ProgressDialog mPb; private File apkFile; private RelativeLayout splash_rl; private long time; private SharedPreferences sp; private int touchPositionX0; private int touchPositionX1; private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { /* * 获取更新信息错误 , 在断网或者获取信息出现异常执行 * 提示一下, 之后进入主界面 */ case ERROR_GET_UPDATEINOF: ToastHint.getInstance().showHint(R.string.fail_to_get_updateinfo); loadMainUI(); break; /* * 成功获取更新信息, 一般在成功从网上获取xml文件并解析出来 * 如果版本号相同, 说明不用更新, 直接进入主界面 * 如果版本号不同, 需要弹出更新对话框 */ case SUCESS_GET_UPDATEINOF: if(updateInfo.getVersion().equals(version)){ loadMainUI(); }else{ showUpdateDialog(); } break; /* * 下载apk文件出现错误, 中途断网 出现异常等情况 * 提示后进入主界面 */ case ERROR_DOWNLOAD_APK: mPb.dismiss(); ToastHint.getInstance().showHint(R.string.fail_to_get_apk); loadMainUI(); break; /* * 成功下载apk文件之后执行的操作 * 取消进度条对话框, 之后安装apk文件 */ case SUCCESS_DOWNLOAD_APK: mPb.dismiss(); installApk(); break; default: break; } }; };