将图像从相机保存到应用程序专用存储

时间:2015-06-09 08:02:20

标签: android android-intent android-camera android-camera-intent

这里有很多关于如何在android中创建外部存储文件的信息,将uri传递给ACTION_IMAGE_CAPTURE,然后将图像保存在那里。

但是,我想在Application的私有存储(有时称为内部存储)中创建一个文件,并将该文件uri传递给ACTION_IMAGE_CAPTURE,但Camera intent在onActivityResult中返回RESULT_CANCELED。

我该怎么办?

private void checkWhetherCameraIsAvailableAndTakeAPicture() {
    // Check wether this device is able to take pictures
    if (PhotoHandler.isIntentAvailable(a, MediaStore.ACTION_IMAGE_CAPTURE)) {
        System.gc();
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File imageFile = null;

        try {
                if(a.application.user.isPublishImagesToGallery()){
                imageFile = a.application.photoHandler.createImageFileOnExternalStorage();
            } else {
                imageFile = a.application.photoHandler.createImageFileOnInternalStorage();
            }

            imagePath = imageFile.getAbsolutePath();
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
        } catch (IOException e) {
            e.printStackTrace();
            imageFile = null;
            imagePath = null;
        }
        startActivityForResult(takePictureIntent, Preferences.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA);
    } else { // Notify the user that their device is unable to take photos
        a.application.toastMaker.toastLong(ErrorMessages.DEVICE_UNABLE_TO_TAKE_PHOTOS);
    }
} // End of checkWhetherCameraIsAvailableAndTakeAPicture

public File createImageFileOnInternalStorage() throws IOException {
        return createTempFileOnGivenLocation();
    }

    private String imageFilename() {
        return filenamePrefix + Calendar.getInstance().getTimeInMillis();
    }

    private File createTempFileOnGivenLocation() throws IOException {
        File imageFile = File.createTempFile(imageFilename(), filenameSuffix, context.getFilesDir());
        setImagePathTemporary(imageFile.toString());

        return imageFile;
    }


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == Preferences.REQUEST_CODE_TAKE_IMAGE_WITH_CAMERA) {
        if (resultCode != Activity.RESULT_CANCELED) {
            handlePhotoTakenWithCamera();
        } else {
            // ONACTIVITYRESULT Returns Here!
            new File(imagePath).delete())
        }
    } else if (requestCode == Preferences.REQUEST_CODE_PICK_IMAGES_FROM_GALLERY) {
        if (resultCode != Activity.RESULT_CANCELED) {
            handlePhotosPickedFromGallery(data);
        }
    }
} // End of onActivityResult

2 个答案:

答案 0 :(得分:1)

每个应用程序的内部存储都是私有的。 Camera App无法访问应用程序的内部存储。在内部存储中获取图像的最佳方法是。

1)使用自己的相机在应用程序内拍摄图像

2)使用相机意图拍摄图像以拍摄将图像保存到外部存储器的图片。 onActivityResult将图片复制到应用的内部存储空间并从外部存储空间中删除。复制文件的代码可以在这个答案中找到。 https://stackoverflow.com/a/4770586/4811470

答案 1 :(得分:1)

正如this answer中所述,相机应用无法直接写入应用的内部存储空间。

但是,您可以编写一个Content Provider,它可以将来自Camera应用程序的数据作为流使用并自行保存。

这是如何使相机应用程序知道放置文件的位置。

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
Uri uri = Uri.withAppendedPath(CONTENT_URI_OF_YOUR_CONTENT_PROVIDER, "id_of_your_image");
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(takePictureIntent, CAMERA_REQUEST);  

如何建立实际的内容提供者是恕我直言这个问题的范围。阅读上面链接的文档并搜索SO以获取相关问题。 一个提示,您必须实现insert方法才能执行此操作。 它可能看起来像这样。

public Uri insert(Uri uri, ContentValues values) {
    String name = uri.getPath();
    File file = new File(name);     
    OutputStream stream = new FileOutputStream(file);
    byte[] data = (byte[]) values.get(KEY_FILE_CONTENT);
    try {
        stream.write(data);
        stream.flush();
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return uri;
}

但是,由于内容提供商的复杂程度,上面的代码可能无法为您提供开箱即用的功能。