Android7.0调用照相、相册总结
作者:互联网
前言
前段时间写了一个调用Camera拍照,并从图库中选取图片的小程序,但是当它在7.0的系统上运行时,直接崩溃,根本不能使用。
原来Android5.0、6.0、7.0增加了很多特性,我并没有对此进行适配,从而导致了很多错误。
异常错误:
android.os.FileUriExposedException:
file:///storage/emulated/0/camera/1513393885728.jgp
exposed beyond app through ClipData.Item.getUri()
java.lang.SecurityException: Permission Denial:
reading android.support.v4.content.FileProvider uri content://com.zxl.test_picture_camera/camera_gallery/camera/1514101205911.jgp
from pid=5847, uid=10048 requires the provider be exported, or grantUriPermission()
java.lang.SecurityException:
Permission Denial: writing android.support.v4.content.FileProvider uri content://com.zxl.test_picture_camera/camera_gallery/camera/1514101317846.jgp
from pid=8336, uid=10048 requires the provider be exported, or grantUriPermission()
功能点:
-权限校验
-权限申请
-赋予第三方应用Uri权限
-打开照相机
-打开相册
-裁剪图片
代码地址:https://github.com/zxlworking/test_picture_carmera
1.权限校验
public static boolean checkPermission(Context context, String permissionStr){ boolean result = true; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ result = context.checkSelfPermission(permissionStr) == PackageManager.PERMISSION_GRANTED; }else{ result = PermissionChecker.checkSelfPermission(context,permissionStr) == PackageManager.PERMISSION_GRANTED; } return result;}
1.1 Camera权限校验
Manifest.permission.CAMERA
public static boolean checkCameraPermission(Context context){ return checkPermission(context, Manifest.permission.CAMERA);}
1.2 外部存储目录权限校验
Manifest.permission.READ_EXTERNAL_STORAGE
Manifest.permission.WRITE_EXTERNAL_STORAGE
public static boolean checkSDCardPermission(Context context){ return checkPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) && checkPermission(context,Manifest.permission.WRITE_EXTERNAL_STORAGE);}
2.权限申请
AndroidManifest.xml添加权限:
android.permission.CAMERA
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
在Android6.0以后有的权限需要主动去申请
requestPermissions
@RequiresApi(api = Build.VERSION_CODES.M)public static void requestPermission(Activity activity, String[] permissionStrs, int requestCode){ activity.requestPermissions(permissionStrs,requestCode);}
2.1 Camera权限申请
requestPermissions Manifest.permission.CAMERA
@RequiresApi(api = Build.VERSION_CODES.M)public static void requestCameraPermission(Activity activity, int requestCode){ requestPermission(activity,new String[]{Manifest.permission.CAMERA},requestCode);}
2.2 外部存储目录权限申请
requestPermissions Manifest.permission.READ_EXTERNAL_STORAGE
Manifest.permission.WRITE_EXTERNAL_STORAGE
@RequiresApi(api = Build.VERSION_CODES.M)public static void requestSDCardPermission(Activity activity, int requestCode){ requestPermission(activity,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);}
2.3 权限申请结果回调
通过Activity回调接口获取结果
onRequestPermissionsResult
@RequiresApi(api = Build.VERSION_CODES.M)@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults);}
2.4 权限申请结果校验
PackageManager.PERMISSION_GRANTED
public static boolean checkRequestPermissionsResult(int[] grantResults){ if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ return true; } return false;}
3.赋予第三方应用Uri权限
当获取到图片后,需要进行裁剪,这需要将原图片、裁剪后到图片的保存路径都要给裁剪应用,并且要封装成Uri通过Intent传递,在Android7.0增加了第三方应用读取Uri的权限校验
3.1 配置共享文件目录资源文件
在res/xml下新建资源文件file_path.xml
files-path与Context.getFilesDir()相同的目录
external-path与Environment.getExternalStorageDirectory()相同的目录
cache-path与getCacheDir()相同的目录
name为别名
path为表示对应类型的根目录
<resources> <paths> <files-path name="camera_gallery" path=""/> <external-path name="camera_gallery" path=""/> <cache-path name="camera_gallery" path=""/> paths> resources>
3.2 配置provider
AndroidManifest.xml添加provider
<providerandroid:authorities="com.zxl.test_picture_camera"android:name="android.support.v4.content.FileProvider"android:exported="false"android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_path"/>provider>
3.3 生成Uri
FileProvider.getUriForFile
private static Uri getFileUri(Context context,String filePath){ Uri mUri = null; File mFile = new File(filePath); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ mUri = FileProvider.getUriForFile(context,"com.zxl.test_picture_camera",mFile); }else{ mUri = Uri.fromFile(mFile); } return mUri;}
3.4 赋予Uri读取权限
Intent.FLAG_GRANT_READ_URI_PERMISSION
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ mIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); }
3.5 赋予Uri写权限
通过Intent找到符合的要打开的Activity
activity.grantUriPermission
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
List resInfoList = queryActivityByIntent(activity,mIntent);if (resInfoList.size() == 0) { showMsg(activity, "没有合适的应用程序"); return;}Iterator resInfoIterator = resInfoList.iterator();while (resInfoIterator.hasNext()) { ResolveInfo resolveInfo = (ResolveInfo) resInfoIterator.next(); String packageName = resolveInfo.activityInfo.packageName; activity.grantUriPermission(packageName, desUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);}private static List<ResolveInfo> queryActivityByIntent(Activity activity, Intent intent){ List resInfoList = activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); return resInfoList;}
4.打开照相机
public static void startCamera(Activity activity,int requestCode,String filePath){ if(hasSdcard()){ Intent mOpenCameraIntent = new Intent(); mOpenCameraIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); Uri desUri = getFileUri(activity,filePath); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ //已申请camera权限 //mOpenCameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } mOpenCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,desUri); activity.startActivityForResult(mOpenCameraIntent,requestCode); }else{ showMsg(activity,"设备没有SD卡!"); }}
5.打开相册
public static void startGallery(Activity activity,int requestCode){ if(hasSdcard()){ Intent mOpenGalleryIntent = new Intent(Intent.ACTION_GET_CONTENT); mOpenGalleryIntent.setType("image/*"); activity.startActivityForResult(mOpenGalleryIntent,requestCode); }else{ showMsg(activity,"设备没有SD卡!"); }}
6.裁剪图片
public static void startCropImage(Activity activity, Uri originUri, Uri desUri, int aspectX, int aspectY, int outputX, int outputY, int requestCode){ Intent mIntent = new Intent(); mIntent.setAction("com.android.camera.action.CROP"); mIntent.setDataAndType(originUri,"image/*"); List resInfoList = queryActivityByIntent(activity,mIntent); if (resInfoList.size() == 0) { showMsg(activity, "没有合适的应用程序"); return; } Iterator resInfoIterator = resInfoList.iterator(); while (resInfoIterator.hasNext()) { ResolveInfo resolveInfo = (ResolveInfo) resInfoIterator.next(); String packageName = resolveInfo.activityInfo.packageName; activity.grantUriPermission(packageName, desUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ mIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } mIntent.putExtra("crop","true"); mIntent.putExtra("aspectX",aspectX); mIntent.putExtra("aspectY",aspectY); mIntent.putExtra("outputX",outputX); mIntent.putExtra("outputY",outputY); mIntent.putExtra("scale",true); mIntent.putExtra(MediaStore.EXTRA_OUTPUT, desUri); mIntent.putExtra("return-data",false); mIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); mIntent.putExtra("noFaceDetection",true); activity.startActivityForResult(mIntent,requestCode);}
标签:VERSION,相册,permission,mIntent,照相,Android7.0,requestCode,Intent,activity 来源: https://blog.51cto.com/u_15091798/2782946