1、权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、动态申请
a、文件读写权限:
//在这里动态申请文件读写权限
if (Build.VERSION.SDK_INT > 23) {
verifyStoragePermissions();
} else {
Log.d(TAG, "版本低于23,不需要申请文件读写权限");
}
//在大于23的android版本中,文件读写需要动态申请权限
private void verifyStoragePermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if ((this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) ||
(this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
} else {
Log.d(TAG, "已有权限,不需要再申请");
mHandler.sendEmptyMessage(PERMISSION_ALLOW);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 0x01: //动态申请的读写权限
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
mHandler.sendEmptyMessage(PERMISSION_ALLOW);
} else {
Toast.makeText(this, "用户没有同意文件读取权限!", Toast.LENGTH_LONG).show();
}
break;
default:
break;
}
}
b、未知来源安装:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean hasInstallPermission = isHasInstallPermissionWithO(this);
if (!hasInstallPermission) {
startInstallPermissionSettingActivity(this);
return;
} else {
// ToolsUtil.installApk(MainActivity.this, ToolsUtil.getApkDir() + "updateselftest.apk");
ToolsUtil.updateApp(MainActivity.this, ToolsUtil.getApkDir() + "updateselftest.apk");
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private boolean isHasInstallPermissionWithO(Context context) {
if (context == null) {
return false;
}
return context.getPackageManager().canRequestPackageInstalls();
}
/**
* 开启设置安装未知来源应用权限界面
*
* @param context
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private void startInstallPermissionSettingActivity(Context context) {
if (context == null) {
return;
}
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
((Activity) context).startActivityForResult(intent, REQUEST_CODE_APP_INSTALL);
}
安装apk的代码:
public static void updateApp(Context context, String apkPath) {
Log.e("install","new version" + apkPath);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {
Uri contentUri = MyProvider.getUriForFile(context,"com.joson.adphonelauncher1.fileProvider",new File(apkPath));
Log.e("install","new version " + contentUri);
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(contentUri,"application/vnd.android.package-archive");
}else{
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(new File(apkPath)),"application/vnd.android.package-archive");
}
context.startActivity(intent);
}
或者:
/**
* 安装APK
*
* @param context
* @param apkPath
*/
public static void installApk(Context context, String apkPath) {
if (context == null || TextUtils.isEmpty(apkPath)) {
return;
}
File file = new File(apkPath);
Intent intent = new Intent(Intent.ACTION_VIEW);
//判读版本是否在7.0以上
if (Build.VERSION.SDK_INT >= 24) {
//provider authorities
Uri apkUri = FileProvider.getUriForFile(context, "com.example.updateselftest.fileprovider", file);
//Granting Temporary Permissions to a URI
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
context.startActivity(intent);
}
注册provider:
<!--数据共享-->
<provider
android:name="com.joson.adphonelauncher.MyProvider"
android:authorities="com.joson.adphonelauncher1.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
name 可以用标准的v4 provider。
res下面建立xml / file_paths.xml:(叫什么文件都可以,但是和注册的地方要一致)
<?xml version="1.0" encoding="utf-8"?>
<paths>
<paths>
<external-path path="" name="download"/>
</paths>
</paths>
注1:因为我的代码是在试验中生成的,所以有的地方对应不一致,注意修改。
注2:如果还是会报错,请注意一下app是否有SYSTEM_UID,如果有,请移步:
https://blog.csdn.net/cau_eric/article/details/99859756