Android實現版本更新和自動安裝
阿新 • • 發佈:2019-01-03
直接執行的專案和打包的專案apk簽名不同,所以不能直接用開發工具執行專案進行版本更新.需要用apk打包安裝的形式更新,否則會提示"簽名衝突",無法完成覆蓋安裝
以上例項如有不足請指出./** 版本更新 */ public class SplashActivity extends Activity { private static final String TAG = "SplashActivity"; public static final int SHOW_UPDATE_DIALOG = 0; public static final int SHOW_ERROR = 1; public final static int CONNECT_TIMEOUT = 5000; public final static int READ_TIMEOUT = 5000; public final static int WRITE_TIMEOUT = 5000; //獲取裝置名稱 private String deviceName = Build.MODEL; //獲取裝置序列號 private String serialNumber = getSerialNumber(); private VersionDataBean versionDataBean; @Override protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); initData(); } /** * 初始化資料 */ private void initData() { boolean autoUpdate = PreferenceUtils.getBoolean(this, Constants.AUTO_UPDATE, true); if (autoUpdate) { //版本更新,去伺服器獲取最新的版本,和本地版本比較 new Thread(new CheckServerVersion()).start(); } else { //直接跳轉到登入介面 load2Login(); } } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { /** 彈出提示更新的dialog */ case SHOW_UPDATE_DIALOG: showUpdateDialog(); break; /** 提示錯誤 */ case SHOW_ERROR: Toast.makeText(SplashActivity.this, msg.obj+"", Toast.LENGTH_LONG).show(); load2Login(); break; default: break; } } }; /** * 檢查伺服器端版本號 */ private class CheckServerVersion implements Runnable { @Override public void run() { //訪問網路,獲取伺服器端版本號 OkHttpClient client = new OkHttpClient.Builder().readTimeout(READ_TIMEOUT, TimeUnit.SECONDS).writeTimeout (WRITE_TIMEOUT,TimeUnit.SECONDS).connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS).build(); String url = new UrlInfo(SplashActivity.this).getUrl(); if (url.equals("http://null:null")) { load2Login(); } else { VersionDatas versionDatas = new VersionDatas(); //物件轉json final Gson gson = new Gson(); String versionDatasJson = gson.toJson(versionDatas); FormBody body = new FormBody.Builder().add("versionDatasJson", versionDatasJson).build(); Request request = new Request.Builder().url(url).post(body).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { //如果連線超時則跳轉到登入介面 Message msg = Message.obtain(); msg.what = SHOW_ERROR; msg.obj = "網路異常!請檢查網路連線狀況及設定資訊"; handler.sendMessage(msg); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { Log.d(TAG, "訪問介面成功"); String json = response.body().string(); Log.d(TAG, "獲取伺服器端版本號json= " + json); // 解析json資料 if(versionDataBean!=null){ versionDataBean = gson.fromJson(json, VersionDataBean.class); //獲取到伺服器端版本號,對比本地的版本號 int serverVersionCode = versionDataBean.VERSION_NO; int localVersionCode = PackageUtils.getVersionCode(SplashActivity.this); if (serverVersionCode > localVersionCode) { //伺服器端版本號大於本地版本號,彈出dialog提示更新 Message showUpdateDialog = Message.obtain(); showUpdateDialog.what = SHOW_UPDATE_DIALOG; handler.sendMessage(showUpdateDialog); } else { //跳轉到登入介面 load2Login(); } }else{ load2Login(); Log.d(TAG,"versionDatabean為空0918"); } } else { //跳轉到登入介面 Log.d(TAG, "訪問介面失敗"); load2Login(); } } }); } } } /** * 彈出提示更新的dialog */ private void showUpdateDialog() { AlertDialog.Builder dialog = new AlertDialog.Builder(this); dialog.setCancelable(false); dialog.setTitle("版本更新提示"); dialog.setMessage("檢查到有最新版本,是否更新?"); dialog.setNegativeButton("暫不更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //跳轉到登入介面 load2Login(); } }); dialog.setPositiveButton("立刻更新", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //從伺服器端下載最新apk downloadApk(); } }); dialog.show(); } /** * 從伺服器端下載最新apk */ private void downloadApk() { //顯示下載進度 ProgressDialog dialog = new ProgressDialog(this); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); dialog.show(); //訪問網路下載apk new Thread(new DownloadApk(dialog)).start(); } /** * 訪問網路下載apk */ private class DownloadApk implements Runnable { private ProgressDialog dialog; InputStream is; FileOutputStream fos; public DownloadApk(ProgressDialog dialog) { this.dialog = dialog; } @Override public void run() { OkHttpClient client = new OkHttpClient(); String url = versionDataBean.VERSION_URL; Request request = new Request.Builder().get().url(url).build(); try { Response response = client.newCall(request).execute(); if (response.isSuccessful()) { Log.d(TAG, "開始下載apk"); //獲取內容總長度 long contentLength = response.body().contentLength(); //設定最大值 dialog.setMax((int) contentLength); //儲存到sd卡 File apkFile = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".apk"); fos = new FileOutputStream(apkFile); //獲得輸入流 is = response.body().byteStream(); //定義緩衝區大小 byte[] bys = new byte[1024]; int progress = 0; int len = -1; while ((len = is.read(bys)) != -1) { try { Thread.sleep(1); fos.write(bys, 0, len); fos.flush(); progress += len; //設定進度 dialog.setProgress(progress); } catch (InterruptedException e) { Message msg = Message.obtain(); msg.what = SHOW_ERROR; msg.obj = "ERROR:10002"; handler.sendMessage(msg); load2Login(); } } //下載完成,提示使用者安裝 installApk(apkFile); } } catch (IOException e) { Message msg = Message.obtain(); msg.what = SHOW_ERROR; msg.obj = "ERROR:10003"; handler.sendMessage(msg); load2Login(); } finally { //關閉io流 if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } is = null; } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } fos = null; } } dialog.dismiss(); } } /** * 下載完成,提示使用者安裝 */ private void installApk(File file) { //呼叫系統安裝程式 Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); intent.addCategory("android.intent.category.DEFAULT"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); startActivityForResult(intent, REQUEST_INSTALL_CODE); } /** * 跳轉到登入介面 */ private void load2Login() { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2000); Intent toLogin = new Intent(SplashActivity.this, LoginActivity.class); startActivity(toLogin); finish(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } /** * 跳轉到主介面 */ private void load2MainActivity() { Intent toMainActivity = new Intent(SplashActivity.this, MainActivity.class); startActivity(toMainActivity); finish(); } /** * 獲取裝置序列號 */ private String getSerialNumber() { String serial = null; try { Class<?> c = Class.forName("android.os.SystemProperties"); Method get = c.getMethod("get", String.class); serial = (String) get.invoke(c, "ro.serialno"); } catch (Exception e) { e.printStackTrace(); } return serial; } /** * 封裝版本升級資料 */ private class VersionDatas { String COMMAND = "GET_APP_VERSION"; String DEVICE_NAME = deviceName; String DEVICE_SN = serialNumber; } }