7.0 Build.VERSION_CODES.N 24
为什么要适配
在7.0中 ,Uri.from(file),可能会触发FileUriExposedException
和动态权限一样,如果target选择24以下是不需要适配的,但还是应该尽早适配
解决办法:在24及以上,使用content:// 替代 file:// (Uri.from(file))
适配步骤
1.在res下,新建一个xml目录,在其中创建一个任意名字的xml文件,如file_provider_paths.xml
xml说明
external-path 等同于 Environment.getExternalStorageDirectory()
如果将path设置为path=“pic”,则共享的文件限制为/storage/emulated/0/pic/
为空,则共享文件目录为storage/emulated/0/
代表设备的根目录new File("/");
代表context.getFilesDir()
代表context.getCacheDir()
代表Environment.getExternalStorageDirectory()
代表context.getExternalFilesDirs()
代表context.getExternalCacheDirs()
2.在Manifest文件中注册FileProvider对象
3.修改java代码,场景拍照,裁剪,安装apk
fp=context.getPackageName()+".fileprovider";
3.1 拍照
imgPath = FileUtil.generateImgePath();
File imgFile = new File(imgPath); //设置拍照后的图片的保存位置
Log.i("TAG", imgFile.getAbsolutePath());
Uri imgUri = null;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//通过FileProvider创建一个content类型的Uri
imgUri = FileProvider.getUriForFile(activity, fp, imgFile);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
imgUri = Uri.fromFile(imgFile);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
final Uri uri = imgUri;
activity.startActivityForResult(intent, new CallBackIntent() {
@Override
public void onResult(Intent data) {
if (data == null || data.getData() == null)
// ToastUtils.startShort(activity, "拍照数据返回为空");
Log.i("TAG", "拍照数据返回为空");
startPhotoZoom(uri, activity, new IntentCallBack() {
@Override
public void onIntent(Intent intent) {
callBack.onBitmap(getImageView(intent));
}
});
}
});
imgPath,就是拍照后图片保存的路径
3.2 裁剪
//适配7.0的uri,(文件uri转化为ContentUri)
public Uri getImageContentUri(Context context, File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID },
MediaStore.Images.Media.DATA + "=? ",
new String[] { filePath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (imageFile.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
如果是由相机或者相册之后调用裁减,无需转化uri
如果是单独使用裁减功能,则需要利用上述方法进行转化
private void cropPicture(Uri uri) {
Intent innerIntent = new Intent("com.android.camera.action.CROP");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
innerIntent.setDataAndType(uri, "image/*");
innerIntent.putExtra("crop", "true");
//不是1比1 主要是为了适配华为手机一比一时,裁减是圆形的
innerIntent.putExtra("aspectX", 9998);
innerIntent.putExtra("aspectY", 9999);
innerIntent.putExtra("outputX", 320);
innerIntent.putExtra("outputY", 320);
innerIntent.putExtra("return-data", true);
innerIntent.putExtra("scale", true);
activity.startActivityForResult(intent, new CallBackIntent() {
@Override
public void onResult(Intent data) {
callBack.onIntent(data);
//裁减后的图片
//Bitmap bitmap = data.getParcelableExtra("data");
}
});
}
3.3 安装apk
private void installAPK(UpdateInfo updateInfo) {
File apkfile = new File(mSavePath, updateInfo.getClientVersionName());
if (!apkfile.exists()) {
return;
}
String cmd = "chmod 777 " + apkfile.toString();
try {
Runtime.getRuntime().exec(cmd);
} catch (Exception e) {
e.printStackTrace();
}
// 通过Intent安装APK文件
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri apkUri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
apkUri = FileProvider.getUriForFile(getAppContext(),
BuildConfig.APPLICATION_ID + ".provider", apkFile);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
apkUri = Uri.fromFile(apkFile);
}
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
context.startActivity(i);
//关闭当前程序
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
}