Android App版本自動更新

App在開發過程當中,隨着業務場景的不斷增多,功能的不斷完善,早期下載App的用戶便沒法體驗最新的功能,爲了能讓用戶更及時的體驗App最新版本,在App開發過程加入App自動更新功能便顯得尤其重要。更新apk主要分爲二類: (1)用戶點擊更新後,前臺進行下載,下載過程當中用戶沒法操做 (2)後臺進行下載,下載完成後,service回調進行apk的安裝,下載過程當中用戶可操做,原本講解第一種android

實例下載api

     1. 運行前準備服務器

    本文附帶實例: 實例中會下載一個應用程序(本公司的另外一個產品:優鮮派 無病毒,請安心測試), 若是用戶須要體驗自動下載其它的產品,請自行配置apk下載路徑:  將下圖中的url路徑換成本身的apk路徑便可, apk的路徑能夠到360或者應用寶的官方網站上獲取網絡

 2. 本實例運行效果圖: app

        2.1 啓動應用程序dom

 2.2 點擊 更新 操做, 開始下載最新版本apk,進度條顯示下載進度ide

2.3 apk下載完成以後,自動安裝下載的apk包, 注意下圖的箭頭處的意思測試

3.代碼講解優化

      3.1 程序啓動後, 調用後臺接口獲取最新apk版本信息(包括版本號與版本須要升級功能信息), 將最新版本號與當前apk版本號進行比較,若是版本號不一致,則彈出提示框,提示用戶新版本中包含哪些最新信息, 用戶根據自動須要選擇是否更新網站

       得到當前apk版本號:

複製代碼

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;
    }

複製代碼

因爲沒法模擬與後臺的交互,這裏將網絡版本號寫死,比當前apk版本號要大,模擬更新的場景

       彈出對話框,提示新版本新功能

複製代碼

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";//更新內容
     
            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.2 在彈出的對話框,用戶點擊"更新"與"取消"操做

          更新時構建進度條頁面

複製代碼

private void ShowDialog(int vision, String newversion, String content, final String url) {
            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();
        }

複製代碼

 3.3 開啓線程類下載應用程序,將下載進度顯示到進度條上

         線程啓動前調用:   onPreExecute

         線程下載apk過程:  onPostExecute

         進度條更新:       onProgressUpdate

         下載apk完成回調:  onPostExecute

複製代碼

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();
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP "
                        + connection.getResponseCode() + " "
                        + connection.getResponseMessage();
            }
 
            int fileLength = connection.getContentLength();
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                file = Environment.getExternalStorageDirectory();
                if (!file.exists()) {
                    // 判斷父文件夾是否存在
                    if (!file.getParentFile().exists()) {
                        file.getParentFile().mkdirs();
                    }
                }
                file = new File(file, DOWNLOAD_NAME);
            } 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) {
                ignored.toString();
            }
            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_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 {
            update(context);
        }
 
    }
}

複製代碼

4. 安裝下載完的apk包

複製代碼

private void update(Context context) {
        //安裝應用
        Log.i("lxl  update->","update");
     
        File apkFile = new File(Environment.getExternalStorageDirectory(), DOWNLOAD_NAME);
     
        Intent intent =new Intent(Intent.ACTION_VIEW);
     
        if (apkFile == null || context == null) {
            Log.i("lxl  update->","null.");
            throw new NullPointerException();
        }
     
        if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {
     
                Uri contentUri = FileProvider.getUriForFile(context.getApplicationContext(),
                        BuildConfig.APPLICATION_ID + ".fileProvider",apkFile);
     
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
     
                intent.setDataAndType(contentUri,"application/vnd.android.package-archive");
                Log.i("lxl  update->",">>>==Build.VERSION_CODES.N");
     
        }else{
     
          intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     
          intent.setDataAndType(Uri.fromFile(apkFile),"application/vnd.android.package-archive");
            Log.i("lxl  update->","<<<<<  Build.VERSION_CODES.N");
        }
     
        startActivity(intent);
     
    }
相關文章
相關標籤/搜索