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地址,否则无法正常运行。

0 0
原创粉丝点击