问题 使用Android 6.0未经许可捕获图像


我需要让用户使用Android 6.0拍照(来自图库或相机应用)。

因为我不需要控制相机,所以我想使用这里描述的意图:

但是,如果您不需要此类控件,则只需使用ACTION_IMAGE_CAPTURE意图来请求图像。当您启动意图时,系统会提示用户选择相机应用程序(如果还没有默认的相机应用程序),该应用程序将拍摄照片。相机应用程序将图片返回到应用程序的onActivityResult()方法。

https://developer.android.com/preview/features/runtime-permissions.html

但就此而言 ACTION_IMAGE_CAPTURE,你需要填补额外的 “MediaStore.EXTRA_OUTPUT” 这是一个临时文件的Uri(没有这个参数我将只有一个缩略图)。此临时文件必须位于外部存储中(可由相机应用程序访问)。你需要这个许可 WRITE_EXTERNAL_STORAGE 在外部存储上创建文件。

因此,如果没有,那么通过原生对话框/应用程序捕获图像是不可能的 权限android.permission.CAMERA 要么 android.permission.WRITE_EXTERNAL_STORAGE。那是对的吗?

谢谢


2895
2017-09-08 16:21


起源

欢迎您尝试通过 content://  Uri 在 EXTRA_OUTPUT 指着一个 ContentProvider 你写的,你可以接受数据。我没有试过这个,我的猜测是会有一堆相机应用程序不会期待这样的价值,并会扼杀它。 - CommonsWare
你找到了解决这个问题的方法吗? - AndroidEnthusiast


答案:


有可能你在Android 4.4+上,你可以指定MediaStore.EXTRA_OUTPUT,成为你下的文件 包专用 目录

从Android 4.4开始,文件的所有者,组和模式   现在基于目录合成外部存储设备   结构体。这使应用程序可以管理他们的 包专用   目录 在外部存储,而不要求他们持有广泛的   WRITE_EXTERNAL_STORAGE权限。 例如,带包的应用程序   名称com.example.foo现在可以自由访问   Android / data / com.example.foo /在外部存储设备上没有   权限。 这些合成的权限是通过   将原始存储设备包装在FUSE守护程序中。

https://source.android.com/devices/storage/


4
2017-09-08 16:45



你真的试过这个吗?这使您的应用程序可以访问目录,但不能访问CAMERA应用程序,这就是问题所在。 - Greg Ennis
@Derek Fung你可以分享一个示例项目吗? - Vinil Chandran
Camera无法访问app private cache dir目录。 @Jonathan Aste的解决方案正在发挥作用。 - Makalele


尝试这个:

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = new File(getActivity().getApplicationContext().getExternalFilesDir(android.os.Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + "yourPicture.jpg");
Uri uri = Uri.fromFile(file);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, url);

在这种情况下,这使您可以访问可写入相机应用程序的“外部”存储空间,但文件只能从您的应用程序中看到。 要了解更多关于android中存储空间的信息,请参阅 https://www.youtube.com/watch?v=C28pvd2plBA

希望它能帮到你!


8
2018-05-11 15:08



这是我到目前为止发现的唯一一个不会在Android 6上破解的工作解决方案。:) - Andrea Lazzarotto
加工!无需WRITE_EXTERNAL_STORAGE或READ_EXTERNAL_STORAGE。 - Makalele
谢谢!在 onActivityResult 你会得到 RESULT_OK 和 data == null。在这种情况下,您应该从路径读取文件(变量 uri),或看到 stackoverflow.com/questions/32043222/...。您必须获得API> = 23的文件读取权限。 - CoolMind


由于相机应用程序无法访问您应用的私人目录,因此将照片文件写入该目录是您的应用程序职责。我对此并不十分确定,但这对我有用:

private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
            .format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    return File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );
}

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
    // Create the File where the photo should go
    File photoFile = null;
    try {
        photoFile = createImageFile();
        takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
    } catch (IOException ex) {
        // Error occurred while creating the File
        Log.e(TAG, "Unable to create Image File", ex);
    }

    // Continue only if the File was successfully created
    if (photoFile != null) {
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                Uri.fromFile(photoFile));
    } else {
        takePictureIntent = null;
    }
}

但你仍然需要 WRITE_EXTERNAL_STORAGE KITKAT之前的许可:

<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18" />

2
2018-02-12 19:59





没有任何一个,这是可能的 CAMERA 和 WRITE_EXTERNAL_STORAGE 权限。

您可以在应用程序的缓存目录中创建临时文件,并让其他应用程序访问它。这使得该文件可由相机应用程序写入:

File tempFile = File.createTempFile("photo", ".jpg", context.getCacheDir());
tempFile.setWritable(true, false);

现在您只需将此文件作为摄像头意图的输出文件传递:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));  // pass temp file
startActivityForResult(intent, REQUEST_CODE_CAMERA);

注意:文件Uri不会在Activity结果中传递给你,你必须保留对tempFile的引用并从那里检索它。


1
2017-11-11 21:15



在定位Marshmallow时似乎不再起作用了。 - wiradikusuma
这个选项似乎很有希望,任何人都有关于兼容性的任何反馈? - Zapnologica
不起作用。相机应用无法访问应用缓存目录。 - Makalele