在安卓中从相机意图获取URI

19
点击
 takePic.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                Intent m_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                imageUri = getImageUri();
                m_intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(m_intent, REQUEST_IMAGE_CAPTURE);
            }
        });

关于结果:
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_IMAGE_CAPTURE
                    && resultCode == RESULT_OK) {   

                Log.d("test1",""+imageUri);
                Intent shareIntent = new Intent(this, SharePicForm.class);
                shareIntent.putExtra("photo",""+imageUri);
                startActivity(shareIntent);
            }

        }

获取图像URI。
private Uri getImageUri(){
        Uri m_imgUri = null;
        File m_file;
        try {
            SimpleDateFormat m_sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
            m_curentDateandTime = m_sdf.format(new Date());
            m_imagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + m_curentDateandTime + ".jpg";
            m_file = new File(m_imagePath);
            m_imgUri = Uri.fromFile(m_file);
        } catch (Exception p_e) {
        }
        return m_imgUri;
    }

我想要实现的很简单,就是调用相机意图并获取结果照片的URI。但似乎在不同的设备上存在不一致性,在我的设备上根本无法工作。我尝试将路径存储在公共变量中,但当我检索它时,它为空。是否有正式和标准的方法来实现它,并且应该在所有设备上都能工作?此外,是否有任何方法可以不提供自定义路径,而是从相机意图中获取默认的URI路径?
谢谢帮助。

5
使用onSavedInstanceState()和onRestoreInstanceState()来保存和恢复图像路径。 - amit singh
5个回答

14

如果您的设备没有相应地使用cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,您仍然可以使用

Uri imageUri = data.getData();

onActivityResult(int requestCode, int resultCode, Intent data)中。但在大多数情况下,问题是RAM有限,系统会销毁您的活动以为相机应用程序提供足够的内存来执行您的意图。因此,在返回结果时,您的活动字段未初始化,您应该遵循Amit的建议并实现onSavedInstance()onRestoreInstanceState()


3
data.getData 在大多数情况下返回 null。 - zakjma
1
@zakjma:要接收 data.getData(),您不应该在意图中传递 MediaStore.EXTRA_OUTPUT 额外的参数。 - Alex Cohn
3
在我的设备上(安卓 7.1.1),即使我没有在意图中传递 MediaStore.EXTRA_OUTPUT,data.getData() 仍然返回 null。代码如下:Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, CAMERA_REQUEST_CODE); - zakjma
@zakjma,这可能是您的设备出现了错误行为,但看起来data.getData()不再被官方文档所覆盖。请注意,他们鼓励您使用FileProvider而不是Uri,因此这种转变确实有意义。 - Alex Cohn
1
@zakjma 是正确的,即使不传递 MediaStore.EXTRA_OUTPUT,我也无法获取 data.data。 - Sreekanth Karumanaghat

7

首先确保您已经创建了目录......

final String dir =  Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+ "/Folder/";
     File newdir = new File(dir); 
     newdir.mkdirs();

在按钮单击时调用此函数。

private void capturarFoto() {
 String file = dir+DateFormat.format("yyyy-MM-dd_hhmmss", new Date()).toString()+".jpg";


File newfile = new File(file);
            try {
                newfile.createNewFile();
            } catch (IOException e) {}       

            Uri outputFileUri = Uri.fromFile(newfile);

            Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);

            startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
}

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

    if (requestCode == TAKE_PHOTO_CODE && resultCode == RESULT_OK) {
        Log.d("Demo Pic", "Picture is saved");


    }
}

请确保在清单文件中添加权限

<uses-permission android:name="android.permission.CAMERA"/>

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

这段代码适用于带有SD卡和不带SD卡的手机吗? - Parag Kadam
2
如果您通过隐式意图使用相机,则不需要相机权限。只有在实现自己的相机时才需要它。 - Leo DroidCoder
2
该数据返回空值。我很困惑。 - Kylo Ren

3
经过大量的研究,我找到了这个解决方案。为了让事情更清楚,我创建了一个完整的应用程序来回答这个问题,它可以打开相机,拍摄照片,并将图像设置为ImageView的ImageBitmap。这个问题所要求的代码从第二个块开始,即setView()方法,在onCreate()方法之后,接下来是onActivityResult()方法。
这是该应用程序的演示。

Demonstration

以下是MainActivity.java文件的附件。
package com.cr7.opencamera;

import android.Manifest;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private Button buttonCaptureImageFromCamera;
    private Uri imageUri;
    private ImageView imageViewCameraImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Button that will open the camera
        buttonCaptureImageFromCamera = findViewById(R.id.buttonCaptureImageFromCamera);
        // ImageView that will store the image
        imageViewCameraImage = findViewById(R.id.imageViewCameraImage);
        askPermission();
    }


这是获取图像Uri所需的内容,这里的imageUri是一个全局变量,以便在onActivityResult()方法中使用。
    // Sets OnClickListener for the button if storage permission is given
    private void setView() {
        buttonCaptureImageFromCamera.setOnClickListener(v -> {
            String fileName = "new-photo-name.jpg";
            // Create parameters for Intent with filename
            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.TITLE, fileName);
            values.put(MediaStore.Images.Media.DESCRIPTION, "Image capture by camera");
            imageUri =
                    getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                            values);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            startActivityForResult(intent, 1231);
        });
    }

这是onActivityResult方法。在此,我使用了imageUri,即类型为Uri的全局变量,该变量在上面setView()方法中按钮的OnClickListener中进行了初始化。
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1231 && resultCode == Activity.RESULT_OK) {
            try {
                ContentResolver cr = getContentResolver();
                try {
                    // Creating a Bitmap with the image Captured
                    Bitmap bitmap = MediaStore.Images.Media.getBitmap(cr, imageUri);
                    // Setting the bitmap as the image of the
                    imageViewCameraImage.setImageBitmap(bitmap);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (IllegalArgumentException e) {
                if (e.getMessage() != null)
                    Log.e("Exception", e.getMessage());
                else
                    Log.e("Exception", "Exception");
                e.printStackTrace();
            }
        }
    }

剩余的代码...

    // Asking user for storage permission
    public void askPermission() {
        // Checking if the permissions are not granted.
        if (
                ContextCompat.checkSelfPermission(
                        this,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE
                ) != PackageManager.PERMISSION_GRANTED ||
                        ContextCompat.checkSelfPermission(
                                this,
                                android.Manifest.permission.READ_EXTERNAL_STORAGE
                        ) != PackageManager.PERMISSION_GRANTED
        ) {
            // If not granted requesting Read and  Write storage
            ActivityCompat.requestPermissions(this, /*You can ask for multiple request by adding
            more permissions to the string*/new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
                            Manifest.permission.READ_EXTERNAL_STORAGE}, 60);
        } else {
            // If permissions are granted we proceed by setting an OnClickListener for the button
            // which helps the user pick the image
            setView();
        }
    }

    // This method is called after the permissions have been asked i.e. the dialog that says
    // allow or deny
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // Now by default we assume that the permission has not been granted
        boolean allPermissionsGranted = false;
        // Now we check if the permission was granted
        if ( requestCode == 60 && grantResults.length > 0) {
            // If all the permissions are granted allPermissionsGranted is set to true else false
            allPermissionsGranted = grantResults[0] == PackageManager.PERMISSION_GRANTED
                    &&
                    grantResults[1] == PackageManager.PERMISSION_GRANTED;
        }
        // If permissions are granted we call the setView Method which prompts the user to pick
        // an Image either by the clicking it now or picking from the gallery
        if ( allPermissionsGranted ) {
            setView();
        }
    }
}

这些代码块是按顺序排列的,即如果你合并所有这些块,就会得到完整的MainActivity.java类。
如果您想要实现此应用程序,您需要创建一个布局文件,其中包含一个ID为“imageViewCameraImage”的ImageView和一个ID为“buttonCaptureImageFromCamera”的按钮。
希望这可以帮助您。我知道这很长,但通过写这个使它变得更长了。 问候, 乔尔

2

仅获取缩略图,您可以使用以下代码:

val imageBitmap = data.extras.get("data") as Bitmap

获取完整信息:
请查看具体步骤(官方文档)

您可以从文档中了解更多信息。


-9

只需使用以下代码 Uri imageUri = data.getData();


7
从相机中,data.getData()方法总是返回null。你错了。 - Nakamoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接