zoukankan      html  css  js  c++  java
  • 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";    
    @Override
    public 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;
    }
    @Override
    public 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







  • 相关阅读:
    求树的直径算法
    二叉排序树BST+求树深度算法
    HDU1114Piggy-Bank(完全背包)
    HDU1102(最小生成树Kruskal算法)
    NYoj289苹果(0-1背包)
    NYOJ201作业题
    C#发送邮件附件
    JS用户登录保存账号密码
    远程连接服务器
    博客园页面更新了
  • 原文地址:https://www.cnblogs.com/leftfist/p/4258029.html
Copyright © 2011-2022 走看看