您好,登錄后才能下訂單哦!
本文為大家分享了Android自動檢測版本及自動升級的具體代碼,供大家參考,具體內容如下
步驟:
1.檢測當前版本的信息AndroidManifest.xml–>manifest–>[Android]
2.從服務器獲取版本號(版本號存在于xml文件中)并與當前檢測到的版本進行匹配,如果不匹配,提示用戶進行升級,如果匹配則進入程序主界面。(demo中假設需要更新)
3.當提示用戶進行版本升級時,如果用戶點擊了“更新”,系統將自動從服務器上下載安裝包并進行自動升級,如果點擊取消將進入程序主界面。
效果圖如下:
下面介紹一下代碼的實現:
1.獲取應用的當前版本號,我是封裝了一個工具類來獲取
// 獲取本版本號,是否更新 int vision = Tools.getVersion(this);
獲取當前版本號工具類:
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 * 獲取版本號 3 * @return 當前應用的版本號 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.獲取服務器版本號,是否要更新(此處就是簡單的網絡請求拿到需要的數據即可,我是寫了固定值)
// 獲取更新版本號 private void getVersion(final int vision) { // {"data":{"content":"其他bug修復。","id":"2","api_key":"android", // // "version":"2.1"},"msg":"獲取成功","status":1} String data = ""; //網絡請求獲取當前版本號和下載鏈接 //實際操作是從服務器獲取 //demo寫死了 String newversion = "2.1";//更新新的版本號 String content = "\n" + "就不告訴你我們更新了什么-。-\n" + "\n" + "----------萬能的分割線-----------\n" + "\n" + "(ㄒoㄒ) 被老板打了一頓,還是來告訴你吧:\n" + "1.下架商品誤買了?恩。。。我搞了點小動作就不會出現了\n" + "2.側邊欄、彈框優化 —— 這個你自己去探索吧,總得留點懸念嘛-。-\n";//更新內容 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); // 版本號不同 ShowDialog(vision, newversion, content, url); } } }
3.接下來就是下載文件了
(1) 顯示下載
此處用的是自定義按鈕:
/** * 升級系統 * * @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)通過異步任務實現進度++
/** * 下載應用 * * @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) { // // 申請多個權限。大神的界面 // AndPermission.with(MainActivity.this) // .requestCode(REQUEST_CODE_PERMISSION_OTHER) // .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) // // rationale作用是:用戶拒絕一次權限,再次申請時先征求用戶同意,再打開授權對話框,避免用戶勾選不再提示。 // .rationale(new RationaleListener() { // @Override // public void showRequestPermissionRationale(int requestCode, Rationale rationale) { // // 這里的對話框可以自定義,只要調用rationale.resume()就可以繼續申請。 // AndPermission.rationaleDialog(MainActivity.this, rationale).show(); // } // } // ) // .send(); // 申請多個權限。 AndPermission.with(MainActivity.this) .requestCode(REQUEST_CODE_PERMISSION_SD) .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) // rationale作用是:用戶拒絕一次權限,再次申請時先征求用戶同意,再打開授權對話框,避免用戶勾選不再提示。 .rationale(rationaleListener ) .send(); Toast.makeText(context, "您未打開SD卡權限" + result, Toast.LENGTH_LONG).show(); } else { // Toast.makeText(context, "File downloaded", // Toast.LENGTH_SHORT) // .show(); update(); } } }
此處下載apk文件,需要獲取SD的讀寫權限(用的是嚴大的權限庫)
權限庫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) { // 這里使用自定義對話框,如果不想自定義,用AndPermission默認對話框: // AndPermission.rationaleDialog(Context, Rationale).show(); // 自定義對話框。 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權限----------------------------------// @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(); // 用戶否勾選了不再提示并且拒絕了權限,那么提示用戶到設置中授權。 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,請看上面。 } } //----------------------------------權限回調處理----------------------------------// @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); /** * 轉給AndPermission分析結果。 * * @param object 要接受結果的Activity、Fragment。 * @param requestCode 請求碼。 * @param permissions 權限數組,一個或者多個。 * @param grantResults 請求結果。 */ 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(); //設置成功,再次請求更新 getVersion(Tools.getVersion(MainActivity.this)); break; } } }
(3) 當apk文件下載完畢時,打開安裝
private void update() { //安裝應用 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已經上傳到GitHub,如有需要自行下載
GitHub: 鏈接地址
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。