Android版本更新,兼容7.0 8.0

释放双眼,带上耳机,听听看~!

Android版本更新 借鉴: Android版本更新知识(检测、升级)总结

先说遇到的问题,7.0,8.0及以上版本采用旧方法更新,首先无法安装,添加响应权限之后,更新包安装之后,点击打开图标,应用无反应,点击图标打开正常。

解决方案:

1.版本更新的策略:比对 versionCode 如服务器versionCode>本地安装包
则弹出升级提示框,进行应用下载。

添加网络权限,在application标签下添加 provider,指定: android:resource=”@xml/filepaths”

mainest

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 8.0安装不了的问题 权限-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<application...>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
...
</application>

res xml文件夹下添加:filepaths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths
xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external" path="."/>
</paths>

2.代码如下:

SplashActivity中
获取权限  verifyStoragePermissions(this);//
versionName= ApkUtil.packageName(mContext);
versionCode= ApkUtil.packageCode(mContext);
mHttpUtil.getMobileAppInfo(new ProgressSubscriber<VersionModel>(mContext,true) {
@Override
public void next(VersionModel model) {
String code=model.getCode();
if(code.equals(Constant.SUCCESS)){
VersionModel.AppInfo app=model.getAppInfo();
int resultVersionCode=Integer.parseInt(app.getVersionCode());
String resultVersionName=app.getVersionName();
Log.d("MyInfo","resultVersionCode=="+resultVersionCode+",versionCode="+versionCode);
Log.d("MyInfo","resultVersionName=="+resultVersionName+",versionName="+versionName);
if(resultVersionCode>versionCode){//服务器版本大于本地版本
showUpdateDialog(model,app);
}else{//跳转到登录页面
Message msg=handler.obtainMessage();
handler.sendMessage(msg);
}
}else{//跳转到登录页面
Message msg=handler.obtainMessage();
handler.sendMessage(msg);
}
}
},0);

动态申明权限:

//动态获取内存存储权限
public static void verifyStoragePermissions(Activity activity) {
/**
* 动态获取权限,Android 6.0 新特性,一些保护权限,除了要在AndroidManifest中声明权限,还要使用如下代码动态获取
*/
if (Build.VERSION.SDK_INT >= 23) {
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//验证是否许可权限
for (String str : permissions) {
if (activity.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
activity.requestPermissions(permissions, REQUEST_CODE_CONTACT);
return;
}
}
}
}

3.更新提示框:

/**
* 弹出提示更新的dialog
*/
private void showUpdateDialog(final VersionModel model,final VersionModel.AppInfo app) {
final int forceUpdate=app.getForceUpdate();
String remark=app.getRemark();
UpdateDialog updateDialog=new UpdateDialog(mContext,R.style.progress_dialog);
updateDialog.setOnPositiveListener(new OnPositiveListener() {
@Override
public void onPositive() {
//从服务器端下载最新apk
downloadApk(model);
}
});
updateDialog.setOnNegativeListener(new OnNegativeListener() {
@Override
public void onNegative() {
if(forceUpdate==1){//跳转到登录页面
System.exit(0);
}else{//返回
Message msg=handler.obtainMessage();
handler.sendMessage(msg);
}
}
});
updateDialog.show();
}

4.下载应用:(进度条显示 多少M)
关键代码
dialog.setProgressNumberFormat(“%1d Mb /%2d Mb”);//这里设置的是进度条下面显示的文件大小和下载了多

/**
* 从服务器端下载最新apk
*/
private void downloadApk(VersionModel model) {
//显示下载进度
ProgressDialog dialog = new ProgressDialog(this);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
dialog.setTitle("版本更新");
dialog.setMessage("正在下载中,请稍候...");
dialog.setProgressNumberFormat("%1d Mb /%2d Mb");//这里设置的是进度条下面显示的文件大小和下载了多
dialog.show();
String url=model.getPreUrl()+model.getAppInfo().getApkUri();
Log.d("MyInfo","updateApkUrl=="+url);
//访问网络下载apk
new Thread(new DownloadApk(dialog,url)).start();
}

5.开启线程下载应用

/**
* 访问网络下载apk
*/
private class DownloadApk implements Runnable {
private ProgressDialog dialog;
private String url;
InputStream is;
FileOutputStream fos;
public DownloadApk(ProgressDialog dialog,String url) {
this.dialog = dialog;
this.url=url;
}
@Override
public void run() {
Log.d("MyInfo","url=="+url);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().get().url(url).build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
Log.d("MyInfo", "开始下载apk------");
//获取内容总长度
long contentLength = response.body().contentLength();
//设置最大值
//                    dialog.setMax((int) contentLength);
dialog.setMax((int)contentLength/1024/1024);
//保存到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);
dialog.setProgress(progress/1024/1024);
} catch (InterruptedException e) {
Message msg = handler.obtainMessage();
msg.what = SHOW_ERROR;
msg.obj = "ERROR:10002";
handler.sendMessage(msg);
}
}
Log.d("MyInfo", "下载apk完成------");
//下载完成,提示用户安装
autoInstallApk(mContext,apkFile);
}
} catch (IOException e) {
Log.d("MyInfo","error=="+e.getMessage());
Message msg = handler.obtainMessage();
msg.what = SHOW_ERROR;
msg.obj = "ERROR:10003";
handler.sendMessage(msg);
} 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();
}
}

6.应用安装,此处代码与之前的写法略有不同,(适配7.0 8.0的方案)

private void autoInstallApk(Context context, File file) {
//Intent intent = new Intent(Intent.ACTION_VIEW)//以前的写法,替换为下面的
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {// 小于7.0
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} else {
//以下语句不添加,下载之后点击打开无反应
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
// 声明需要的临时的权限
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// 第二个参数,即第一步中配置的authorities
Uri contentUri = FileProvider.getUriForFile(SplashActivity.this, BuildConfig.APPLICATION_ID + ".fileprovider", file);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
}
context.startActivity(intent);
}

人已赞赏
Android文章

安卓进阶第五篇之常见动画的使用

2020-2-23 7:44:46

Android文章

Android 事件分发机制(图解)

2020-2-23 11:57:32

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索