Android--APK更新总结
来源:互联网 发布:人工智能要从娃娃抓起 编辑:程序博客网 时间:2024/05/15 07:07
以下内容部分来自网络资源,这里做了个小小的总结。
目前Android开发中一般采用的是CS模式,对于Apk的升级就需要有Server端支持。基本思路:我们将升级版本以及一个记录升级版本的配置文件(一般采用json array/Xml格式)放在服务器端,当客户端Client初始化时,如果检测到Server服务器端有更新的版本,也就是配置文件中的版本信息不同,那么就将在Server端的升级版本以Http方式连接,将其下载下来,然后调用android api接口进行升级。
这里我们以Xml为例:
客户端与服务端约定如下:
1,版本信息记录在服务器端的version.xml文件中;
2,客户端每次运行时,先从服务器获取version.xml文件,然后对比该文件中的版本信息version与当前客户端的version是否一致,如果不一致,弹出更新选择框,由用户决定是否更新,如果更新,则启动更新程序;
3,更新程序:客户端从制定的URL中获取APK下载到本地,更新进度,如果下载完毕,启动APK安装程序,同时,允许用户中途取消下载,取消安装。
基于上述约定即可编写程序。
下面介绍一下具体过程:
1,定义version.xml文件
<?xml version="1.0" encoding="UTF-8"?> <update> <version>2.0_20141230</version> <versionCode>2</versionCode> <updateTime>2014-12-30</updateTime> <apkName>Updatedemo.apk</apkName> <downloadURL>http://localhost:8080/UpdateDemo.apk</downloadURL> <updateinformation>Update to the new version</updateinformation> </update>
2,定义version实体类VersionInformation.java
package com.client.update;public class VersionInformation { //Discription of version private String mVersion; //Update time private String mUpdateTime; //Update url private String mDownloadURL; //Update information private String mUpdateInformation; //Version number private int mVersionCode; //Name of android application private String mApkName; public String getVersion() { return mVersion; } public void setVersion(String version) { this.mVersion = version; } public String getUpdateTime() { return mUpdateTime; } public void setUpdateTime(String updateTime) { this.mUpdateTime = updateTime; } public String getDownloadURL() { return mDownloadURL; } public void setDownloadURL(String downloadURL) { this.mDownloadURL = downloadURL; } public String getUpdateInfomation() { return mUpdateInformation; } public void setUpdateInfomation(String updateInfo) { this.mUpdateInformation = updateInfo; } public int getVersionCode() { return mVersionCode; } public void setVersionCode(int versionCode) { this.mVersionCode = versionCode; } public String getApkName() { return mApkName; } public void setApkName(String apkName) { this.mApkName = apkName; } }
3,定义version.xml解析类XMLParserUtils.java
package com.client.update;import java.io.IOException;import java.io.InputStream;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlPullParserException;import org.xmlpull.v1.XmlPullParserFactory;public class XMLParserUtils { //get VersionInformation entry from version.xml public static VersionInformation getUpdateInformation(InputStream is) { VersionInformation info = new VersionInformation(); try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser parser = factory.newPullParser(); parser.setInput(is, "UTF-8"); int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { switch (eventType) { case XmlPullParser.START_TAG: if ("version".equals(parser.getName())) { info.setVersion(parser.nextText()); } else if ("updateTime".equals(parser.getName())) { info.setUpdateTime(parser.nextText()); } else if ("updateTime".equals(parser.getName())) { info.setUpdateTime(parser.nextText()); } else if ("downloadURL".equals(parser.getName())) { info.setDownloadURL(parser.nextText()); } else if ("updateinformation".equals(parser.getName())) { info.setUpdateInfomation(parseTxtFormat(parser.nextText(), "##")); } else if ("apkName".equals(parser.getName())) { info.setApkName(parser.nextText()); } else if ("versionCode".equals(parser.getName())) { info.setVersionCode(Integer.parseInt(parser.nextText())); } break; case XmlPullParser.END_TAG: break; } eventType = parser.next(); } } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return info; } public static String parseTxtFormat(String data, String formatChar) { StringBuffer backData = new StringBuffer(); String[] txts = data.split(formatChar); for (int i = 0; i < txts.length; i++) { backData.append(txts[i]); backData.append("\n"); } return backData.toString(); } }
4,定义APK更新类UpdateManager.java
package com.client.update;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 android.app.AlertDialog;import android.app.Dialog;import android.app.AlertDialog.Builder;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.DialogInterface.OnClickListener;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.net.Uri;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.widget.ProgressBar;import android.widget.Toast;import com.tutor.update.R;public class UpdateManager {//Context private Context mContext;//Description of updateprivate String mUpdateInfo = null;//description of applicationprivate static String TAG = "UpdateAPKDemo";//Update url of applicationprivate String mApkUrl = null;//"http://softfile.3g.qq.com:8080/msoft/179/24659/43549/qq_hd_mini_1.4.apk";//url address of version.xmlprivate URL mDownloadUrl = null;//new version number private int mNewVersion = 0;//description of update dialogprivate Dialog mNoticeDialog;//description of download dialogprivate Dialog mDownloadDialog;//saving path for updated apk private static final String savePath = "/sdcard/"+TAG+"/"; //saving name for updated apk private static final String saveFileName = savePath + "UpdateAPKDemo.apk"; //display current process of loading private ProgressBar mProgressBar; //message for process updating private static final int DOWN_UPDATE = 1; //message for download completed private static final int DOWN_OVER = 2; //value of loading process private int mProgress; //thread for download private Thread downLoadThread; //switch for download private boolean mInteruptDownload = false; private Handler mHandler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what) {case DOWN_UPDATE:mProgressBar.setProgress(mProgress);break;case DOWN_OVER:installApk();break;default:break;} }; }; public UpdateManager(Context context) {this.mContext = context;} public void checkUpdateInfo(){if(updateInfo()) showNoticeDialog();elseToast.makeText(mContext, "No update information", Toast.LENGTH_SHORT).show();}public boolean updateInfo(){VersionInformation info = getVersionInfoFromServer();if(info!=null){mApkUrl = info.getDownloadURL();mUpdateInfo = info.getUpdateInfomation();mNewVersion = info.getVersionCode();}else{ Log.e("Error","Version information is null.");return false;}try {int oldversion = (mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), PackageManager.GET_CONFIGURATIONS)).versionCode;if(oldversion < mNewVersion)return true;elsereturn false;} catch (NameNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();return false;} }private VersionInformation getVersionInfoFromServer() {VersionInformation info = null;try {//set url address of version.xmlmDownloadUrl = new URL("http://10.0.2.2:8080/updateApkServer/version.xml");//just for test} catch (MalformedURLException e) {e.printStackTrace();}if (mDownloadUrl != null) {try {HttpURLConnection urlConn = (HttpURLConnection) mDownloadUrl.openConnection();info = XMLParserUtils.getUpdateInformation(urlConn.getInputStream());urlConn.disconnect();} catch (IOException e) {e.printStackTrace();}}return info;} private void showNoticeDialog(){AlertDialog.Builder builder = new Builder(mContext);builder.setTitle("ChoseUpdate");builder.setMessage(mUpdateInfo);builder.setPositiveButton("Download", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();showDownloadDialog();}});builder.setNegativeButton("Later", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}});mNoticeDialog = builder.create();mNoticeDialog.show();}private void showDownloadDialog(){AlertDialog.Builder builder = new Builder(mContext);builder.setTitle("Update");final LayoutInflater inflater = LayoutInflater.from(mContext);View v = inflater.inflate(R.layout.progress, null);mProgressBar = (ProgressBar)v.findViewById(R.id.progress);builder.setView(v);builder.setNegativeButton("Cancel", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();mInteruptDownload = true;}});mDownloadDialog = builder.create();mDownloadDialog.show();downloadApk();}private Runnable mdownApkRunnable = new Runnable() {@Overridepublic void run() {if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {Builder builder = new Builder(mContext);builder.setTitle("Warning");builder.setMessage("SD card isn't exist!");builder.setPositiveButton("OK", new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}});builder.show();return;} else {try {URL url = new URL(mApkUrl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.connect();int length = conn.getContentLength();InputStream is = conn.getInputStream();File file = new File(savePath);if (!file.exists()) {file.mkdir();}String apkFile = saveFileName;File ApkFile = new File(apkFile);FileOutputStream fos = new FileOutputStream(ApkFile);int count = 0;byte buf[] = new byte[1024];do {int numread = is.read(buf);count += numread;mProgress = (int) (((float) count / length) * 100);// update current process valuemHandler.sendEmptyMessage(DOWN_UPDATE);if (numread <= 0) {mHandler.sendEmptyMessage(DOWN_OVER);break;}fos.write(buf, 0, numread);} while (!mInteruptDownload);// cancel download operation if you wantfos.close();is.close();} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}}; //download apkprivate void downloadApk(){downLoadThread = new Thread(mdownApkRunnable);downLoadThread.start();} //install apkprivate void installApk(){File apkfile = new File(saveFileName); if (!apkfile.exists()) { return; } Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); mContext.startActivity(i);}}
5,在每次启动APK时,在MainActivity中调用
package com.tutor.update;import com.client.update.UpdateManager;import android.app.Activity;import android.os.Bundle;public class MainAcitivity extends Activity { private UpdateManager mUpdateManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //check update mUpdateManager = new UpdateManager(this); mUpdateManager.checkUpdateInfo(); //do other things } }
以上5个步骤就是具体的实现过程了,这里的代码需要你设定正确的version.xml 地址和apk地址,否则无法正常运行。
- Android--APK更新总结
- android强制更新APK
- Android在线更新APK
- Android在线更新APK
- android apk版本更新
- Android 静默更新apk
- android apk版本更新
- Android 增量更新APK
- android apk更新
- android更新安装apk
- Android apk版本更新
- android apk版本更新
- Android应用更新apk
- Android 自动检测更新apk版本
- android APK更新主要代码
- android apk的更新下载
- android中apk更新机制
- Android apk 包提示更新
- 利用BeanUtils与PropertyUtils进行javabean的内省操作
- javascript中 "||", "&&" 特殊用法
- Java 中int与byte数组转换详解
- 企业级Hadoop 2.x入门系列之三将Hadoop 2.x源码导入Eclipse中
- 【经典】利用堆,将若干个有序数组合并
- Android--APK更新总结
- 使用AWS亚马逊云搭建Gmail转发服务(一)
- magento目录解析
- 数据可视化-------图解“博士是什么”
- 徒手打造一款PK 名片全能王 的名片识别应用
- 关于Java中FileOutputStream的一点细节问题
- 企业级Hadoop 2.x入门系列之四HDFS文件系统和YARN资源管理框架简介
- 天声人語 20141231
- 伸展树