Android 7.0中拍照和图片裁剪适配的问题详解
程序员文章站
2023-12-19 09:25:58
前言
android 7.0系统发布后,拿到能升级的nexus 6p,就开始了7.0的适配。发现在android 7.0以上,在相机拍照和图片裁剪上,可能会碰到以下一些错...
前言
android 7.0系统发布后,拿到能升级的nexus 6p,就开始了7.0的适配。发现在android 7.0以上,在相机拍照和图片裁剪上,可能会碰到以下一些错误:
process: com.yuyh.imgsel, pid: 22995 // 错误1 android.os.fileuriexposedexception: file:///storage/emulated/0/android/data/com.yuyh.imgsel/cache/1486438962645.jpg exposed beyond app through clipdata.item.geturi() // 错误2 android.os.fileuriexposedexception: file:///storage/emulated/0/dcim/rxgalleryfinal/img_20161018180127.jpg exposed beyond app through intent.getdata()
主要是由于在android 7.0以后,用了content uri 替换了原本的file uri,故在targetsdkversion=24
的时候,部分 “`uri.fromfile()
“` 方法就不适用了。 **file uri 与 content uri 的区别** - file uri 对应的是文件本身的存储路径 - content uri 对应的是文件在content provider的路径 所以在android 7.0 以上,我们就需要将file uri转换为 content uri。
具体转换方法如下:
/** * 转换 content:// uri * * @param imagefile * @return */ public uri getimagecontenturi(file imagefile) { string filepath = imagefile.getabsolutepath(); cursor cursor = 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 getcontentresolver().insert( mediastore.images.media.external_content_uri, values); } else { return null; } } }
那么,我们在裁剪的时候,应该如下调用:
private void crop(string imagepath) { file file = new file("xxx.jpg"); cropimagepath = file.getabsolutepath(); intent intent = new intent("com.android.camera.action.crop"); intent.setdataandtype(getimagecontenturi(new file(imagepath)), "image/*"); intent.putextra("crop", "true"); intent.putextra("aspectx", config.aspectx); intent.putextra("aspecty", config.aspecty); intent.putextra("outputx", config.outputx); intent.putextra("outputy", config.outputy); intent.putextra("scale", true); intent.putextra("return-data", false); intent.putextra(mediastore.extra_output, uri.fromfile(file)); intent.putextra("outputformat", bitmap.compressformat.jpeg.tostring()); intent.putextra("nofacedetection", true); startactivityforresult(intent, image_crop_code); }
这样就解决了裁剪的问题,但是!!拍照的时候就会出现以下错误:
intent cameraintent = new intent(mediastore.action_image_capture); if (cameraintent.resolveactivity(getactivity().getpackagemanager()) != null) { tempfile = new file(fileutils.createrootpath(getactivity()) + "/" + system.currenttimemillis() + ".jpg"); logutils.e(tempfile.getabsolutepath()); fileutils.createfile(tempfile); cameraintent.putextra(mediastore.extra_output, uri.fromfile(tempfile)); startactivityforresult(cameraintent, request_camera); }
android.os.fileuriexposedexception: file:///storage/emulated/0/android/data/com.yuyh.imgsel/cache/1486438962645.jpg exposed beyond app through clipdata.item.geturi()
这是因为拍照存储的文件,也需要以content uri的形式,故采用以下办法解决:
step.1
修改androidmanifest.xml
<application ...> <provider android:name="android.support.v4.content.fileprovider" android:authorities="{替换为你的包名}.provider" android:exported="false" android:granturipermissions="true"> <meta-data android:name="android.support.file_provider_paths" android:resource="@xml/provider_paths"/> </provider> </application>
step.2
在res/xml/下新建provider_paths.xml文件
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="."/> </paths>
step.3
修改拍照时的参数
cameraintent.putextra(mediastore.extra_output, fileprovider.geturiforfile(getactivity(),buildconfig.application_id + ".provider", tempfile)); //uri.fromfile(tempfile)
总结
好了,以上就是这篇文章的全部内容了,希望本文的内容对各位android开发者们能带来一定的帮助,如果有疑问大家可以留言交流。