Android实现版本更新和自动安装
16lz
2021-01-25
直接运行的项目和打包的项目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; }}
以上实例如有不足请指出. 更多相关文章
- Android第三方开源对话消息提示框:SweetAlertDialog(sweet-alert-d
- cordova+vue构建iOS APP
- Android(安卓)- 获取版本号、判断当前是否为debug模式,判断当前应
- Android系统编译so库提示error undefined reference to '__andro
- android相关插件下载以及安装
- Android(安卓)Toast提示封装实例代码
- Android(安卓)SDK和NDK的linux环境变量配置
- Android(安卓)Studio Cannot find local variable
- [Android实例] android中进行https连接的方式的详解 (转发)