Android檢測版本更新


一、准備

      1.檢測當前版本的信息AndroidManifest.xml-->manifest-->android:versionName。

      2.從服務器獲取版本號(版本號存在於xml文件中)並與當前檢測到的版本進行匹配,如果不匹配,提示用戶進行升級,如果匹配則進入程序主界面。

      3.當提示用戶進行版本升級時,如果用戶點擊了確定,系統將自動從服務器上下載並進行自動升級,如果點擊取消將進入程序主界面。

二、效果圖

                       1234

三、必要說明

      服務器端存儲apk文件,同時有version.xml文件便於比對更新。

<?xml version="1.0" encoding="utf-8"?>
<info>
	<version>2.0</version>
	<url>http://192.168.1.187:8080/mobilesafe.apk</url>
	<description>檢測到最新版本,請及時更新!</description>
	<url_server>http://192.168.1.99/version.xml</url_server>
</info>

      通過一個實體類獲取上述信息。   

package com.android;
public class UpdataInfo {
	private String version;
	private String url;
	private String description;
	private String url_server;
	
	public String getUrl_server() {
		return url_server;
	}
	public void setUrl_server(String url_server) {
		this.url_server = url_server;
	}
	public String getVersion() {
		return version;
	}
	public void setVersion(String version) {
		this.version = version;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
}

      apk和版本信息地址都放在服務器端的version.xml里比較方便,當然如果服務器端不變動,apk地址可以放在strings.xml里,不過版本號信息是新的,必須放在服務器端,xml地址放在strings.xml。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, VersionActivity!</string>
    <string name="app_name">Version</string>
    <string name="url_server">http://192.168.1.99/version.xml</string>
</resources>

      不知道讀者發現沒有,筆者犯了個錯誤,那就是url_server地址必須放在本地,否則怎么讀取version.xml,所以url_server不必在實體類和version里添加,畢竟是現需要version地址也就是url_server,才能夠讀取version。

三、代碼實現

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
	<Button 
	    android:id="@+id/btn_getVersion"
	    android:text="檢查更新"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"/>
</LinearLayout>

package com.android;
import java.io.InputStream;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
public class UpdataInfoParser {
	public static UpdataInfo getUpdataInfo(InputStream is) throws Exception{
		XmlPullParser  parser = Xml.newPullParser();  
		parser.setInput(is, "utf-8");
		int type = parser.getEventType();
		UpdataInfo info = new UpdataInfo();
		while(type != XmlPullParser.END_DOCUMENT ){
			switch (type) {
			case XmlPullParser.START_TAG:
				if("version".equals(parser.getName())){
					info.setVersion(parser.nextText());	
				}else if ("url".equals(parser.getName())){
					info.setUrl(parser.nextText());	
				}else if ("description".equals(parser.getName())){
					info.setDescription(parser.nextText());	
				}
				break;
			}
			type = parser.next();
		}
		return info;
	}
}

package com.android;
import java.io.File;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class VersionActivity extends Activity {
	private final String TAG = this.getClass().getName();
	private final int UPDATA_NONEED = 0;
	private final int UPDATA_CLIENT = 1;
	private final int GET_UNDATAINFO_ERROR = 2;
	private final int SDCARD_NOMOUNTED = 3;
	private final int DOWN_ERROR = 4;
	private Button getVersion;
	private UpdataInfo info;
	private String localVersion;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		getVersion = (Button) findViewById(R.id.btn_getVersion);
		getVersion.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				try {
					localVersion = getVersionName();
					CheckVersionTask cv = new CheckVersionTask();
					new Thread(cv).start();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}
	private String getVersionName() throws Exception {
		//getPackageName()是你當前類的包名,0代表是獲取版本信息  
		PackageManager packageManager = getPackageManager();
		PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(),
				0);
		return packInfo.versionName;
	}
	public class CheckVersionTask implements Runnable {
		InputStream is;
		public void run() {
			try {
				String path = getResources().getString(R.string.url_server);
				URL url = new URL(path);
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.setConnectTimeout(5000);
				conn.setRequestMethod("GET"); 
                int responseCode = conn.getResponseCode(); 
                if (responseCode == 200) { 
                    // 從服務器獲得一個輸入流 
                	is = conn.getInputStream(); 
                } 
				info = UpdataInfoParser.getUpdataInfo(is);
				if (info.getVersion().equals(localVersion)) {
					Log.i(TAG, "版本號相同");
					Message msg = new Message();
					msg.what = UPDATA_NONEED;
					handler.sendMessage(msg);
					// LoginMain();
				} else {
					Log.i(TAG, "版本號不相同 ");
					Message msg = new Message();
					msg.what = UPDATA_CLIENT;
					handler.sendMessage(msg);
				}
			} catch (Exception e) {
				Message msg = new Message();
				msg.what = GET_UNDATAINFO_ERROR;
				handler.sendMessage(msg);
				e.printStackTrace();
			}
		}
	}
	Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			switch (msg.what) {
			case UPDATA_NONEED:
				Toast.makeText(getApplicationContext(), "不需要更新",
						Toast.LENGTH_SHORT).show();
			case UPDATA_CLIENT:
				 //對話框通知用戶升級程序   
				showUpdataDialog();
				break;
			case GET_UNDATAINFO_ERROR:
				//服務器超時   
	            Toast.makeText(getApplicationContext(), "獲取服務器更新信息失敗", 1).show(); 
				break;
			case DOWN_ERROR:
				//下載apk失敗  
	            Toast.makeText(getApplicationContext(), "下載新版本失敗", 1).show(); 
				break;
			}
		}
	};
	/* 
	 *  
	 * 彈出對話框通知用戶更新程序  
	 *  
	 * 彈出對話框的步驟: 
	 *  1.創建alertDialog的builder.   
	 *  2.要給builder設置屬性, 對話框的內容,樣式,按鈕 
	 *  3.通過builder 創建一個對話框 
	 *  4.對話框show()出來   
	 */  
	protected void showUpdataDialog() {
		AlertDialog.Builder builer = new Builder(this);
		builer.setTitle("版本升級");
		builer.setMessage(info.getDescription());
		 //當點確定按鈕時從服務器上下載 新的apk 然后安裝   װ
		builer.setPositiveButton("確定", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				Log.i(TAG, "下載apk,更新");
				downLoadApk();
			}
		});
		builer.setNegativeButton("取消", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
				// TODO Auto-generated method stub
				//do sth
			}
		});
		AlertDialog dialog = builer.create();
		dialog.show();
	}
	/* 
	 * 從服務器中下載APK 
	 */  
	protected void downLoadApk() {  
	    final ProgressDialog pd;    //進度條對話框  
	    pd = new  ProgressDialog(this);  
	    pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);  
	    pd.setMessage("正在下載更新");  
	    pd.show();  
	    new Thread(){  
	        @Override  
	        public void run() {  
	            try {  
	                File file = DownLoadManager.getFileFromServer(info.getUrl(), pd);  
	                sleep(3000);  
	                installApk(file);  
	                pd.dismiss(); //結束掉進度條對話框  
	            } catch (Exception e) {  
	                Message msg = new Message();  
	                msg.what = DOWN_ERROR;  
	                handler.sendMessage(msg);  
	                e.printStackTrace();  
	            }  
	        }}.start();  
	}  
	  
	//安裝apk   
	protected void installApk(File file) {  
	    Intent intent = new Intent();  
	    //執行動作  
	    intent.setAction(Intent.ACTION_VIEW);  
	    //執行的數據類型  
	    intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");  
	    startActivity(intent);  
	}  
}

package com.android;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.ProgressDialog;
import android.os.Environment;
public class DownLoadManager {
	public static File getFileFromServer(String path, ProgressDialog pd) throws Exception{
		//如果相等的話表示當前的sdcard掛載在手機上並且是可用的
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
			URL url = new URL(path);
			HttpURLConnection conn =  (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(5000);
			//獲取到文件的大小 
			pd.setMax(conn.getContentLength());
			InputStream is = conn.getInputStream();
			File file = new File(Environment.getExternalStorageDirectory(), "updata.apk");
			FileOutputStream fos = new FileOutputStream(file);
			BufferedInputStream bis = new BufferedInputStream(is);
			byte[] buffer = new byte[1024];
			int len ;
			int total=0;
			while((len =bis.read(buffer))!=-1){
				fos.write(buffer, 0, len);
				total+= len;
				//獲取當前下載量
				pd.setProgress(total);
			}
			fos.close();
			bis.close();
			is.close();
			return file;
		}
		else{
			return null;
		}
	}
}

<uses-permission android:name="android.permission.INTERNET"/>
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

四、參考文獻

                http://blog.csdn.net/furongkang/article/details/6886526


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM