Android7.0权限适配
来源:互联网 发布:网络计算机培训 编辑:程序博客网 时间:2024/05/01 09:37
权限变化
Android从6.0开始对隐私的保护越来越注重,从6.0动态申请权限到Android7.0的“私有目录被限制访问”,虽然对用户保护的力度加大了,但是对于我们开发者来说,之前我们写的代码必须要适配到7.0了,很讨厌哦~下面我们具体讲一下关于7.0方方面面的变化
拍照
// 请求加载系统照相机 private static final int TAKE_PICTURE = 0x000001;// 跳转到系统照相机 Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //判断是否有系统相机 if(cameraIntent.resolveActivity(getActivity().getPackageManager()) != null){ // 设置系统相机拍照后的输出路径 // 创建临时文件 mTmpFile = HexAlbumFileUtils.createTmpFile(getActivity()); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N){//判断当前版本号 cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile)); startActivityForResult(cameraIntent, TAKE_PICTURE); }else { ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DATA, mTmpFile.getAbsolutePath()); Uri uri = getContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); } startActivityForResult(cameraIntent, TAKE_PICTURE); }else{ Toast.makeText(getActivity(), R.string.hexalbum_msg_no_camera, Toast.LENGTH_SHORT).show(); }
创建文件
public static File createTmpFile(Context context){ String state = Environment.getExternalStorageState(); if(state.equals(Environment.MEDIA_MOUNTED)){ // 已挂载 File pic = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); String fileName = "multi_image_"+timeStamp+""; File tmpFile = new File(pic, fileName+".jpg"); return tmpFile; }else{ File cacheDir = context.getCacheDir(); String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date()); String fileName = "multi_image_"+timeStamp+""; File tmpFile = new File(cacheDir, fileName+".jpg"); return tmpFile; } }
在7.0版本以前,我们打开相机保存图片通常方法为:
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile)); startActivityForResult(cameraIntent, TAKE_PICTURE);
但7.0版本后,由于Android7.0执行了“StrictMode API ”的原因,” StrictMode API 政策” 是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常。我们可以用下面的方法来实现
ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.DATA, mTmpFile.getAbsolutePath()); Uri uri = getContext().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
我们也可以通过使用FileProvider来实现打开相机保存图片
第一步:创建FileProvider
在清单文件创建:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.hexfuture.hexteacher.fileprovider" android:exported="false" android:grantUriPermissions="true"> <!-- 元数据 --> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
exported:要求必须为false,为true则会报安全异常。grantUriPermissions:true,表示授予 URI 临时访问权限。
第二步:指定共享的目录:
在res/xml文件下创建xml文件名字无所谓 (名字可以随便起,只要和在manifest注册的provider所引用的resource保持一致即可))file_paths.xml:
<resources> <paths> <external-path path="" name="camera_photos" /> </paths></resources>
上述代码中path=”“,是有特殊意义的,它代码根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了,如果你将path设为path=”pictures”,
那么它代表着共享根目录下的pictures目录(/storage/emulated/0/pictures)任何一个文件,如果你向其它应用分享pictures目录范围之外的文件是不行的。
第三步:使用FileProvider
Uri imageUri = FileProvider.getUriForFile(context, "com.hexfuture.hexteacher.fileprovider", mTmpFile);//通过FileProvider创建一个content类型的UriIntent intent = new Intent();intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URIstartActivityForResult(intent,TAKE_PICTURE);
这样我们就可以在7.0打开相机保存图片了,但sdk6.0以后,我们都需要动态申请权限.
裁剪图片
在7.0之前,我们调用系统裁剪:
Uri outputUri = Uri.fromFile(mTmpFile);Uri imageUri=Uri.fromFile(new File("/storage/emulated/0/temp/1474960080319.jpg"));Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(imageUri, "image/*");intent.putExtra("crop", "true");intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);intent.putExtra("scale", true);intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true); // no face detectionstartActivityForResult(intent,1008);
但在7.0以后我们需要使用fileprovide来进行裁剪图片
Uri outputUri = FileProvider.getUriForFile(context, "com.hexfuture.hexteacher.fileprovider",mTmpFile);Uri imageUri=FileProvider.getUriForFile(context, "com.hexfuture.hexteacher.fileprovider", new File("/storage/emulated/0/temp/1474960080319.jpg");//通过FileProvider创建一个content类型的UriIntent intent = new Intent("com.android.camera.action.CROP");intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.setDataAndType(imageUri, "image/*");intent.putExtra("crop", "true");intent.putExtra("aspectX", 1);intent.putExtra("aspectY", 1);intent.putExtra("scale", true);intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true); // no face detectionstartActivityForResult(intent,1008);
解析URI
在这我想讲一下URI的改变
4.4之前
Uri : content://media/extenral/images/media/17766
4.4及以后
Uri : content://com.android.providers.media.documents/document/image%3A82482
URI转path路径
public static String getRealFilePath(final Context context, final Uri uri ) { if ( null == uri ) return null; final String scheme = uri.getScheme(); String data = null; if ( scheme == null ) data = uri.getPath(); else if ( ContentResolver.SCHEME_FILE.equals( scheme ) ) { data = uri.getPath(); } else if ( ContentResolver.SCHEME_CONTENT.equals( scheme ) ) { //判断URI形式是4.4版本之前还是4.4版本及以后的 if (DocumentsContract.isDocumentUri(context, uri)) {//4.4及以后解析 String wholeID = DocumentsContract.getDocumentId(uri); // 使用':'分割 String id = wholeID.split(":")[1]; String[] projection = { MediaStore.Images.Media.DATA }; String selection = MediaStore.Images.Media._ID + "=?"; String[] selectionArgs = { id }; Cursor cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null); int columnIndex = cursor.getColumnIndex(projection[0]); if (cursor.moveToFirst()) { data = cursor.getString(columnIndex); } cursor.close(); }else {//4.4之前解析 Cursor cursor = context.getContentResolver().query( uri, new String[] { MediaStore.Images.ImageColumns.DATA }, null, null, null ); if ( null != cursor ) { if ( cursor.moveToFirst() ) { int index = cursor.getColumnIndex( MediaStore.Images.ImageColumns.DATA ); if ( index > -1 ) { data = cursor.getString( index ); } } cursor.close(); } } } return data; }
如果有什么问题,就可以问我
- Android7.0权限适配
- android7.0适配权限问题
- android7.0 权限获取
- Android7.0检查权限
- Android7.0文件访问权限
- Android7.0共享文件权限
- Android7.0适配心得
- Android7.0 适配心得
- Android7.0适配心得
- Android7.0的适配
- Android7.0适配总结
- Android7.0动态申请打电话的权限
- android7.0新特性--权限更改
- Android7.0 拍照 选择照片 权限 实现
- Android7.0 动态申请打电话的权限
- Android7.0适配教程与心得
- Android7.0适配教程与心得
- Android7.0(Android N)适配教程
- 考研英语
- [置顶] Android APK反编译就这么简单 详解(附图)
- Android开发之PathMeasure的基本用法
- 0020_Valid Parentheses
- Thymeleaf系列五 迭代,if,switch语法
- Android7.0权限适配
- python 格式化输出
- 使用脚本进行同行股票基本面对比效果
- python 相对导入
- dubbo 部分 配置的关系-dubbo github 官方案例
- Linux相关挂载操作
- PAT乙级真题及训练集(2)--1011. A+B和C (15)
- 【剑指offer-解题系列(57)】删除链表中重复的节点
- vpn 详细介绍(百度)