manifest–>[Android..."/>
您好,登錄后才能下訂單哦!
本文為大家分享了Android自動(dòng)檢測版本及自動(dòng)升級(jí)的具體代碼,供大家參考,具體內(nèi)容如下
步驟:
1.檢測當(dāng)前版本的信息AndroidManifest.xml–>manifest–>[Android]
2.從服務(wù)器獲取版本號(hào)(版本號(hào)存在于xml文件中)并與當(dāng)前檢測到的版本進(jìn)行匹配,如果不匹配,提示用戶進(jìn)行升級(jí),如果匹配則進(jìn)入程序主界面。(demo中假設(shè)需要更新)
3.當(dāng)提示用戶進(jìn)行版本升級(jí)時(shí),如果用戶點(diǎn)擊了“更新”,系統(tǒng)將自動(dòng)從服務(wù)器上下載安裝包并進(jìn)行自動(dòng)升級(jí),如果點(diǎn)擊取消將進(jìn)入程序主界面。
效果圖如下:
下面介紹一下代碼的實(shí)現(xiàn):
1.獲取應(yīng)用的當(dāng)前版本號(hào),我是封裝了一個(gè)工具類來獲取
// 獲取本版本號(hào),是否更新 int vision = Tools.getVersion(this);
獲取當(dāng)前版本號(hào)工具類:
public class Tools { /** * 檢查是否存在SDCard * * @return */ public static boolean hasSdcard() { String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { return true; } else { return false; } } /** * 2 * 獲取版本號(hào) 3 * @return 當(dāng)前應(yīng)用的版本號(hào) 4 */ public static int getVersion(Context context) { try { PackageManager manager = context.getPackageManager(); PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0); String version = info.versionName; int versioncode = info.versionCode; return versioncode; } catch (Exception e) { e.printStackTrace(); } return 0; } }
2.獲取服務(wù)器版本號(hào),是否要更新(此處就是簡單的網(wǎng)絡(luò)請(qǐng)求拿到需要的數(shù)據(jù)即可,我是寫了固定值)
// 獲取更新版本號(hào) private void getVersion(final int vision) { // {"data":{"content":"其他bug修復(fù)。","id":"2","api_key":"android", // // "version":"2.1"},"msg":"獲取成功","status":1} String data = ""; //網(wǎng)絡(luò)請(qǐng)求獲取當(dāng)前版本號(hào)和下載鏈接 //實(shí)際操作是從服務(wù)器獲取 //demo寫死了 String newversion = "2.1";//更新新的版本號(hào) String content = "\n" + "就不告訴你我們更新了什么-。-\n" + "\n" + "----------萬能的分割線-----------\n" + "\n" + "(ㄒoㄒ) 被老板打了一頓,還是來告訴你吧:\n" + "1.下架商品誤買了?恩。。。我搞了點(diǎn)小動(dòng)作就不會(huì)出現(xiàn)了\n" + "2.側(cè)邊欄、彈框優(yōu)化 —— 這個(gè)你自己去探索吧,總得留點(diǎn)懸念嘛-。-\n";//更新內(nèi)容 String url = "http://openbox.mobilem.#/index/d/sid/3429345";//安裝包下載地址 double newversioncode = Double .parseDouble(newversion); int cc = (int) (newversioncode); System.out.println(newversion + "v" + vision + ",," + cc); if (cc != vision) { if (vision < cc) { System.out.println(newversion + "v" + vision); // 版本號(hào)不同 ShowDialog(vision, newversion, content, url); } } }
3.接下來就是下載文件了
(1) 顯示下載
此處用的是自定義按鈕:
/** * 升級(jí)系統(tǒng) * * @param content * @param url */ private void ShowDialog(int vision, String newversion, String content, final String url) { final MaterialDialog dialog = new MaterialDialog(this); dialog.content(content).btnText("取消", "更新").title("版本更新 ") .titleTextSize(15f).show(); dialog.setCanceledOnTouchOutside(false); dialog.setOnBtnClickL(new OnBtnClickL() {// left btn click listener @Override public void onBtnClick() { dialog.dismiss(); } }, new OnBtnClickL() {// right btn click listener @Override public void onBtnClick() { dialog.dismiss(); // pBar = new ProgressDialog(MainActivity.this, // R.style.dialog); pBar = new CommonProgressDialog(MainActivity.this); pBar.setCanceledOnTouchOutside(false); pBar.setTitle("正在下載"); pBar.setCustomTitle(LayoutInflater.from( MainActivity.this).inflate( R.layout.title_dialog, null)); pBar.setMessage("正在下載"); pBar.setIndeterminate(true); pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pBar.setCancelable(true); // downFile(URLData.DOWNLOAD_URL); final DownloadTask downloadTask = new DownloadTask( MainActivity.this); downloadTask.execute(url); pBar.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { downloadTask.cancel(true); } }); } }); }
原生的按鈕:
new android.app.AlertDialog.Builder(this) .setTitle("版本更新") .setMessage(content) .setPositiveButton("更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); pBar = new CommonProgressDialog(MainActivity.this); pBar.setCanceledOnTouchOutside(false); pBar.setTitle("正在下載"); pBar.setCustomTitle(LayoutInflater.from( MainActivity.this).inflate( R.layout.title_dialog, null)); pBar.setMessage("正在下載"); pBar.setIndeterminate(true); pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pBar.setCancelable(true); // downFile(URLData.DOWNLOAD_URL); final DownloadTask downloadTask = new DownloadTask( MainActivity.this); downloadTask.execute(url); pBar.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { downloadTask.cancel(true); } }); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .show();
(2)通過異步任務(wù)實(shí)現(xiàn)進(jìn)度++
/** * 下載應(yīng)用 * * @author Administrator */ class DownloadTask extends AsyncTask<String, Integer, String> { private Context context; private PowerManager.WakeLock mWakeLock; public DownloadTask(Context context) { this.context = context; } @Override protected String doInBackground(String... sUrl) { InputStream input = null; OutputStream output = null; HttpURLConnection connection = null; File file = null; try { URL url = new URL(sUrl[0]); connection = (HttpURLConnection) url.openConnection(); connection.connect(); // expect HTTP 200 OK, so we don't mistakenly save error // report // instead of the file if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { return "Server returned HTTP " + connection.getResponseCode() + " " + connection.getResponseMessage(); } // this will be useful to display download percentage // might be -1: server did not report the length int fileLength = connection.getContentLength(); if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { file = new File(Environment.getExternalStorageDirectory(), DOWNLOAD_NAME); if (!file.exists()) { // 判斷父文件夾是否存在 if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } } } else { Toast.makeText(MainActivity.this, "sd卡未掛載", Toast.LENGTH_LONG).show(); } input = connection.getInputStream(); output = new FileOutputStream(file); byte data[] = new byte[4096]; long total = 0; int count; while ((count = input.read(data)) != -1) { // allow canceling with back button if (isCancelled()) { input.close(); return null; } total += count; // publishing the progress.... if (fileLength > 0) // only if total length is known publishProgress((int) (total * 100 / fileLength)); output.write(data, 0, count); } } catch (Exception e) { System.out.println(e.toString()); return e.toString(); } finally { try { if (output != null) output.close(); if (input != null) input.close(); } catch (IOException ignored) { } if (connection != null) connection.disconnect(); } return null; } @Override protected void onPreExecute() { super.onPreExecute(); // take CPU lock to prevent CPU from going off if the user // presses the power button during download PowerManager pm = (PowerManager) context .getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName()); mWakeLock.acquire(); pBar.show(); } @Override protected void onProgressUpdate(Integer... progress) { super.onProgressUpdate(progress); // if we get here, length is known, now set indeterminate to false pBar.setIndeterminate(false); pBar.setMax(100); pBar.setProgress(progress[0]); } @Override protected void onPostExecute(String result) { mWakeLock.release(); pBar.dismiss(); if (result != null) { // // 申請(qǐng)多個(gè)權(quán)限。大神的界面 // AndPermission.with(MainActivity.this) // .requestCode(REQUEST_CODE_PERMISSION_OTHER) // .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) // // rationale作用是:用戶拒絕一次權(quán)限,再次申請(qǐng)時(shí)先征求用戶同意,再打開授權(quán)對(duì)話框,避免用戶勾選不再提示。 // .rationale(new RationaleListener() { // @Override // public void showRequestPermissionRationale(int requestCode, Rationale rationale) { // // 這里的對(duì)話框可以自定義,只要調(diào)用rationale.resume()就可以繼續(xù)申請(qǐng)。 // AndPermission.rationaleDialog(MainActivity.this, rationale).show(); // } // } // ) // .send(); // 申請(qǐng)多個(gè)權(quán)限。 AndPermission.with(MainActivity.this) .requestCode(REQUEST_CODE_PERMISSION_SD) .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) // rationale作用是:用戶拒絕一次權(quán)限,再次申請(qǐng)時(shí)先征求用戶同意,再打開授權(quán)對(duì)話框,避免用戶勾選不再提示。 .rationale(rationaleListener ) .send(); Toast.makeText(context, "您未打開SD卡權(quán)限" + result, Toast.LENGTH_LONG).show(); } else { // Toast.makeText(context, "File downloaded", // Toast.LENGTH_SHORT) // .show(); update(); } } }
此處下載apk文件,需要獲取SD的讀寫權(quán)限(用的是嚴(yán)大的權(quán)限庫)
權(quán)限庫GitHub
private static final int REQUEST_CODE_PERMISSION_SD = 101; private static final int REQUEST_CODE_SETTING = 300; private RationaleListener rationaleListener = new RationaleListener() { @Override public void showRequestPermissionRationale(int requestCode, final Rationale rationale) { // 這里使用自定義對(duì)話框,如果不想自定義,用AndPermission默認(rèn)對(duì)話框: // AndPermission.rationaleDialog(Context, Rationale).show(); // 自定義對(duì)話框。 AlertDialog.build(MainActivity.this) .setTitle(R.string.title_dialog) .setMessage(R.string.message_permission_rationale) .setPositiveButton(R.string.btn_dialog_yes_permission, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); rationale.resume(); } }) .setNegativeButton(R.string.btn_dialog_no_permission, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.cancel(); rationale.cancel(); } }) .show(); } }; //----------------------------------SD權(quán)限----------------------------------// @PermissionYes(REQUEST_CODE_PERMISSION_SD) private void getMultiYes(List<String> grantedPermissions) { Toast.makeText(this, R.string.message_post_succeed, Toast.LENGTH_SHORT).show(); } @PermissionNo(REQUEST_CODE_PERMISSION_SD) private void getMultiNo(List<String> deniedPermissions) { Toast.makeText(this, R.string.message_post_failed, Toast.LENGTH_SHORT).show(); // 用戶否勾選了不再提示并且拒絕了權(quán)限,那么提示用戶到設(shè)置中授權(quán)。 if (AndPermission.hasAlwaysDeniedPermission(this, deniedPermissions)) { AndPermission.defaultSettingDialog(this, REQUEST_CODE_SETTING) .setTitle(R.string.title_dialog) .setMessage(R.string.message_permission_failed) .setPositiveButton(R.string.btn_dialog_yes_permission) .setNegativeButton(R.string.btn_dialog_no_permission, null) .show(); // 更多自定dialog,請(qǐng)看上面。 } } //----------------------------------權(quán)限回調(diào)處理----------------------------------// @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); /** * 轉(zhuǎn)給AndPermission分析結(jié)果。 * * @param object 要接受結(jié)果的Activity、Fragment。 * @param requestCode 請(qǐng)求碼。 * @param permissions 權(quán)限數(shù)組,一個(gè)或者多個(gè)。 * @param grantResults 請(qǐng)求結(jié)果。 */ AndPermission.onRequestPermissionsResult(this, requestCode, permissions, grantResults); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE_SETTING: { Toast.makeText(this, R.string.message_setting_back, Toast.LENGTH_LONG).show(); //設(shè)置成功,再次請(qǐng)求更新 getVersion(Tools.getVersion(MainActivity.this)); break; } } }
(3) 當(dāng)apk文件下載完畢時(shí),打開安裝
private void update() { //安裝應(yīng)用 Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(Environment .getExternalStorageDirectory(), DOWNLOAD_NAME)), "application/vnd.android.package-archive"); startActivity(intent); }
源碼
此demo已經(jīng)上傳到GitHub,如有需要自行下載
GitHub: 鏈接地址
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。