Android更新apk升级时出现FileUriExposedException: xxx.apk exposed beyond app through Intent.getData()的解决方法
1、获取包信息
PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
2、发送包名和版本号,检测是否有更新
String versionUrl = webUrl + "?package=" + packageInfo.packageName + "&version=" + packageInfo.versionCode;
URL url = new URL(versionUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(5000);
int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) {
InputStream inputStream = urlConnection.getInputStream();
byte[] b = new byte[1024];
int len = 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while ((len = inputStream.read(b)) > -1) {
byteArrayOutputStream.write(b, 0, len);
}
String result = byteArrayOutputStream.toString();
JSONObject jsonObject = new JSONObject(result);
if (jsonObject.has("data") && jsonObject.get("data") instanceof JSONObject) {
versionJsonObject = jsonObject.getJSONObject("data");
int newVersionCode = versionJsonObject.getInt("version");
if (newVersionCode > packageInfo.versionCode) {
//显示更新提示
}
}}
3、显示更新对话框,检测文件保存权限,下载apk
Dialog dialog = new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("是否更新版本?")
.setMessage(info)
.setPositiveButton("确认",
new DialogInterface.OnClickListener() {
@Overridepublic void onClick(DialogInterface dialog, int which) {
//检测文件保存权限
if (Build.VERSION.SDK_INT >= 23) {
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//验证是否许可权限
for (String str : permissions) {
if (checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
requestPermissions(permissions, 101);
return;
}
}
downFile();
}else{
downFile();
}
}
})
.setNegativeButton("下次再说",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
dialog.cancel();
}
}).create();
dialog.show();4、保存权限回调,下载apk
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 101: {
if (grantResults != null && grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 权限被用户同意,可以做你要做的事情了。
downFile();
} else {
// 权限被用户拒绝了,可以提示用户,关闭界面等等。
}
return;
}
}}
5、下载apk
URL url = new URL(apkUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
FileOutputStream fileOutputStream = null;
File file = new File(Environment.getExternalStorageDirectory(), "a.apk");
if (inputStream != null) {
fileOutputStream = new FileOutputStream(file);
byte[] b = new byte[1024];
int len = 0;
while ((len = inputStream.read(b)) > -1) {
fileOutputStream.write(b, 0, len);
}
}
fileOutputStream.flush();
if (fileOutputStream != null) {
fileOutputStream.close();}
6、安装apk,8.0以上系统设置安装未知来源权限
boolean haveInstallPermission;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
//先判断是否有安装未知来源应用的权限
haveInstallPermission = getPackageManager().canRequestPackageInstalls();
if(!haveInstallPermission){//弹框提示用户手动打开
toInstallPermissionSettingIntent();}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void toInstallPermissionSettingIntent() {
Uri packageURI = Uri.parse("package:"+getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,packageURI);
startActivityForResult(intent, 1);
}@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == 1) {
installApk();
}
}7、安装apk
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(MainActivity.this, "包名.fileprovider", mFile);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(mFile), "application/vnd.android.package-archive");
}startActivity(intent);
8、安装未知来源权限
AndroidManifest.xml 里添加
<provider
AS3.6.1中会提示无法引用android.support.v4包
android:name="android.support.v4.content.FileProvider"
改为
android:name="androidx.core.content.FileProvider"
android:authorities="包名.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" /></provider>
res里新建xml文件夹,里新建file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="Android/data/包名/" name="files_root" />
<external-path path="." name="external_storage_root" />
</paths>