Android編程實(shí)現(xiàn)自動(dòng)檢測(cè)版本及自動(dòng)升級(jí)的方法
本文實(shí)例講述了Android編程實(shí)現(xiàn)自動(dòng)檢測(cè)版本及自動(dòng)升級(jí)的方法。分享給大家供大家參考,具體如下:
步驟:
1.檢測(cè)當(dāng)前版本的信息AndroidManifest.xml-->manifest-->android:versionName。
2.從服務(wù)器獲取版本號(hào)(版本號(hào)存在于xml文件中)并與當(dāng)前檢測(cè)到的版本進(jìn)行匹配,如果不匹配,提示用戶進(jìn)行升級(jí),如果匹配則進(jìn)入程序主界面。
3.當(dāng)提示用戶進(jìn)行版本升級(jí)時(shí),如果用戶點(diǎn)擊了確定,系統(tǒng)將自動(dòng)從服務(wù)器上下載并進(jìn)行自動(dòng)升級(jí),如果點(diǎn)擊取消將進(jìn)入程序主界面。
效果圖:
獲取當(dāng)前程序的版本號(hào):
/* * 獲取當(dāng)前程序的版本號(hào) */ private String getVersionName() throws Exception{ //獲取packagemanager的實(shí)例 PackageManager packageManager = getPackageManager(); //getPackageName()是你當(dāng)前類的包名,0代表是獲取版本信息 PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0); return packInfo.versionName; }
獲取服務(wù)器端的版本號(hào):
/* * 用pull解析器解析服務(wù)器返回的xml文件 (xml封裝了版本號(hào)) */ public static UpdataInfo getUpdataInfo(InputStream is) throws Exception{ XmlPullParser parser = Xml.newPullParser(); parser.setInput(is, "utf-8");//設(shè)置解析的數(shù)據(jù)源 int type = parser.getEventType(); UpdataInfo info = new UpdataInfo();//實(shí)體 while(type != XmlPullParser.END_DOCUMENT ){ switch (type) { case XmlPullParser.START_TAG: if("version".equals(parser.getName())){ info.setVersion(parser.nextText()); //獲取版本號(hào) }else if ("url".equals(parser.getName())){ info.setUrl(parser.nextText()); //獲取要升級(jí)的APK文件 }else if ("description".equals(parser.getName())){ info.setDescription(parser.nextText()); //獲取該文件的信息 } break; } type = parser.next(); } return info; }
從服務(wù)器下載apk:
public static File getFileFromServer(String path, ProgressDialog pd) throws Exception{ //如果相等的話表示當(dāng)前的sdcard掛載在手機(jī)上并且是可用的 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; //獲取當(dāng)前下載量 pd.setProgress(total); } fos.close(); bis.close(); is.close(); return file; } else{ return null; } }
匹配、下載、自動(dòng)安裝:
/* * 從服務(wù)器獲取xml解析并進(jìn)行比對(duì)版本號(hào) */ public class CheckVersionTask implements Runnable{ public void run() { try { //從資源文件獲取服務(wù)器 地址 String path = getResources().getString(R.string.serverurl); //包裝成url的對(duì)象 URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); InputStream is =conn.getInputStream(); info = UpdataInfoParser.getUpdataInfo(is); if(info.getVersion().equals(versionname)){ Log.i(TAG,"版本號(hào)相同無(wú)需升級(jí)"); LoginMain(); }else{ Log.i(TAG,"版本號(hào)不同 ,提示用戶升級(jí) "); 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_CLIENT: //對(duì)話框通知用戶升級(jí)程序 showUpdataDialog(); break; case GET_UNDATAINFO_ERROR: //服務(wù)器超時(shí) Toast.makeText(getApplicationContext(), "獲取服務(wù)器更新信息失敗", 1).show(); LoginMain(); break; case DOWN_ERROR: //下載apk失敗 Toast.makeText(getApplicationContext(), "下載新版本失敗", 1).show(); LoginMain(); break; } } }; /* * * 彈出對(duì)話框通知用戶更新程序 * * 彈出對(duì)話框的步驟: * 1.創(chuàng)建alertDialog的builder. * 2.要給builder設(shè)置屬性, 對(duì)話框的內(nèi)容,樣式,按鈕 * 3.通過(guò)builder 創(chuàng)建一個(gè)對(duì)話框 * 4.對(duì)話框show()出來(lái) */ protected void showUpdataDialog() { AlertDialog.Builder builer = new Builder(this) ; builer.setTitle("版本升級(jí)"); builer.setMessage(info.getDescription()); //當(dāng)點(diǎn)確定按鈕時(shí)從服務(wù)器上下載 新的apk 然后安裝 builer.setPositiveButton("確定", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { Log.i(TAG,"下載apk,更新"); downLoadApk(); } }); //當(dāng)點(diǎn)取消按鈕時(shí)進(jìn)行登錄 builer.setNegativeButton("取消", new OnClickListener() { public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub LoginMain(); } }); AlertDialog dialog = builer.create(); dialog.show(); } /* * 從服務(wù)器中下載APK */ protected void downLoadApk() { final ProgressDialog pd; //進(jìn)度條對(duì)話框 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(); //結(jié)束掉進(jìn)度條對(duì)話框 } 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(); //執(zhí)行動(dòng)作 intent.setAction(Intent.ACTION_VIEW); //執(zhí)行的數(shù)據(jù)類型 intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); startActivity(intent); } /* * 進(jìn)入程序的主界面 */ private void LoginMain(){ Intent intent = new Intent(this,MainActivity.class); startActivity(intent); //結(jié)束掉當(dāng)前的activity this.finish(); }
UpdataInfo:
public class UpdataInfo { private String version; private String url; private String description; 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; } }
update.xml:
<?xml version="1.0" encoding="utf-8"?> <info> <version>2.0</version> <url>http://192.168.1.187:8080/mobilesafe.apk</url> <description>檢測(cè)到最新版本,請(qǐng)及時(shí)更新!</description> </info>
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
相關(guān)文章
Android中使用Spinner實(shí)現(xiàn)下拉列表功能
Spinner是一個(gè)列表選擇框,會(huì)在用戶選擇后,展示一個(gè)列表供用戶進(jìn)行選擇。下面通過(guò)本文給大家實(shí)例詳解android中使用Spinner實(shí)現(xiàn)下拉列表功能,一起看看吧2017-04-04詳解Android中的ActivityThread和APP啟動(dòng)過(guò)程
ActivityThread就是我們常說(shuō)的主線程或UI線程,ActivityThread的main方法是整個(gè)APP的入口,本篇深入學(xué)習(xí)下ActivityThread,順便了解下APP和Activity的啟動(dòng)過(guò)程。2021-06-06基于Android studio3.6的JNI教程之helloworld思路詳解
這篇文章主要介紹了基于Android studio3.6的JNI教程之helloworld,本文通過(guò)圖文實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Android彈窗ListPopupWindow的簡(jiǎn)單應(yīng)用詳解
這篇文章主要為大家詳細(xì)介紹了Android彈窗ListPopupWindow的簡(jiǎn)單應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Android平臺(tái)生成二維碼并實(shí)現(xiàn)掃描 & 識(shí)別功能
這篇文章主要介紹了Android平臺(tái)生成二維碼并實(shí)現(xiàn)掃描 & 識(shí)別功能的相關(guān)資料,需要的朋友可以參考下2016-06-06詳解Android應(yīng)用中使用TabHost組件進(jìn)行布局的基本方法
這篇文章主要介紹了Android應(yīng)用中使用TabHost組件進(jìn)行布局的基本方法,不繼承TabActivity并以最基本的布局文件方式進(jìn)行布局,需要的朋友可以參考下2016-04-04