如何获得相机的结果数据文件夹中的URI?如何获得、相机、结果、文件

2023-09-11 12:16:32 作者:断桥烟雨旧人殇

我创造的,我要捕捉的图像,然后我想发送图像中的电子邮件作为附件的应用程序。

I am creating an application in which I want to capture a image and then I want to send that image in the email as a attachment.

我打开相机中使用 android.provider.MediaStore.ACTION_IM​​AGE_CAPTURE 意图的行动,我将文件传递的URI作为参数 EXTRA_OUTPUT 获取图像回文件。这是工作完美,我是能够获得所拍摄的图像,如果我使用外部存储URI EXTRA_OUTPUT 但如果我使用数据文件夹URI,它不工作,如果相机没有关闭其所有按钮都不起作用。

I am opening a camera using android.provider.MediaStore.ACTION_IMAGE_CAPTURE intent action and I am passing the Uri of the file as a parameter EXTRA_OUTPUT to get the image back to the file. This is working perfectly and I am able to get the captured image if I use the external storage uri as a EXTRA_OUTPUT but if I use the data folder uri it is not working and the camera is not closing and its all buttons are not working.

下面是我的$ C $下得到的结果在外部存储目录

Here is my code for get the result in the external storage directory

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = Environment.getExternalStorageDirectory();
out = new File(out, imagename);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);

这code是用于获取数据文件夹中的图片

And this code is for get the image in the data folder

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = getFilesDir();
out = new File(out, MyPharmacyOptions.PRESCRIPTION_IMAGE_NAME);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);

我知道,在数据文件夹不能访问第三方应用程序等都可能是这会导致一个问题,所以我必须创建一个内容提供商共享的文件。

I knew that the data folder is not accessible to third application so may be this causes an issue so I have create one content provider to share the file.

下面是我的内容提供类

public class MyContentProvider extends ContentProvider {
    private static final String Tag = RingtonContentProvider.class.getName();
    public static final Uri CONTENT_URI = Uri
            .parse("content://x.y.z/");
    private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();

    static {
        MIME_TYPES.put(".mp3", "audio/mp3");
        MIME_TYPES.put(".wav", "audio/mp3");
        MIME_TYPES.put(".jpg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }

        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
            throws FileNotFoundException {
        File f = new File(getContext().getFilesDir(), uri.getPath());

        if (f.exists()) {
            return (ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY));
        }

        throw new FileNotFoundException(uri.getPath());
    }

    @Override
    public Cursor query(Uri url, String[] projection, String selection,
            String[] selectionArgs, String sort) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public Uri insert(Uri uri, ContentValues initialValues) {
        File file = new File(getContext().getFilesDir(), uri.getPath());
        if(file.exists()) file.delete();
        try {
            file.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return Uri.fromFile(file);
    }

    @Override
    public int update(Uri uri, ContentValues values, String where,
            String[] whereArgs) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        File f = new File(getContext().getFilesDir(), "image1.jpg");
        if(f.exists()) f.delete();
        f = new File(getContext().getFilesDir(), "image2.jpg");
        if(f.exists()) f.delete();

        getContext().getContentResolver().notifyChange(CONTENT_URI, null);

    }
}

因此​​,要使用这个内容提供我使用下面的code要通过URI相机活性

So to use this content provide I am using following code to pass the uri to the camera activity

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = MyContentProvider.CONTENT_URI;
uri = Uri.withAppendedPath(uri, imagename);
getContentResolver().insert(uri, null);
getContentResolver().notifyChange(RingtonContentProvider.CONTENT_URI, null);
Log.d(Tag, uri.toString());
i.putExtra(MediaStore.EXTRA_OUTPUT, uri);

startActivityForResult(i, CAMERA_RESULT);

现在,如果我通过URL以外的其他外部存储目录中的相机打开,但它不是关​​闭在模拟器,但在设备的摄像头将会关闭,但我没有得到的结果。

Now if I pass the url other then external storage directory the camera is opening but it is not closing in emulator but in device the camera is going to closed but I am not getting the result.

我已经声明在manifest文件中该内容提供

I have declared this content provide in the manifest file

<provider
android:name=".contentproviders.MyContentProvider"
android:authorities="x.y.z" />

此外,我已经给了允许的写外部存储,也为使用相机

我能够捕捉使用外部存储的图像,但我想存储在数据目录中,而不是外部存储的图像,因为如果外部存储所不具备我想捕捉的图像,并希望将邮件发送。

I am able to capture the image using the external storage but I want to store the image in the data directory instead of external storage because if the external storage in not available I want to capture the image and want to send mail.

如果我创造内容提供那么我也可以分享我的图像的电子邮件应用程序。

If I create content provide then I can also share my image to the email application.

如果我们不能提供额外的相机意图将返回图像作为活动的结果作为数据的额外一个byte []但这是缩略图的目的,所以我不能让高分辨率图像采用这种方式。

请看看到我的问题,并给你的建议。 谢谢你。

Please have a look into my question and give your suggestions. Thanks.

推荐答案

有两种方法来解决这个问题。 你可以从 onActivityResult 的位图,如果你使用 ACTION_IM​​AGE捕获启动摄像头的活动。 使用内容提供商可以将图像保存到从相机的活动手机的内存(应用程序的文件目录)。

There are two ways to solve this problem. You can get the bitmap from the onActivityResult if you start the camera activity using ACTION_IMAGE-CAPTURE. Using content provider you can save the image to the phone's internal memory(File directory of your application) from the camera activity.

1。第一个解决方案是很容易的。使用这个code启动摄像头的活动

Intent cameraIntent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);

压脚提升拍摄的图像,你会得到的结果在ActivtyResult。

fter capturing image you will get the result in the ActivtyResult.

if (requestCode == CAMERA_REQUEST) {  
    Bitmap photo = (Bitmap) data.getExtras().get("data"); 
 }

注意:: 这第一个解决方案工作正常,但该位图你得到的的 onActivityResult() 的是低分辨率。如果你想要高清晰度图像,那么你应该preFER第二个解决方案。

Note:: This first solution is working fine but the bitmap you are getting in onActivityResult() is of low resolution. If you want high resolution image then you should prefer a second solution.

2。第二种解决方案是有点长,但它是非常重要的。

在这种情况下,你必须创建一个将用于共享本地(应用程序内部的)文件到相机的活动内容提供商。

In this case you will have to create a content provider which will use to share your local (Application's internal) file to the camera activity.

下面下面是我的内容提供类,我已经改变,使之正确。

Here below is my Content provider class which I have changed and make it correct.

public class MyFileContentProvider extends ContentProvider {
    public static final Uri CONTENT_URI = Uri.parse
                                    ("content://com.example.camerademo/");
    private static final HashMap<String, String> MIME_TYPES = 
                                     new HashMap<String, String>();

    static {
        MIME_TYPES.put(".jpg", "image/jpeg");
        MIME_TYPES.put(".jpeg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {

        try {
            File mFile = new File(getContext().getFilesDir(), "newImage.jpg");
            if(!mFile.exists()) {
                mFile.createNewFile();
            }
            getContext().getContentResolver().notifyChange(CONTENT_URI, null);
            return (true);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }
        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
    throws FileNotFoundException {

        File f = new File(getContext().getFilesDir(), "newImage.jpg");
        if (f.exists()) {
            return (ParcelFileDescriptor.open(f,
                    ParcelFileDescriptor.MODE_READ_WRITE));
        }
        throw new FileNotFoundException(uri.getPath());
    }
}

和启动相机活动中使用简单

And to start the camera activity use simply

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAMERA_RESULT);

有关详细信息,您可以参考这个博客

For more information you can refer this blog

注意::请不要在模拟器不可考。有些时候,它是不工作的模拟器。

我收到有关空意图和低分辨率图像许多意见,所以我增加了一些内容,很容易理解的解决方案

I am getting many comments about the null intent and low resolution images so I am adding some content to easily understand the solution

修改

code,从相机获得高清晰度的图像。

Code to get high resolution images from camera.

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 /** 
 Here destination is the File object in which your captured images will be stored
 **/
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
/**
Here REQUEST_IMAGE is the unique integer value you can pass it any integer
**/
startActivityForResult(intent, REQUEST_IMAGE);

在此实现onActivityResult方法如下图所示。

After this implement the onActivityResult method like below

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode == REQUEST_IMAGE && resultCode == Activity.RESULT_OK) {
        // Now check the file which you have pass with the intent to capture.
        // Camera had stored the captured image to the file which you have passed with the intent.
    }
}

注意:如果您传递文件URI的意图,然后把它放在心上在该文件的相机不会写入所拍摄的图像,如果该文件不会被摄像头应用程序访问。

Note: If you are passing the file URi with the intent then keep it mind that camera will not write a captured image in that file if the file will not accessible by the camera application.