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

Capture image without permission with Android 6.0

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

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

However, if you don't need such control, you can just use an ACTION_IMAGE_CAPTURE intent to request an image. When you start the intent, the user is prompted to choose a camera app (if there isn't already a default camera app), and that app takes the picture. The camera app returns the picture to your app's onActivityResult() method.

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

但是对于这个ACTION_IMAGE_CAPTURE,你需要填充额外的"MediaStore.EXTRA_OUTPUT"这是一个Uri一个临时文件(没有这个参数我将只有一个缩略图)。这个临时文件必须在外部存储中(相机应用程序可以访问)。您需要 WRITE_EXTERNAL_STORAGE 权限才能在外部存储上创建文件。

因此,如果没有 许可 android.permission.CAMERAandroid.permission.WRITE_EXTERNAL_STORAGE[,则无法通过本机 dialogs/apps 捕获图像=30=]。对吗?

谢谢

如果您使用 android 4.4+,您可以指定 MediaStore.EXTRA_OUTPUT 作为您的 特定包下的文件 目录

Starting in Android 4.4, the owner, group and modes of files on external storage devices are now synthesized based on directory structure. This enables apps to manage their package-specific directories on external storage without requiring they hold the broad WRITE_EXTERNAL_STORAGE permission. For example, the app with package name com.example.foo can now freely access Android/data/com.example.foo/ on external storage devices with no permissions. These synthesized permissions are accomplished by wrapping raw storage devices in a FUSE daemon.

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

无需 CAMERAWRITE_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 的引用并从那里检索它。

由于相机应用无法访问您应用的私有目录,您的应用有责任将照片文件写入该目录。我不太确定,但这对我有用:

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;
    }
}

但在 KITKAT 之前您仍然需要 WRITE_EXTERNAL_STORAGE 许可:

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

试试这个:

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);

在这种情况下,这使您可以访问相机应用的 "external" 可写存储,但这些文件只能从您的应用中看到。 要详细了解 android 中的存储空间,请参阅 https://www.youtube.com/watch?v=C28pvd2plBA

希望对您有所帮助!

我按照 here 所述将 content://FileProvider.getUriForFile() 一起使用,并按 ACTION_IMAGE_CAPTURE 意图使用外部相机应用程序,这不需要任何许可。

但是,如果应用的清单使用了android.permission.CAMERA权限,那么打开外置摄像头应用似乎需要摄像头权限。参见 and