从相机捕获图像并在活动中显示

Posted

技术标签:

【中文标题】从相机捕获图像并在活动中显示【英文标题】:Capture Image from Camera and Display in Activity 【发布时间】:2011-08-24 21:08:55 【问题描述】:

我想编写一个模块,单击按钮即可打开相机,我可以单击并捕获图像。如果我不喜欢该图像,我可以将其删除并单击另一张图像,然后选择该图像,它应该返回并在活动中显示该图像。

【问题讨论】:

您应该打开相机意图,捕获图像,如果需要将其保存在 SD 卡上,通过内容提供程序获取 id,并在对话框中显示,并带有确定/取消按钮。 @jengelsma 我在使用相机时遇到了一个问题,我以纵向模式捕获图像并在图像视图中显示,然后它总是以横向模式显示。你有什么想法吗?否则你能解决这个问题吗。请回复我等一下你的答案。 @Harsha M V 如果你得到答案然后回复我。 这个博客可以帮助你。 startandroiddevelopment.blogspot.in/2013/10/… 参考链接***.com/questions/13977245/… 【参考方案1】:

您需要阅读有关Camera 的信息。 (我认为要做你想做的事,你必须将当前图像保存到你的应用程序中,在那里进行选择/删除,然后调用相机重试,而不是直接在相机内重试。)

【讨论】:

【参考方案2】:

这是一个示例 Activity,它将启动相机应用,然后检索图像并显示它。

package edu.gvsu.cis.masl.camerademo;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MyCameraActivity extends Activity

    private static final int CAMERA_REQUEST = 1888; 
    private ImageView imageView;
    private static final int MY_CAMERA_PERMISSION_CODE = 100;

    @Override
    public void onCreate(Bundle savedInstanceState)
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        this.imageView = (ImageView)this.findViewById(R.id.imageView1);
        Button photoButton = (Button) this.findViewById(R.id.button1);
        photoButton.setOnClickListener(new View.OnClickListener()
        
            @Override
            public void onClick(View v)
            
                if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
                
                    requestPermissions(new String[]Manifest.permission.CAMERA, MY_CAMERA_PERMISSION_CODE);
                
                else
                
                    Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
                    startActivityForResult(cameraIntent, CAMERA_REQUEST);
                 
            
        );
    

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
    
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == MY_CAMERA_PERMISSION_CODE)
        
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
            
                Toast.makeText(this, "camera permission granted", Toast.LENGTH_LONG).show();
                Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
                startActivityForResult(cameraIntent, CAMERA_REQUEST);
            
            else
            
                Toast.makeText(this, "camera permission denied", Toast.LENGTH_LONG).show();
            
        
    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
      
        if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK)
          
            Bitmap photo = (Bitmap) data.getExtras().get("data"); 
            imageView.setImageBitmap(photo);
          
     

请注意,相机应用程序本身使您能够查看/重新拍摄图像,一旦图像被接受,活动就会显示它。

这是上述活动使用的布局。它只是一个 LinearLayout,包含一个 ID 为 button1 的 Button 和一个 ID 为 imageview1 的 ImageView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_
    android:layout_
    >
    <Button android:id="@+id/button1" android:layout_ android:layout_ android:text="@string/photo"></Button>
    <ImageView android:id="@+id/imageView1" android:layout_ android:src="@drawable/icon" android:layout_></ImageView>

</LinearLayout>

最后一个细节,一定要补充:

<uses-feature android:name="android.hardware.camera"></uses-feature> 

如果相机对于您的应用功能来说是可选的。确保在权限中将 require 设置为 false。像这样

<uses-feature android:name="android.hardware.camera" android:required="false"></uses-feature>

到您的 manifest.xml。

【讨论】:

位图照片 = (位图) data.getExtras().get("data");它给出了一个空指针期望。当我打开应用程序并单击 Capture 时,它​​会转到相机应用程序,2-4 秒后整个事情都崩溃了。 我想为了安全起见,我们应该检查 onActivityResult() 方法中的 resultCode == Activity.RESULT_OK 。至于为什么相机会崩溃,我们必须看到堆栈跟踪。 @Harsha M V 这是三星 Galaxy 上的一个已知错误。请看这个答案***.com/questions/7031374/… @WillKru 如果该功能不是强制性的,您应该添加带有android:required="false" 属性的&lt;uses-feature/&gt;&lt;uses-feature android:name="android.hardware.camera" android:required="false"&gt;&lt;/uses-feature&gt; 还要注意Bitmap photo = (Bitmap) data.getExtras().get("data"); 不会抓取拍摄的图像。它会抓取所拍摄图像的缩略图。【参考方案3】:

活动中:

@Override
    protected void onCreate(Bundle savedInstanceState) 
                 image = (ImageView) findViewById(R.id.imageButton);
        image.setOnClickListener(new OnClickListener() 

            @Override
            public void onClick(View v) 
                try 
                SimpleDateFormat sdfPic = new SimpleDateFormat(DATE_FORMAT);
                currentDateandTime = sdfPic.format(new Date()).replace(" ", "");
                File imagesFolder = new File(IMAGE_PATH, currentDateandTime);
                imagesFolder.mkdirs();
                Random generator = new Random();
                int n = 10000;
                n = generator.nextInt(n);
                String fname = IMAGE_NAME + n + IMAGE_FORMAT;
                File file = new File(imagesFolder, fname);
                outputFileUri = Uri.fromFile(file);
                cameraIntent= new Intent(
                        android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
                                startActivityForResult(cameraIntent, CAMERA_DATA);
                catch(Exception e) 
                    e.printStackTrace();
                

            
        );
           @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) 
        super.onActivityResult(requestCode, resultCode, data);
        switch(requestCode) 
        case CAMERA_DATA :
                final int IMAGE_MAX_SIZE = 300;
                try 
                    // Bitmap bitmap;
                    File file = null;
                    FileInputStream fis;
                    BitmapFactory.Options opts;
                    int resizeScale;
                    Bitmap bmp;
                    file = new File(outputFileUri.getPath());
                    // This bit determines only the width/height of the
                    // bitmap
                    // without loading the contents
                    opts = new BitmapFactory.Options();
                    opts.inJustDecodeBounds = true;
                    fis = new FileInputStream(file);
                    BitmapFactory.decodeStream(fis, null, opts);
                    fis.close();

                    // Find the correct scale value. It should be a power of
                    // 2
                    resizeScale = 1;

                    if (opts.outHeight > IMAGE_MAX_SIZE
                            || opts.outWidth > IMAGE_MAX_SIZE) 
                        resizeScale = (int) Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE/ (double) Math.max(opts.outHeight, opts.outWidth)) / Math.log(0.5)));
                    

                    // Load pre-scaled bitmap
                    opts = new BitmapFactory.Options();
                    opts.inSampleSize = resizeScale;
                    fis = new FileInputStream(file);
                    bmp = BitmapFactory.decodeStream(fis, null, opts);
                    Bitmap getBitmapSize = BitmapFactory.decodeResource(
                            getResources(), R.drawable.male);
                    image.setLayoutParams(new RelativeLayout.LayoutParams(
                            200,200));//(width,height);
                    image.setImageBitmap(bmp);
                    image.setRotation(90);
                    fis.close();

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    bmp.compress(Bitmap.CompressFormat.JPEG, 70, baos);
                    imageByte = baos.toByteArray();
                    break;
                 catch (FileNotFoundException e) 

                    e.printStackTrace();
                 catch (IOException e) 
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
            
        

在 layout.xml 中:

enter code here
<RelativeLayout
        android:id="@+id/relativeLayout2"
        android:layout_
        android:layout_>


        <ImageView
            android:id="@+id/imageButton"
            android:layout_
            android:layout_

                            android:src="@drawable/XXXXXXX"
            android:textAppearance="?android:attr/textAppearanceSmall" />

在 manifest.xml 中:

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

【讨论】:

【参考方案4】:

拍摄照片 + 从图库中选择:

        a = (ImageButton)findViewById(R.id.imageButton1);

        a.setOnClickListener(new View.OnClickListener() 

            @Override

            public void onClick(View v) 

                selectImage();

            

        );
    
    private File savebitmap(Bitmap bmp) 
      String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
      OutputStream outStream = null;
     // String temp = null;
        File file = new File(extStorageDirectory, "temp.png");
      if (file.exists()) 
       file.delete();
       file = new File(extStorageDirectory, "temp.png");

      

      try 
       outStream = new FileOutputStream(file);
       bmp.compress(Bitmap.CompressFormat.PNG, 100, outStream);
       outStream.flush();
       outStream.close();

       catch (Exception e) 
       e.printStackTrace();
       return null;
      
      return file;
     
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    
     private void selectImage() 



            final CharSequence[] options =  "Take Photo", "Choose from Gallery","Cancel" ;



            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

            builder.setTitle("Add Photo!");

            builder.setItems(options, new DialogInterface.OnClickListener() 

                @Override

                public void onClick(DialogInterface dialog, int item) 

                    if (options[item].equals("Take Photo"))

                    

                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

                        File f = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");

                        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
                        //pic = f;

                        startActivityForResult(intent, 1);


                    

                    else if (options[item].equals("Choose from Gallery"))

                    

                        Intent intent = new   Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

                        startActivityForResult(intent, 2);



                    

                    else if (options[item].equals("Cancel")) 

                        dialog.dismiss();

                    

                

            );

            builder.show();

        



        @Override

        protected void onActivityResult(int requestCode, int resultCode, Intent data) 

            super.onActivityResult(requestCode, resultCode, data);

            if (resultCode == RESULT_OK) 

                if (requestCode == 1) 
                    //h=0;
                    File f = new File(Environment.getExternalStorageDirectory().toString());

                    for (File temp : f.listFiles()) 

                        if (temp.getName().equals("temp.jpg")) 

                            f = temp;
                            File photo = new File(Environment.getExternalStorageDirectory(), "temp.jpg");
                           //pic = photo;
                            break;

                        

                    

                    try 

                        Bitmap bitmap;

                        BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();



                        bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(),

                                bitmapOptions); 



                        a.setImageBitmap(bitmap);




                        String path = android.os.Environment

                                .getExternalStorageDirectory()

                                + File.separator

                                + "Phoenix" + File.separator + "default";
                        //p = path;

                        f.delete();

                        OutputStream outFile = null;

                        File file = new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg");

                        try 

                            outFile = new FileOutputStream(file);

                            bitmap.compress(Bitmap.CompressFormat.JPEG, 85, outFile);
    //pic=file;
                            outFile.flush();

                            outFile.close();


                         catch (FileNotFoundException e) 

                            e.printStackTrace();

                         catch (IOException e) 

                            e.printStackTrace();

                         catch (Exception e) 

                            e.printStackTrace();

                        

                     catch (Exception e) 

                        e.printStackTrace();

                    

                 else if (requestCode == 2) 



                    Uri selectedImage = data.getData();
                   // h=1;
    //imgui = selectedImage;
                    String[] filePath =  MediaStore.Images.Media.DATA ;

                    Cursor c = getContentResolver().query(selectedImage,filePath, null, null, null);

                    c.moveToFirst();

                    int columnIndex = c.getColumnIndex(filePath[0]);

                    String picturePath = c.getString(columnIndex);

                    c.close();

                    Bitmap thumbnail = (BitmapFactory.decodeFile(picturePath));


                    Log.w("path of image from gallery......******************.........", picturePath+"");


                    a.setImageBitmap(thumbnail);

                

            

【讨论】:

ResultCode == 1ResultCode == RESULT_OK ? 它是requestCode==1,帮助识别发起请求的人。【参考方案5】:

您可以使用带有缩略图的自定义相机。 你可以看看我的project。

【讨论】:

【参考方案6】:

完整代码如下:

package com.example.cameraa;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity 




        Button btnTackPic;
        Uri photoPath;
        ImageView ivThumbnailPhoto;

        static int TAKE_PICTURE = 1;

        @Override
        protected void onCreate(Bundle savedInstanceState) 
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // Get reference to views

            btnTackPic = (Button) findViewById(R.id.bt1);
            ivThumbnailPhoto = (ImageView) findViewById(R.id.imageView1);




     btnTackPic.setOnClickListener(new View.OnClickListener() 

        @Override
        public void onClick(View v) 
            // TODO Auto-generated method stub


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




    );

         

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent intent) 


                if (requestCode == TAKE_PICTURE && resultCode == RESULT_OK)   
                    Bitmap photo = (Bitmap)intent.getExtras().get("data"); 
                   ivThumbnailPhoto.setImageBitmap(photo);
                ivThumbnailPhoto.setVisibility(View.VISIBLE);



            
        

记得为相机添加权限。

【讨论】:

【参考方案7】:

从相机拍摄照片+从图库中选择图像并将其设置为布局或图像视图的背景。这是示例代码。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;

    import android.provider.MediaStore;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.GridView;
    import android.widget.ImageView;
    import android.widget.LinearLayout;

    public class Post_activity extends Activity
    
        final int TAKE_PICTURE = 1;
        final int ACTIVITY_SELECT_IMAGE = 2;

        ImageView openCameraOrGalleryBtn,cancelBtn;
        LinearLayout backGroundImageLinearLayout;

        public void onCreate(Bundle savedBundleInstance) 
            super.onCreate(savedBundleInstance);
            overridePendingTransition(R.anim.slide_up,0);
            setContentView(R.layout.post_activity);

            backGroundImageLinearLayout=(LinearLayout)findViewById(R.id.background_image_linear_layout);
            cancelBtn=(ImageView)findViewById(R.id.cancel_icon);

            openCameraOrGalleryBtn=(ImageView)findViewById(R.id.camera_icon);



            openCameraOrGalleryBtn.setOnClickListener(new OnClickListener() 

                @Override
                public void onClick(View v) 
                    // TODO Auto-generated method stub

                    selectImage();
                
            );
            cancelBtn.setOnClickListener(new OnClickListener() 

                @Override
                public void onClick(View v) 
                    // TODO Auto-generated method stub
                overridePendingTransition(R.anim.slide_down,0);
                finish();
                
            );

        

    public void selectImage()
        
             final CharSequence[] options =  "Take Photo", "Choose from Gallery","Cancel" ;
             AlertDialog.Builder builder = new AlertDialog.Builder(Post_activity.this);
                builder.setTitle("Add Photo!");
                builder.setItems(options,new DialogInterface.OnClickListener() 

                    @Override
                    public void onClick(DialogInterface dialog, int which) 
                        // TODO Auto-generated method stub
                        if(options[which].equals("Take Photo"))
                        
                            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
                            startActivityForResult(cameraIntent, TAKE_PICTURE);
                        
                        else if(options[which].equals("Choose from Gallery"))
                        
                            Intent intent=new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                            startActivityForResult(intent, ACTIVITY_SELECT_IMAGE);
                        
                        else if(options[which].equals("Cancel"))
                        
                            dialog.dismiss();
                        

                    
                );
                builder.show();
        
        public void onActivityResult(int requestcode,int resultcode,Intent intent)
        
            super.onActivityResult(requestcode, resultcode, intent);
            if(resultcode==RESULT_OK)
            
                if(requestcode==TAKE_PICTURE)
                
                    Bitmap photo = (Bitmap)intent.getExtras().get("data"); 
                    Drawable drawable=new BitmapDrawable(photo);
                    backGroundImageLinearLayout.setBackgroundDrawable(drawable);

                
                else if(requestcode==ACTIVITY_SELECT_IMAGE)
                
                    Uri selectedImage = intent.getData();
                    String[] filePath =  MediaStore.Images.Media.DATA ;
                    Cursor c = getContentResolver().query(selectedImage,filePath, null, null, null);
                    c.moveToFirst();
                    int columnIndex = c.getColumnIndex(filePath[0]);
                    String picturePath = c.getString(columnIndex);
                    c.close();
                    Bitmap thumbnail = (BitmapFactory.decodeFile(picturePath));
                    Drawable drawable=new BitmapDrawable(thumbnail);
                    backGroundImageLinearLayout.setBackgroundDrawable(drawable);


                
            
        

        public void onBackPressed() 
            super.onBackPressed();
            //overridePendingTransition(R.anim.slide_down,0);
        
    

Add these permission in Androidmenifest.xml file

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

【讨论】:

这已经很老了,但我喜欢你这样做的方式。当我从图库中选择时,图像无法显示。有什么想法吗?【参考方案8】:

更新(2020 年)

Google 添加了一个新的 ActivityResultRegistry API,“让您处理 startActivityForResult() + onActivityResult() 以及 requestPermissions() + onRequestPermissionsResult() 流,而无需覆盖您的 Activity 或 Fragment 中的方法,带来更多通过ActivityResultContract 进行类型安全,并提供用于测试这些流程的挂钩" - source。

在androidx.activity 1.2.0-alpha02 和androidx.fragment 1.3.0-alpha02 中添加了API。

所以您现在可以执行以下操作:

val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture())  success: Boolean ->
    if (success) 
        // The image was saved into the given Uri -> do something with it
    


val imageUri: Uri = ...
button.setOnClickListener 
    takePicture.launch(imageUri)

查看文档以了解如何使用新的 Activity 结果 API:https://developer.android.com/training/basics/intents/result#kotlin

有许多内置的ActivityResultContracts 允许您执行不同的操作,例如选择联系人、请求权限、拍照或拍摄视频。您可能对上面显示的ActivityResultContracts.TakePicture 感兴趣。

请注意,androidx.fragment 1.3.0-alpha04 不推荐使用 Fragment 上的 startActivityForResult() + onActivityResult()requestPermissions() + onRequestPermissionsResult() API。因此,ActivityResultContracts 似乎是从现在开始做事的新方式。


原始答案(2015 年)

我花了几个小时才完成这项工作。代码几乎是developer.android.com的复制粘贴,略有不同。

AndroidManifest.xml 上请求此权限:

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

在您的 Activity 上,首先定义以下内容:

static final int REQUEST_IMAGE_CAPTURE = 1;
private Bitmap mImageBitmap;
private String mCurrentPhotoPath;
private ImageView mImageView;

然后在onClick 中触发这个Intent

Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) 
    // Create the File where the photo should go
    File photoFile = null;
    try 
        photoFile = createImageFile();
     catch (IOException ex) 
        // Error occurred while creating the File
        Log.i(TAG, "IOException");
    
    // Continue only if the File was successfully created
    if (photoFile != null) 
        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
        startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
    

添加如下支持方式:

private File createImageFile() throws IOException 
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  // prefix
            ".jpg",         // suffix
            storageDir      // directory
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = "file:" + image.getAbsolutePath();
    return image;

然后接收结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) 
        try 
            mImageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(mCurrentPhotoPath));
            mImageView.setImageBitmap(mImageBitmap);
         catch (IOException e) 
            e.printStackTrace();
        
    

使它起作用的是MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(mCurrentPhotoPath)),它与developer.android.com 的代码不同。原始代码给了我一个FileNotFoundException

【讨论】:

"Uri.parse(mCurrentPhotoPath))" 是解决方案,因为 MediaStore.EXTRA_OUTPUT 导致空意图结果。 我的图片默认是横向模式,我错过了什么吗? 这段代码对我不起作用。我收到android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/JPEG_20180823_102340_722874009725833047.jpg exposed beyond app through ClipData.Item.getUri()。关于如何解决这个问题的任何想法? @AlbertVilaCalvo @AlbertVilaCalvo 我不知道。那么,您对如何解决此问题有任何想法吗?我不知道我能改变什么。我希望你能帮助我,谢谢。 我不得不使用storageDir = Context.getFilesDir(); 代替文件storageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES);。否则我会收到权限被拒绝错误。【参考方案9】:

这是我用于捕获和保存相机图像然后将其显示到 imageview 的代码。您可以根据需要使用。

您必须将相机图像保存到特定位置,然后从该位置获取,然后将其转换为字节数组。

这是打开捕获相机图像活动的方法。

private static final int CAMERA_PHOTO = 111;
private Uri imageToUploadUri;

private void captureCameraImage() 
        Intent chooserIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File f = new File(Environment.getExternalStorageDirectory(), "POST_IMAGE.jpg");
        chooserIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
        imageToUploadUri = Uri.fromFile(f);
        startActivityForResult(chooserIntent, CAMERA_PHOTO);
    

那么你的 onActivityResult() 方法应该是这样的。

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

            if (requestCode == CAMERA_PHOTO && resultCode == Activity.RESULT_OK) 
                if(imageToUploadUri != null)
                    Uri selectedImage = imageToUploadUri;
                    getContentResolver().notifyChange(selectedImage, null);
                    Bitmap reducedSizeBitmap = getBitmap(imageToUploadUri.getPath());
                    if(reducedSizeBitmap != null)
                        ImgPhoto.setImageBitmap(reducedSizeBitmap);
                        Button uploadImageButton = (Button) findViewById(R.id.uploadUserImageButton);
                          uploadImageButton.setVisibility(View.VISIBLE);                
                    else
                        Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
                    
                else
                    Toast.makeText(this,"Error while capturing Image",Toast.LENGTH_LONG).show();
                
             
        

这里是 onActivityResult() 中使用的 getBitmap() 方法。在获取相机捕获图像位图时,我已经完成了所有可能的性能改进。

private Bitmap getBitmap(String path) 

        Uri uri = Uri.fromFile(new File(path));
        InputStream in = null;
        try 
            final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
            in = getContentResolver().openInputStream(uri);

            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(in, null, o);
            in.close();


            int scale = 1;
            while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) >
                    IMAGE_MAX_SIZE) 
                scale++;
            
            Log.d("", "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight);

            Bitmap b = null;
            in = getContentResolver().openInputStream(uri);
            if (scale > 1) 
                scale--;
                // scale to max possible inSampleSize that still yields an image
                // larger than target
                o = new BitmapFactory.Options();
                o.inSampleSize = scale;
                b = BitmapFactory.decodeStream(in, null, o);

                // resize to desired dimensions
                int height = b.getHeight();
                int width = b.getWidth();
                Log.d("", "1th scale operation dimenions - width: " + width + ", height: " + height);

                double y = Math.sqrt(IMAGE_MAX_SIZE
                        / (((double) width) / height));
                double x = (y / height) * width;

                Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,
                        (int) y, true);
                b.recycle();
                b = scaledBitmap;

                System.gc();
             else 
                b = BitmapFactory.decodeStream(in);
            
            in.close();

            Log.d("", "bitmap size - width: " + b.getWidth() + ", height: " +
                    b.getHeight());
            return b;
         catch (IOException e) 
            Log.e("", e.getMessage(), e);
            return null;
        
    

希望对你有帮助!

【讨论】:

我试过这个并将 captureImage() 从 onClickListener 放在 onClick 中,但不起作用。我正在使用 FragmentDialog... 有什么想法吗?【参考方案10】:

我知道这是一个很老的线程,但是所有这些解决方案都没有完成,并且当用户旋转相机时在某些设备上不起作用,因为 onActivityResult 中的数据为空。所以这是我在很多设备上测试过的解决方案,到目前为止还没有遇到任何问题。

首先在您的活动中声明您的 Uri 变量:

private Uri uriFilePath;

然后创建您的临时文件夹用于存储捕获的图像并打算通过相机捕获图像:

PackageManager packageManager = getActivity().getPackageManager();
if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) 
    File mainDirectory = new File(Environment.getExternalStorageDirectory(), "MyFolder/tmp");
         if (!mainDirectory.exists())
             mainDirectory.mkdirs();

          Calendar calendar = Calendar.getInstance();

          uriFilePath = Uri.fromFile(new File(mainDirectory, "IMG_" + calendar.getTimeInMillis()));
          intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
          intent.putExtra(MediaStore.EXTRA_OUTPUT, uriFilePath);
          startActivityForResult(intent, 1);

现在最重要的事情之一来了,您必须将您的 uriFilePath 保存在 onSaveInstanceState 中,因为如果您不这样做并且用户在使用相机时旋转了他的设备,您的 uri 将为空。

@Override
protected void onSaveInstanceState(Bundle outState) 
     if (uriFilePath != null)
         outState.putString("uri_file_path", uriFilePath.toString());
     super.onSaveInstanceState(outState);

之后,您应该始终在 onCreate 方法中恢复您的 uri:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) 
         if (uriFilePath == null && savedInstanceState.getString("uri_file_path") != null) 
             uriFilePath = Uri.parse(savedInstanceState.getString("uri_file_path"));
         
     

这是让你的 Uri 进入 onActivityResult 的最后一部分:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)     
    if (resultCode == RESULT_OK) 
         if (requestCode == 1) 
            String filePath = uriFilePath.getPath(); // Here is path of your captured image, so you can create bitmap from it, etc.
         
    
 

附:不要忘记为相机和分机添加权限。存储写入您的清单。

【讨论】:

我正在使用 FragmentDialog。我尝试按照您的方式执行此操作.. 我声明了 Uri,然后在方法“storeCapturedImage”中 - 我输入了 PackageManager 代码,然后我添加了 onSaveInstanceState() - 所有这些都在 onCreate 之前。然后在 onCreateDialog 中,我放置了“恢复您的 uri”代码,然后将 onActivityResult 放置在 onCreate 方法的正上方...请参阅下一条评论,了解我在“恢复您的 uri”代码之后放置的内容 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = getActivity().getLayoutInflater();查看 dialogView = inflater.inflate(R.layout.username_dialog, null); ImageView profilePic = dialogView.findViewById(R.id.profile_pic); profilePic.setImageResource(R.drawable.user_placeholder); profilePic.setOnClickListener(new View.OnClickListener() @Override public void onClick(View view) storeCapturedImage(); ); builder.setView(dialogView); 我真的很想知道为什么操作系统不向您发送 OnActivityResult 内部意图中的 uri。我希望有一个很好的理由,因为随身携带状态对 IMO 来说总是不是一件好事。 那么onActivityResult回调中的数据有什么用呢?【参考方案11】:

使用以下代码使用您的移动相机拍摄照片。 如果您使用的是高于 Lolipop 版本的 android,您还应该添加权限请求。

private void cameraIntent()
    
          Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
          startActivityForResult(intent, REQUEST_CAMERA);
    

@override
protected void onActivityResult(int requestCode, int resultCode, Intent data)   
     if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK)   
            Bitmap photo = (Bitmap) data.getExtras().get("data"); 
            imageView.setImageBitmap(photo);
       
 

【讨论】:

【参考方案12】:

您可以在此处打开相机或图库并将所选图像设置为imageview

private static final String IMAGE_DIRECTORY = "/YourDirectName";
private Context mContext;
private CircleImageView circleImageView;  // imageview
private int GALLERY = 1, CAMERA = 2;

在清单中添加权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="ANDROID.PERMISSION.READ_EXTERNAL_STORAGE" />

在 onCreate() 中

    requestMultiplePermissions(); // check permission 

    circleImageView = findViewById(R.id.profile_image);
    circleImageView.setOnClickListener(new View.OnClickListener() 
        public void onClick(View v) 
            showPictureDialog();
        
    );

显示选项对话框(从相机或图库中选择图像)

private void showPictureDialog() 
    AlertDialog.Builder pictureDialog = new AlertDialog.Builder(this);
    pictureDialog.setTitle("Select Action");
    String[] pictureDialogItems = "Select photo from gallery", "Capture photo from camera";
    pictureDialog.setItems(pictureDialogItems,
            new DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialog, int which) 
                    switch (which) 
                        case 0:
                            choosePhotoFromGallary();
                            break;
                        case 1:
                            takePhotoFromCamera();
                            break;
                    
                
            );
    pictureDialog.show();

从图库中获取照片

public void choosePhotoFromGallary() 
    Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(galleryIntent, GALLERY);

从相机中获取照片

private void takePhotoFromCamera() 
    Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    startActivityForResult(intent, CAMERA);

一旦图像被选中或捕获,

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 

    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == this.RESULT_CANCELED) 
        return;
    
    if (requestCode == GALLERY) 
        if (data != null) 
            Uri contentURI = data.getData();
            try 
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), contentURI);
                String path = saveImage(bitmap);
                Toast.makeText(getApplicationContext(), "Image Saved!", Toast.LENGTH_SHORT).show();
                circleImageView.setImageBitmap(bitmap);

             catch (IOException e) 
                e.printStackTrace();
                Toast.makeText(getApplicationContext(), "Failed!", Toast.LENGTH_SHORT).show();
            
        

     else if (requestCode == CAMERA) 
        Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
        circleImageView.setImageBitmap(thumbnail);
        saveImage(thumbnail);
        Toast.makeText(getApplicationContext(), "Image Saved!", Toast.LENGTH_SHORT).show();
    

现在是时候存储图片了

public String saveImage(Bitmap myBitmap) 
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
    File wallpaperDirectory = new File(Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
    if (!wallpaperDirectory.exists())   // have the object build the directory structure, if needed.
        wallpaperDirectory.mkdirs();
    

    try 
        File f = new File(wallpaperDirectory, Calendar.getInstance().getTimeInMillis() + ".jpg");
        f.createNewFile();
        FileOutputStream fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());
        MediaScannerConnection.scanFile(this,
                new String[]f.getPath(),
                new String[]"image/jpeg", null);
        fo.close();
        Log.d("TAG", "File Saved::---&gt;" + f.getAbsolutePath());

        return f.getAbsolutePath();
     catch (IOException e1) 
        e1.printStackTrace();
    
    return "";

请求权限

    private void requestMultiplePermissions() 
    Dexter.withActivity(this)
            .withPermissions(
                    Manifest.permission.CAMERA,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE)
            .withListener(new MultiplePermissionsListener() 
                @Override
                public void onPermissionsChecked(MultiplePermissionsReport report) 
                    if (report.areAllPermissionsGranted())   // check if all permissions are granted
                        Toast.makeText(getApplicationContext(), "All permissions are granted by user!", Toast.LENGTH_SHORT).show();
                    

                    if (report.isAnyPermissionPermanentlyDenied())  // check for permanent denial of any permission
                        // show alert dialog navigating to Settings
                        //openSettingsDialog();
                    
                

                @Override
                public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) 
                    token.continuePermissionRequest();
                
            ).
            withErrorListener(new PermissionRequestErrorListener() 
                @Override
                public void onError(DexterError error) 
                    Toast.makeText(getApplicationContext(), "Some Error! ", Toast.LENGTH_SHORT).show();
                
            )
            .onSameThread()
            .check();

【讨论】:

【参考方案13】:

我创建了一个对话框,其中包含从图库或相机中选择图像的选项。 回调为

如果图片来自图库,则为 Uri 如果图像是从相机捕获的,则作为文件路径的字符串。 图像作为文件从相机中选择的图像需要作为多部分文件数据上传到互联网上

首先我们在 AndroidManifest 中定义权限,因为我们需要在创建文件和从图库中读取图像时写入外部存储

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

在里面创建一个file_paths xml app/src/main/res/xml/file_paths.xml

带路径

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

然后我们需要定义file provier来生成Content uri来访问存储在外部存储中的文件

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="$applicationId.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

对话布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_>

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_
        android:layout_
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.50" />

    <ImageView
        android:id="@+id/gallery"
        android:layout_
        android:layout_
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="32dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline2"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_menu_gallery" />

    <ImageView
        android:id="@+id/camera"
        android:layout_
        android:layout_
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="32dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/guideline2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_menu_camera" />
</androidx.constraintlayout.widget.ConstraintLayout>

ImagePicker 日志

public class ImagePicker extends BottomSheetDialogFragment 
ImagePicker.GetImage getImage;
public ImagePicker(ImagePicker.GetImage getImage, boolean allowMultiple) 
    this.getImage = getImage;

File cameraImage;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    View view = inflater.inflate(R.layout.bottom_sheet_imagepicker, container, false);
    view.findViewById(R.id.camera).setOnClickListener(new View.OnClickListener() @
        Override
        public void onClick(View view) 
            if(ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) 
                requestPermissions(new String[] 
                    Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE
                , 2000);
             else 
                captureFromCamera();
            
        
    );
    view.findViewById(R.id.gallery).setOnClickListener(new View.OnClickListener() @
        Override
        public void onClick(View view) 
            if(ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) 
                requestPermissions(new String[] 
                    Manifest.permission.READ_EXTERNAL_STORAGE
                , 2000);
             else 
                startGallery();
            
        
    );
    return view;

public interface GetImage 
    void setGalleryImage(Uri imageUri);
    void setCameraImage(String filePath);
    void setImageFile(File file);
@
Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == Activity.RESULT_OK) 
        if(requestCode == 1000) 
            Uri returnUri = data.getData();
            getImage.setGalleryImage(returnUri);
            Bitmap bitmapImage = null;
        
        if(requestCode == 1002) 
            if(cameraImage != null) 
                getImage.setImageFile(cameraImage);
            
            getImage.setCameraImage(cameraFilePath);
        
    

private void startGallery() 
    Intent cameraIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    cameraIntent.setType("image/*");
    if(cameraIntent.resolveActivity(getActivity().getPackageManager()) != null) 
        startActivityForResult(cameraIntent, 1000);
    

private String cameraFilePath;
private File createImageFile() throws IOException 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Camera");
    File image = File.createTempFile(imageFileName, /* prefix */ ".jpg", /* suffix */ storageDir /* directory */ );
    cameraFilePath = "file://" + image.getAbsolutePath();
    cameraImage = image;
    return image;

private void captureFromCamera() 
    try 
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".provider", createImageFile()));
        startActivityForResult(intent, 1002);
     catch(IOException ex) 
        ex.printStackTrace();
    

像这样在Activity或片段中调用 在 Fragment/Activity 中定义 ImagePicker

ImagePicker imagePicker;

然后点击按钮调用dailog

      imagePicker = new ImagePicker(new ImagePicker.GetImage() 
            @Override
            public void setGalleryImage(Uri imageUri) 

                Log.i("ImageURI", imageUri + "");

                String[] filePathColumn = MediaStore.Images.Media.DATA;

                Cursor cursor = getContext().getContentResolver().query(imageUri, filePathColumn, null, null, null);
                assert cursor != null;
                cursor.moveToFirst();

                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                mediaPath = cursor.getString(columnIndex);
                // Set the Image in ImageView for Previewing the Media
                imagePreview.setImageBitmap(BitmapFactory.decodeFile(mediaPath));
                cursor.close();

            

            @Override
            public void setCameraImage(String filePath) 

                mediaPath =filePath;
                Glide.with(getContext()).load(filePath).into(imagePreview);

            

            @Override
            public void setImageFile(File file) 

                cameraImage = file;

            
        , true);
        imagePicker.show(getActivity().getSupportFragmentManager(), imagePicker.getTag());

【讨论】:

【参考方案14】:

您可以使用此代码来 onClick 监听器(您可以使用 ImageView 或按钮)

image.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePictureIntent.resolveActivity(getPackageManager()) != null) 
                startActivityForResult(takePictureIntent, 1);
            
        
    );

在你的 imageView 中显示

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) 
        Bundle extras = data.getExtras();
        bitmap = (Bitmap) extras.get("data");
        image.setImageBitmap(bitmap);

    

注意:将此插入清单

<uses-feature android:name="android.hardware.camera" android:required="true" />

【讨论】:

【参考方案15】:

Bitmap photo = (Bitmap) data.getExtras().get("data"); 从摄像头获取缩略图。有一篇关于如何从相机将图片存储在外部存储器中的文章。 useful link

【讨论】:

【参考方案16】:

请通过使用 Kotlin 和 Andoirdx 支持来执行此示例:

button1.setOnClickListener
        file = getPhotoFile()
        val uri: Uri = FileProvider.getUriForFile(applicationContext, "com.example.foto_2.filrprovider", file!!)
        captureImage.putExtra(MediaStore.EXTRA_OUTPUT, uri)

        val camaraActivities: List<ResolveInfo> = applicationContext.getPackageManager().queryIntentActivities(captureImage, PackageManager.MATCH_DEFAULT_ONLY)

        for (activity in camaraActivities) 
            applicationContext.grantUriPermission(activity.activityInfo.packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
        

        startActivityForResult(captureImage, REQUEST_PHOTO)
    

以及活动结果:

if (requestCode == REQUEST_PHOTO) 
        val uri = FileProvider.getUriForFile(applicationContext, "com.example.foto_2.filrprovider", file!!)
        applicationContext.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
        imageView1.viewTreeObserver.addOnGlobalLayoutListener 
            width = imageView1.width
            height = imageView1.height
            imageView1.setImageBitmap(getScaleBitmap(file!!.path , width , height))
        
        if(width!=0&&height!=0)
            imageView1.setImageBitmap(getScaleBitmap(file!!.path , width , height))
        else
            val size = Point()
            this.windowManager.defaultDisplay.getSize(size)
            imageView1.setImageBitmap(getScaleBitmap(file!!.path , size.x , size.y))
        

    

您可以在https://github.com/joelmmx/take_photo_kotlin.git获取更多详细信息

希望对你有帮助!

【讨论】:

【参考方案17】:

正如其他人所讨论的,使用data.getExtras().get("data") 只会得到低质量的缩略图

解决方案是使用您的 ACTION_IMAGE_CAPTURE 意图传递一个位置,告诉相机在哪里存储完整质量的图像。

代码是Kotlin,不需要任何权限。


val f = File("$getExternalFilesDir(null)/imgShot")
val photoURI = FileProvider.getUriForFile(this, "$packageName.fileprovider", f)
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        .apply  putExtra(MediaStore.EXTRA_OUTPUT, photoURI) 
startActivityForResult(intent, 1234)

然后处理拍照后的结果:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) 
    if (requestCode == 1234 && resultCode == Activity.RESULT_OK) 
        val bitmap = BitmapFactory.decodeFile(
                File("$getExternalFilesDir(null)/imgShot").toString()
        )
        // use imageView.setImageBitmap(bitmap) or whatever
    


您还需要添加一个外部 FileProvider,如 here 所述。 AndroidManifest.xml

<manifest>
    <application>

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="$applicationId.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provide_paths" />
        </provider>

    </application>
</manifest>

添加一个新文件app/src/main/res/xml/provide_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="." />
</paths>

最后,您应该用自己的逻辑替换 1234 以跟踪请求代码(通常是带有 RequestCode.CAPTURE_IMAGE 等成员的枚举)

【讨论】:

【参考方案18】:

2021 年 5 月,JAVA

在处理了本文后面描述的必要权限后, 在清单中添加:

<uses-permission 
    android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission 
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18"  />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
    android:name="android.hardware.camera"
    android:required="true" />
....

    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="$applicationId.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>
....

其中 $applicationId 是应用程序的包名,例如my.app.com

res->xml->provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
 <paths>
  <external-files-path name="my_images" path="Pictures" />
  <external-path name="external_files" path="."/>
    <files-path
    name="files"   path="." />
    <external-cache-path
      name="images" path="." />
 </paths>

活动中:

private void onClickCaptureButton(View view) 
    Intent takePictureIntent_ = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // Ensure that there's a camera activity to handle the intent
    if (takePictureIntent_.resolveActivity(getPackageManager()) != null) 
        // Create the File where the photo should go
        File photoFile_ = null;
        try 
            photoFile_ = createImageFile();
         catch (IOException ex) 
        
        if(photoFile_!=null)
            picturePath=photoFile_.getAbsolutePath();
        
        // Continue only if the File was successfully created
        if (photoFile_ != null) 
            Uri photoURI_ = FileProvider.getUriForFile(this,
               "my.app.com.fileprovider", photoFile_);
            takePictureIntent_.putExtra(MediaStore.EXTRA_OUTPUT, photoURI_);
            startActivityForResult(takePictureIntent_, REQUEST_IMAGE_CAPTURE);
        
    

还有三个动作:

...
private static String picturePath;
private static final int REQUEST_IMAGE_CAPTURE = 2;
...
private File createImageFile() throws IOException 
    // Create an image file name
    String timeStamp_ = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new 
      Date());
    String imageFileName_ = "JPEG_" + timeStamp_ + "_";
    File storageDir_ = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image_ = File.createTempFile(
            imageFileName_,  /* prefix */
            ".jpg",         /* suffix */
            storageDir_      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    picturePath= image_.getAbsolutePath();
    return image_;


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
   if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK 
   )

        try 
            File file_ = new File(picturePath);
            Uri uri_ = FileProvider.getUriForFile(this,
                    "my.app.com.fileprovider", file_);
            rasm.setImageURI(uri_);
         catch (/*IO*/Exception e) 
            e.printStackTrace();
        
    

@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
    savedInstanceState.putString("safar", picturePath);
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);

和:

 @Override
 protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) 
        picturePath = savedInstanceState.getString("safar");
    
 ....

【讨论】:

以上是关于从相机捕获图像并在活动中显示的主要内容,如果未能解决你的问题,请参考以下文章

从相机捕获图像并将其显示在android的另一个活动中

使用啥控件从相机捕获图像并在 ui 上显示为带有事件 xamarin ios 的缩略图

从活动中调用相机,捕获图像并上传到服务器

从相机捕获的图像被视为 ImageView 对象的问题。 - 安卓

从相机拍照后图像未在 ImageView 中设置

如何在android中保存从相机拍摄的图像