Android7.0适配心得(一)_拍照兼容
2017-12-04 13:37
399 查看
一、在Android7.0上调用系统相机拍照,裁切照片的适配
在Android7.0之前,如果你想调用系统相机拍照可以通过以下代码来进行:
File file = new File(Environment.getExternalStorageDirectory(), "/pic/" + System.currentTimeMillis() + ".jpg"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); } Uri imageUri = Uri.fromFile(file); Intent intent = new Intent(); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照 intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI startActivityForResult(intent, 1);
在Android7.0上使用上述方式调用系统相拍照会抛出如下异常:
android.os.FileUriExposedException: file:////storage/emulated/0/temp/1474956193735.jpg exposed beyond app through Intent.getData() at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799) at android.net.Uri.checkFileUriExposed(Uri.java:2346) at android.content.Intent.prepareToLeaveProcess(Intent.java:8933) at android.content.Intent.prepareToLeaveProcess(Intent.java:8894) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517) at android.app.Activity.startActivityForResult(Activity.java:4223) at android.app.Activity.startActivityForResult(Activity.java:4182)
这是由于Android7.0执行了“StrictMode API 政策禁”的原因,不过可以用FileProvider来解决这一问题,
现在我们就来一步一步的解决这个问题。
使用FileProvider
1、在manifest清单文件中注册provider
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.bj.bs.fileprovider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
心得:exported:要求必须为false,为true则会报安全异常。grantUriPermissions:true,表示授予 URI 临时访问权限。
2、指定共享的目录
为了指定共享的目录我们需要在资源(res)目录下创建一个xml目录,然后创建一个名为“file_paths”(名字可以随便起,只要和在manifest注册的provider所引用的resource保持一致即可)的资源文件,内容如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <paths> <external-path path="" name="camera_photos" /> </paths> </resources>
files-path 代表的根目录: Context.getFilesDir()
external-path 代表的根目录: Environment.getExternalStorageDirectory()
cache-path 代表的根目录: getCacheDir()
心得:上述代码中path=”“,是有特殊意义的,它代码根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了,如果你将path设为path=”pictures”,
那么它代表着根目录下的pictures目录(eg:/storage/emulated/0/pictures),如果你向其它应用分享pictures目录范围之外的文件是不行的。
3、使用FileProvider
上述准备工作做完之后,现在我们就可以使用FileProvider了。
还是以调用系统相机拍照为例,我们需要将上述拍照代码修改为如下:
File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg"); if (!file.getParentFile().exists())file.getParentFile().mkdirs(); Uri imageUri = FileProvider.getUriForFile(context, "com.bj.bs.fileprovider", file); // 通过FileProvider创建一个content类型的Uri Intent 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);//将拍取的照片保存到指定URI startActivityForResult(intent, 1);
上述代码中主要有两处改变:
将之前Uri的scheme类型为file的Uri改成了有FileProvider创建一个content类型的Uri。
添加了intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);来对目标应用临时授权该Uri所代表的文件。
心得:上述代码通过FileProvider的Uri getUriForFile (Context context, String authority, File file)
静态方法来获取Uri,该方法中authority参数就是清单文件中注册provider的android:authorities=”com.jph.takephoto.file
c5d9
provider”。
对Web服务器如tomcat,IIS比较熟悉的小伙伴,都只知道为了网站内容的安全和高效,Web服务器都支持为网站内容设置一个虚拟目录,其实FileProvider也有异曲同工之处。
将getUriForFile方法获取的Uri打印出来如下:
content://com.bj.bs.fileprovider/camera_photos/temp/1474960080319.jpg`。
其中camera_photos就是file_paths.xml中paths的name。
因为上述指定的path为path=”“,所以content://com.bj.bs.fileprovider/camera_photos/代表的真实路径就是根目录,即:/storage/emulated/0/。
content://com.bj.bs.fileprovider/camera_photos/temp/1474960080319.jpg代表的真实路径是:/storage/emulated/0/temp/1474960080319.jpg。
裁切照片
在Android7.0之前,你可以通过如下方法来裁切照片:File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg"); if (!file.getParentFile().exists())file.getParentFile().mkdirs(); Uri outputUri = Uri.fromFile(file); 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 detection startActivityForResult(intent, 2);
和拍照一样,上述代码在Android7.0上同样会引起android.os.FileUriExposedException异常,解决办法就是上文说说的使用FileProvider。
然后,将上述代码改为如下即可:
File file=new File(Environment.getExternalStorageDirectory(), "/temp/"+System.currentTimeMillis() + ".jpg"); if (!file.getParentFile().exists())file.getParentFile().mkdirs(); Uri outputUri = FileProvider.getUriForFile(context, "com.jph.takephoto.fileprovider",file); Uri imageUri=FileProvider.getUriForFile(context, "com.jph.takephoto.fileprovider", new File("/storage/emulated/0/temp/1474960080319.jpg");//通过FileProvider创建一个content类型的Uri Intent 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 detection startActivityForResult(intent, 2);
源码
http://download.csdn.net/download/u010302765/10144547相关文章推荐
- Android进阶封装之一个类实现兼容Android 6.0权限、适配Android7.0 拍照: 相机与相册上传图片就用我好啦!
- Android进阶封装之一个类实现兼容Android 6.0权限、适配Android7.0 拍照!
- Android7.0适配教程,心得
- android7.0拍照裁剪兼容
- Android7.0适配心得
- [置顶] Android7.0适配之FileProvide(拍照,裁剪,应用安装)
- Android7.0(Android N)适配心得教程
- Android7.0适配的一些小心得
- PopUpWindow位置指定对小米4(Android7.0)兼容适配
- Android7.0适配教程,心得
- Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)
- Android7.0 适配心得
- 适配Android7.0的拍照,选取照片
- Android7.0(Android N)适配教程,心得
- Android7.0适配教程,心得
- Android7.0适配心得
- Android7.0完美适配——FileProvider拍照裁剪全解析
- Android7.0(Android N)适配教程,心得
- Android7.0(Android N)适配教程,心得
- 【转】Android7.0适配心得