本文记录实现app应用内升级功能中遇到的问题
常见的app应用内升级常见步骤为:
1,调用后台接口,比对当前版本号查看是否有更新
2,下载最新的apk
3,覆盖安装
问题:安装未知应用权限
先上代码,包含2个方法
- 判断是否允许应用安装apk权限
- 没权限的话,跳转打开设置页面
/**
* 是否允许 安装app
* @param context
* @return true:允许; false:不允许
*
* 注意需要声明该权限
* <!--8.0 安装权限-->
* <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
*/
public static boolean isAgreeInstallPackage(Context context) {
boolean isAgree = true;
//8.0以上 需要判断
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isAgree = context.getPackageManager().canRequestPackageInstalls();
}
return isAgree;
}
/**
* 前往设置,开启 安装apk权限
* @param context
*/
public static void openInstallSetting(Activity context) {
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
context.startActivityForResult(intent,SetInstallRequestCode);
}

在 Android 8.0 以上,安装apk需要注意多了一个 安装未知应用 权限,故需要兼容一下8.0以上,需要注意的是,检测该权限需要注意在AndroidManifest
中声明:<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
问题:下载完成apk,调起安装页面
先贴上调起apk安装界面的代码
public class InstallApkUtils {
/**
* @param apkFile : 需要安装的apk
* @return
* @Description 安装apk
*/
public static void installApk(Context context,File apkFile) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//需要开新的任务栈,不然安装完成无法弹出“完成”、“打开”页面
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0+以上版本
Uri apkUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID+ ".fileprovider", apkFile); //包名.fileprovider
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
}
context.startActivity(intent);
}
}
这里需要处理 Android7.0 以上的兼容问题,Android 7.0以上需要通过 FileProvider 来获取 Uri。FileProvider使用下面会介绍。附上:Google-FileProvider
注意:上面的BuildConfig.APPLICATION_ID
其实就是你的包名,我在下面声明FileProvider也使用的是包名
FileProvider使用
1,AndroidManifest.xml 创建一个FileProvider
<!--${applicationId} 是项目包名-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
注意:android:authorities="你的包名.fileprovider"
替换,后面的不要动
2,Res 目录下创建 xml文件夹, 创建一个 file_paths.xml

注意:这个xml,命名只要跟
AndroidManifest.xml
resource中的对应即可。(我创建的名字为:file_paths)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/DCIM/camerademo目录-->
<external-path name="name" path="DCIM/camerademo" />
<!--代表外部存储区域的根目录下的文件 Environment.getExternalStorageDirectory()/Pictures/camerademo目录-->
<external-path name="name" path="Pictures/camerademo" />
<!--代表app 私有的存储区域 Context.getFilesDir()目录下的images目录 /data/user/0/com.hm.camerademo/files/images-->
<files-path name="name" path="images" />
<!--代表app 私有的存储区域 Context.getCacheDir()目录下的images目录 /data/user/0/com.hm.camerademo/cache/images-->
<cache-path name="name" path="images" />
<!--代表app 外部存储区域根目录下的文件 Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)目录下的Pictures目录-->
<!--/storage/emulated/0/Android/data/com.hm.camerademo/files/Pictures-->
<external-files-path name="name" path="Pictures" />
<!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的images目录-->
<!--/storage/emulated/0/Android/data/com.hm.camerademo/cache/images-->
<external-cache-path name="name" path="images" />
</paths>
比如,我要获取到下面外部存储目录的Uri
String fileName = Environment.getExternalStorageDirectory() +File.separator+"down_apk"+File.separator + "xxxx.apk";
需要在file_paths.xml中添加如下目录,即可:
<external-path
name="name"
path="down_apk"/>
如果报错的话,多半是目录跟File路径不对应,请仔细检查
网友评论