一、准備
1.檢測當前版本的信息AndroidManifest.xml-->manifest-->android:versionName。
2.從服務器獲取版本號(版本號存在於xml文件中)並與當前檢測到的版本進行匹配,如果不匹配,提示用戶進行升級,如果匹配則進入程序主界面。
3.當提示用戶進行版本升級時,如果用戶點擊了確定,系統將自動從服務器上下載並進行自動升級,如果點擊取消將進入程序主界面。
二、效果圖
三、必要說明
服務器端存儲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" ><Buttonandroid: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;
@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.main);getVersion = (Button) findViewById(R.id.btn_getVersion);getVersion.setOnClickListener(new OnClickListener() {
@Overridepublic 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() {
@Overridepublic 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(){
@Overridepublic 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"/>
四、參考文獻