如何让Camera Intent将照片放入内部存储?

时间:2013-08-02 19:39:24

标签: android storage photos

我整天都在这里,似乎无法让它发挥作用。根据之前的工作人员的说法,它可以用来工作。

    cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
        String imageName = CustomApp.getTimeStamp(0) ;
        String path = CustomApp.getCurrentActivity().getDir("images", Context.MODE_WORLD_WRITEABLE).getPath()+File.separator+imageName;

        File file = new File(path) ;
        Uri img = Uri.fromFile(file) ;

        Intent passthruDataIntent = new Intent();

        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, img);
        CustomApp.getCurrentActivity().startActivityForResult(cameraIntent, CustomConstants.REQUESTCODE_CAMERA);

这里发布了类似的代码,但它似乎不适用于4.2.2上的nexus 4。我试过外部存储,然后工作正常。任何有关它可能不起作用的见解都会非常有帮助。感谢。

3 个答案:

答案 0 :(得分:8)

每个应用程序的内部存储都是私有的 - 第三方相机应用程序无权写入您的内部存储空间。

答案 1 :(得分:4)

我正在与同样的问题作斗争并且很晚才得到解决问题的问题,但我相信这可能对社区有用。

随着Android 6.0 / API级别23中引入的新dynamic permissions,主题问题变得尤为重要,因为您需要在运行时请求权限并处理用户的接受和拒绝反应。要使用相机活动,您需要先要求相应的权限(android.permission.CAMERA)。然后,如果您将图片存储在外部目录中,则用户还需要将相应的权限android.permission.READ_EXTERNAL_STORAGE授予您的应用。当用户即将执行预期动作时(例如,如果在按钮之后出现相机访问许可请求"按下照片"被按下),则运行时许可请求对用户来说似乎是自然的。但是,如果您使用外部存储器保存相机图片,则需要在应用拍照时同时询问两个权限:(1)使用相机和(2)访问外部存储。后者可能令人沮丧,因为当用户期望只拍摄照片时,您的应用程序试图访问用户文件的原因并不一定清楚。

解决方案允许避免外部存储并直接保存相机图片包括使用content providers。根据{{​​3}},

  

Android提供了一种方法,您可以使用内容提供商将您的私人数据公开给其他应用程序。内容提供程序是一个可选组件,它公开对应用程序数据的读/写访问权限,但受限于您要施加的限制。

这正是您需要允许相机活动将图片直接保存到应用的本地存储中,以便您可以轻松访问它,而无需请求其他权限(只需要授予相机访问权限)

提供了一篇包含代码示例的好文章storage options documentation。本文启发的以下通用代码在我们的应用程序中用于执行此操作。

内容提供商类:

/**
 * A content provider that allows to store the camera image internally without requesting the
 * permission to access the external storage to take shots.
 */
public class CameraPictureProvider extends ContentProvider {
    private static final String FILENAME = "picture.jpg";

    private static final Uri CONTENT_URI = Uri.parse("content://xyz.example.app/cameraPicture");

    @Override
    public boolean onCreate() {
        try {
            File picture = new File(getContext().getFilesDir(), FILENAME);
            if (!picture.exists())
                if (picture.createNewFile()) {
                    getContext().getContentResolver().notifyChange(CONTENT_URI, null);
                    return true;
                }
        } catch (IOException | NullPointerException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Nullable
    @Override
    public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
        try {
            File picture = new File(getContext().getFilesDir(), FILENAME);
            if (!picture.exists())
                picture.createNewFile();
            return ParcelFileDescriptor.open(picture, ParcelFileDescriptor.MODE_READ_WRITE);
        } catch (IOException | NullPointerException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        String lc = uri.getPath().toLowerCase();
        if (lc.endsWith(".jpg") || lc.endsWith(".jpeg"))
            return "image/jpeg";
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

需要在应用清单中声明内容提供商:

    <provider android:authorities="xyz.example.app"
        android:enabled="true"
        android:exported="true"
        android:name="xyz.example.app.CameraPictureProvider" />

最后,要使用内容提供程序捕获摄像头图片,请从调用活动调用以下代码:

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, CameraPictureProvider.CONTENT_URI);
startActivityForResult(takePictureIntent, 0);

请注意,相机许可请求需要单独处理(未在提供的代码示例中完成)。

还值得注意的是,只有在使用构建工具版本23或更高版本时才需要处理权限请求。相同的代码与较低级别的构建工具兼容,并且在您不受运行时权限请求困扰但只是想避免使用外部存储的情况下非常有用。

答案 2 :(得分:1)

我遇到了同样的问题。我首先将照片保存在外部存储器中然后复制到内存中解决了这个问题。希望这会有所帮助。