欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 7.0中拍照和图片裁剪适配的问题详解

程序员文章站 2024-02-12 22:11: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开发者们能带来一定的帮助,如果有疑问大家可以留言交流。