android App版本升級功能
阿新 • • 發佈:2019-01-29
一般的安卓app都有自動更新功能,實現app的更新,以讓使用者體驗新版本的功能,這裡也是專案中用到的,今天就來總結一下。做和記錄。
import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Message; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; import android.widget.Toast; import com.gwkj.qixiubaodian.Manifest; import com.gwkj.qixiubaodian.R; import com.gwkj.qixiubaodian.qxbd.SdCardUtils; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * 版本更新 */ public class UpdateManager extends SdCardUtils { private Context mContext; private String updateMsg = "發現新版本,請及時更新";// 提示語 private String apkurl = "";// 返回的安裝包url// private AlertDialogEx downloadDialog;// 下載提示 @SuppressLint("SdCardPath") private static final String savePath1 = "/sdcard/App";// 儲存路徑 @SuppressLint("SdCardPath") private static final String savePath = "/sdcard/App/updatedemo/";// 儲存路徑 private static final String saveFileName = "App.apk"; private ProgressBar mProgress;// 進度條 private static final int DOWN_UPDATE = 1; private static final int DOWN_OVER = 2; private int progress; private Thread downLoadThread; private boolean interceptFlag = false; // 外部介面呼叫 public void checkUpdateInfo(String apkurl, String apkInfo) { this.apkurl = apkurl; this.updateMsg = apkInfo; showNoticeDialog(); } // 當有新版本提示示更新 public void showNoticeDialog() { final AlertDialogEx alert = new AlertDialogEx(mContext); alert.setTitle("軟體版本更新"); alert.setMessage(updateMsg); alert.setConfirmButton("立即更新", new AlertDialogEx.OnClickListener() { @Override public void onClick(AlertDialogEx dialog, int button) { showDownloadDialog(); } }); // alert.setCancelButton("暫不更新", null); alert.show(); } // 下載apk public void showDownloadDialog() { downloadDialog = new AlertDialogEx(mContext); final LayoutInflater inflater = LayoutInflater.from(mContext); View v = inflater.inflate(R.layout.pross, null); mProgress = (ProgressBar) v.findViewById(R.id.progress); downloadDialog.setTitle("軟體更新"); downloadDialog.setCancelButton("取消更新", new AlertDialogEx.OnClickListener() { @Override public void onClick(AlertDialogEx dialog, int button) { downloadDialog.dismiss(); interceptFlag = true; } }); downloadDialog.show(); downloadDialog.setContentView(v); downloadApk(); } @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case DOWN_UPDATE: mProgress.setProgress(progress); break; case DOWN_OVER: downloadDialog.dismiss(); installApk(); break; } } }; public UpdateManager(Context context) { this.mContext = context; } private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { "android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"}; // 申請所需的許可權 public static void verifyStoragePermissions(Context context) { try { //檢測是否有寫的許可權 int permission = ActivityCompat.checkSelfPermission(context, "android.permission.WRITE_EXTERNAL_STORAGE"); if (permission != PackageManager.PERMISSION_GRANTED) { // 沒有寫的許可權,去申請寫的許可權,會彈出對話方塊 ActivityCompat.requestPermissions((Activity) context, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } } catch (Exception e) { e.printStackTrace(); } } // 申請所需的許可權 private Runnable mdownApkRunnable = new Runnable() { @Override public void run() { try { URL url = new URL(apkurl); HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.connect(); int length = conn.getContentLength(); InputStream is = conn.getInputStream(); // 假如大於6.0申請所需的許可權 if (Build.VERSION.SDK_INT >= 23) { //假如大於23則申請許可權 verifyStoragePermissions(mContext); if (SdCardUtils.checkSdCard() == true) { SdCardUtils.createFileDir(SdCardUtils.FILEDIR); SdCardUtils.createFileDir(SdCardUtils.FILEDIR + "/" + SdCardUtils.FILEPHOTO); } else { Toast.makeText(mContext, "建立資料夾失敗SD卡不可用", Toast.LENGTH_LONG).show(); } } else { //否則則直接建立資料夾 SdCardUtils.createFileDir(SdCardUtils.FILEDIR); SdCardUtils.createFileDir(SdCardUtils.FILEDIR + "/" + SdCardUtils.FILEPHOTO); } File file1 = new File(savePath1); if (!file1.exists()) { file1.mkdir(); } File file = new File(SdCardUtils.getSdApkPath()); if (!file.exists()) { file.mkdir(); } String apkFile = SdCardUtils.getSdApkPath() + "/" + saveFileName; File ApkFile = new File(apkFile); if (ApkFile.isFile() && ApkFile.exists()) { ApkFile.delete(); } ApkFile.createNewFile(); FileOutputStream fos = new FileOutputStream(apkFile); int count = 0; byte buf[] = new byte[1024]; do { int numread = is.read(buf); count += numread; progress = (int) (((float) count / length) * 100); // 更新進度 mHandler.sendEmptyMessage(DOWN_UPDATE); if (numread <= 0) { // 下載完成通知安裝 mHandler.sendEmptyMessage(DOWN_OVER); break; } fos.write(buf, 0, numread); fos.flush(); } while (!interceptFlag);// 點選取消就停止下載. fos.close(); is.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; // 下載apk private void downloadApk() { downLoadThread = new Thread(mdownApkRunnable); downLoadThread.start(); } // 安裝apk private void installApk() { File apkFile = new File(SdCardUtils.getSdApkPath() + "/" + saveFileName); if (!apkFile.exists()) { return; } Intent i = new Intent(Intent.ACTION_VIEW); // 新加的開啟詢問 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.setDataAndType(Uri.parse("file://" + apkFile.toString()), "application/vnd.android.package-archive"); mContext.startActivity(i); } }
Sd卡建立檔案工具類;
import android.os.Environment; import android.util.Log; import java.io.File; /** * 建立檔案工具類 * Created by admin on 2018/6/14. */ public class SdCardUtils { private String[] permissions = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE}; private static final int REQUEST_1 = 1; // 專案檔案根目錄 public static final String FILEDIR = "QiXiuBaoDian"; // 專案APK目錄 public static final String FILEPHOTO = "updatedemo"; // 應用程式圖片存放 public static final String FILEIMAGE = "/images"; // 應用程式快取 public static final String FILECACHE = "/cache"; // 使用者資訊目錄 public static final String FILEUSER = "user"; private static String path; /* * 檢查sd卡是否可用 * getExternalStorageState 獲取狀態 * Environment.MEDIA_MOUNTED 直譯 環境媒體登上 表示,當前sd可用 */ public static boolean checkSdCard() { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) //sd卡可用 return true; else //當前sd卡不可用 return false; } /* * 獲取sd卡的檔案路徑 * getExternalStorageDirectory 獲取路徑 */ public static String getSdPath() { return Environment.getExternalStorageDirectory() + "/"; } /* * 建立一個資料夾 */ public static void createFileDir(String fileDir) { path = getSdPath() + fileDir; File path1 = new File(path); if (!path1.exists()) { path1.mkdirs(); Log.i("yang", "我被建立了"); Log.e("path", path); } } public static String getSdApkPath() { return path; } }
應用:
/** * 版本更新 */ @SuppressLint("StaticFieldLeak") class UpgradeTask extends AsyncTask<Void, Void, UpgradeResponse> { @Override protected UpgradeResponse doInBackground(Void... params) { return DataInterface.upgradeResponse(); } @Override protected void onPostExecute(UpgradeResponse upgradeResponse) { String packageName = getPackageName(); int versionCode = 0; try { versionCode = getPackageManager().getPackageInfo(packageName, 0).versionCode; } catch (PackageManager.NameNotFoundException e) { return; } if (upgradeResponse != null) { int newver = upgradeResponse.getApp_ver();//新版本號 String sesc = upgradeResponse.getDesc();//更新內容 String apk = upgradeResponse.getUrl();//更新地址 if (versionCode < newver) { UpdateManager updateManager = new UpdateManager(MainActivity.this); updateManager.checkUpdateInfo(apk, sesc); } } else { Toast.makeText(MainActivity.this, "伺服器開小差啦,請稍後再試", Toast.LENGTH_SHORT).show(); } } }