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


当前回答

使用下面的代码捕捉图片使用您的移动相机。 如果你使用的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);
     }  
} 

其他回答

以下是完整的代码:

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);



            }
        }
}

记住也要为相机添加权限。

下面是我用来捕捉和保存相机图像然后显示到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;
        }
    }

希望能有所帮助!

更新(2020)

谷歌已经添加了一个新的ActivityResultRegistry API,“让你处理startActivityForResult() + onActivityResult()以及requestPermissions() + onRequestPermissionsResult()流,而无需覆盖你的活动或片段中的方法,通过ActivityResultContract带来了增加的类型安全性,并为测试这些流提供了钩子”。

该API是在androidx中添加的。和androidx.fragment 1.3.0-alpha02。

所以你现在可以这样做:

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

有许多内置的activityresultcontract,允许您做不同的事情,如选择联系人,请求权限,拍照或拍摄视频。您可能对ActivityResultContracts感兴趣。拍摄上图。

注意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。

下面是一个示例活动,它将启动相机应用程序,然后检索图像并显示它。

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);
        }  
    } 
}

请注意,相机应用程序本身提供了查看/重拍图像的功能,一旦图像被接受,活动就会显示它。

下面是上面的活动使用的布局。它只是一个包含id为button1的Button和id为imageview1的ImageView的LinearLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/photo"></Button>
    <ImageView android:id="@+id/imageView1" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content"></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。

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

首先在activity中声明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中,因为如果你不这样做,用户在使用camera时旋转他的设备,你的uri将为null。

@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.
         }
    }
 }

附注:别忘了在你的Manifest中添加Camera和Ext. storage的写入权限。