Android程序的版本检测与更新

               

做个网站的安卓客户端,用户安装到自己手机上,如果我出了新版本怎么办呢?要有版本更新功能。

本来版本检测最好可以自动进行。但如果每次开启程序,都要先检测一轮,是一种浪费,毕竟版本更新是小概率的事情。或许可以程序开启的时候,判断一下时间,单日就检测,双日就不检测,或者随机什么的,降低一下检测的频率?

我采取的做法是将检测功能做到了菜单上,用户有需要,就手动打开自己检测一下。反正我们这个是网站客户端,有版本更新,在网站上发个通告就行了。

版本检测与更新有以下几个关键步骤:

1、检测有无新版本

2、下载新版本

3、安装替换新版本

我处理的方案是

1、在assets文件夹新增一个文件:ver.cfg,记录版本信息,纯文本格式,内容只有一句话:

Version=1.0

这个会随安装包装到用户的手机上

然后在网站里面,设置一XML文件ver_apk.xml,内容也只有这么一点:

<?xml version="1.0" encoding="utf-8" ?><string>1.0</string>

检测的时候,就先访问网站的这个XML,得到最新版本号,然后与手机上的ver.cfg文件里记录的进行比对,不同的话就可以认为存在新版本,提示进行更新。

2、下载的话就是直接下载的,我还不知道怎么弄断点续传

3、安装替换,关键在于签名。就是每个版本的签名要保持一致。否则新的无法替换旧的,提示安装未完成。

------------------- 天气太冷,咯咯咯 ------------------------------------

这个功能做在菜单上,触发代码如下:

//==========================================================================// 菜单//==========================================================================    private static final String urlApk = "http://3g.***.com/tool/***.apk";private static final String urlVer = "http://3g.***.com/tool/ver_apk.xml";    @Overridepublic boolean onCreateOptionsMenu(Menu menu) { menu.add(Menu.NONE, Menu.FIRST + 1, 5, "检测更新").setIcon( android.R.drawable.ic_menu_upload); menu.add(Menu.NONE,Menu.FIRST+2,4,"退出").setIcon(android.R.drawable.ic_lock_power_off); return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) switch (item.getItemId()) {        case Menu.FIRST + 1:            Toast.makeText(this, "正在检测版本", Toast.LENGTH_LONG).show();         UpdateVer uv = new UpdateVer(urlApk,urlVer,MainActivity.this);         uv.checkVer();            break;        case Menu.FIRST + 2:            confirmExit();            break;    }    return false;}

检测更新因为代码比较多,写成一个类进行封装

UpdateVer.java

package android.***;import android.app.Activity;import android.app.AlertDialog;import android.app.Dialog;import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.net.Uri;import android.os.AsyncTask;import android.util.Log;import android.webkit.URLUtil;import android.widget.Toast;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.util.Properties;import org.xml.sax.InputSource;import java.text.SimpleDateFormat;import java.util.Date;public class UpdateVer extends Activity{    private static final String TAG = "DOWNLOADAPK";    private String PastVersion;    private String NowVersion; public  ProgressDialog pBar;  private String currentFilePath = "";  private String fileEx=""private String fileNa=""private String strURL=""private String VersionUri =""private Context mContext; private final String fileVer = "ver.cfg"public UpdateVer(String urlapk,String urlver,final Context context){  SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");  String ver = "?ver=" + df.format(new Date());//主要是避开手机的缓存  strURL = urlapk + ver;  VersionUri = urlver + ver;  mContext = context; } public void checkVer() {  // 解析Version网页,获取版本号  getVersionxml(VersionUri); } private void compareVer() {  load();    //当有最新版本的时候  if(PastVersion != null && !PastVersion.equals(NowVersion)){    Dialog dialog = new AlertDialog.Builder(mContext).setTitle("系统更新")                .setMessage(String.format("发现新版本%s,目前版本为%s,请更新!",NowVersion,PastVersion))// 设置内容         // 设置确定按钮         .setPositiveButton("确定"          ,new DialogInterface.OnClickListener() {                        @Override     public void onClick(DialogInterface dialog,                                        int which) {                                     pBar = new ProgressDialog(mContext);                              pBar.setTitle("正在下载");                                     pBar.setMessage("请稍候...");                              pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);                                          fileEx = strURL.substring(strURL.lastIndexOf(".") + 1,strURL.length()).toLowerCase();                              fileEx = fileEx.substring(0,fileEx.lastIndexOf("?"));                              fileNa = strURL.substring(strURL.lastIndexOf("/") + 1,strURL.lastIndexOf("."));                              getFile(strURL);                                }                    }).setNegativeButton("取消",                               new DialogInterface.OnClickListener() {                       @Override        public void onClick(DialogInterface dialog,                                int whichButton) {                          // 点击"取消"按钮之后退出程序                                  }                      }).create();// 创建    // 显示对话框    dialog.show();  }  else{   Toast.makeText(mContext, String.format("当前为最新版本%s",PastVersion), Toast.LENGTH_LONG).show();  } } private void getFile(final String strPath)  {   pBar.show();     try{       if (strPath.equals(currentFilePath) ){        getDataSource(strPath);        }      currentFilePath = strPath;            Runnable r = new Runnable(){          @Override    public void run()        {           try{          getDataSource(strPath);         }         catch (Exception e){         Log.e(TAG, e.getMessage(), e);         }        }       };         new Thread(r).start();      }      catch(Exception e){       e.printStackTrace();      } } /*取得远程文件*/  private void getDataSource(String strPath) throws Exception {  if (!URLUtil.isNetworkUrl(strPath)) {   Log.d("Tag","error");  }   else {       /*取得URL*/   URL myURL = new URL(strPath);    /*建立联机*/   URLConnection conn = myURL.openConnection();      conn.connect();      /*InputStream 下载文件*/   InputStream is = conn.getInputStream();      if (is == null) {      Log.d("tag","error");    throw new RuntimeException("没有读取到文件内容");    }    /*建立临时文件*/    File myTempFile = File.createTempFile(fileNa, "." + fileEx);    myTempFile.getAbsolutePath();    /*将文件写入临时盘*/    FileOutputStream fos = new FileOutputStream(myTempFile);    byte buf[] = new byte[128];      do{       int numread = is.read(buf);       if (numread <= 0) {      break;     }     fos.write(buf, 0, numread);      }while (true);        /*打开文件进行安装*/   openFile(myTempFile);   try {     is.close();    }   catch (Exception ex){     Log.d("Tag","error");    Log.e(TAG, "error: " + ex.getMessage(), ex);    }  } }  /* 在手机上打开文件 */ private void openFile(File f) {  pBar.cancel();  Intent intent = new Intent();  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  intent.setAction(android.content.Intent.ACTION_VIEW);      /* 调用getMIMEType()来取得MimeType */  String type = getMIMEType(f);  /* 设定intent的file与MimeType */  intent.setDataAndType(Uri.fromFile(f),type);  mContext.startActivity(intent);  } /* 判断文件MimeType的method */ private String getMIMEType(File f) {      String type = "";     String fName = f.getName();     /* 取得扩展名 */     String end = fName.substring(fName.lastIndexOf(".")+1,fName.length()).toLowerCase();       /* 按扩展名的类型决定MimeType */     if(end.equals("m4a")       || end.equals("mp3")       || end.equals("mid")       || end.equals("xmf")       || end.equals("ogg")       || end.equals("wav")){      type = "audio";      }     else if(end.equals("3gp") || end.equals("mp4")){      type = "video";     }     else if(end.equals("jpg")       || end.equals("gif")       || end.equals("png")       || end.equals("jpeg")       || end.equals("bmp")){      type = "image";     }     else if(end.equals("apk")){       /* android.permission.INSTALL_PACKAGES */       type = "application/vnd.android.package-archive";      }      else{      type = "*";     }     /*如果无法直接打开,就跳出软件清单给使用者选择 */     if(!end.equals("apk")){       type += "/*";       }      return type;   } private void getVersionxml(String resourceUrl){  GetVer gv = new GetVer();  gv.execute(resourceUrl);  } private boolean load(){  Properties properties = new Properties();  try{   InputStream stream = mContext.getAssets().open(fileVer);   //FileInputStream stream = mContext.openFileInput(fileVer);   //读取文件内容   properties.load(stream);   }  catch (FileNotFoundException e){   return false;  }  catch(IOException e){   return false;  }  catch(Exception e){   return false;  }  PastVersion = String.valueOf(properties.get("Version").toString());   return true; }  //========================================================================== // GetVer //==========================================================================  class GetVer extends AsyncTask<String, Integer, String> {  @Override       protected String doInBackground(String... urlVer) {     String db = null;      URL url = null;          try {    url = new URL(urlVer[0]);   }    catch (MalformedURLException e) {    e.printStackTrace();   }     InputSource is = null;    try {     is = new InputSource(url.openStream());     is.setEncoding("UTF-8");       db = SAXGetVersionService.readRssXml(is);   }    catch (Exception e) {    e.printStackTrace();   }    return db;       }       @Override       protected void onCancelled() {           super.onCancelled();       }       @Override       protected void onPostExecute(String result) {    NowVersion = result;      compareVer();     }   } }


AndroidManifest.xml要加上几句

    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.INSTALL_PACKAGES"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.RESTART_PACKAGES" />    <uses-permission android:name="android.permission.READ_PHONE_STATE" />    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> 

参考文章:


http://download.csdn.net/detail/xtlvice/3510681







           

猜你喜欢

转载自blog.csdn.net/qq_44894655/article/details/89500906