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


当前回答

坏的质量

根据我的经验,如果我们使用

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, RESULT_ADD_PHOTO);

和处理onActivityResult()

Bitmap thumbnail= (Bitmap) data.getExtras().get("data");

它只会给你一个缩略图,当然有一个坏的质量。

不错的质量

您可以显示相机和保存您的图像文件在公共目录,例如在文档目录

在onClick()中使用这个

String imagePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) +
                File.separator + "your_image_name.jpeg";
Intent i =new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageFile = new File(imagePath );
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
startActivityForResult(i, RESULT_ADD_PHOTO);

在onActivityResult()中

Bitmap imageBitmap1 = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap imageBitmap = Bitmap.createBitmap(imageBitmap1, 0, 0, imageBitmap1.getWidth(), imageBitmap1.getHeight(), matrix, true);
binding.imageView.setImageBitmap(imageBitmap);

我使用postRotate(),因为在我的代码中,图像结果向左旋转,所以我需要将其旋转90

其他回答

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

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

                }

            }

你得好好研究一下相机。(我认为要做到你想要的,你必须保存当前的图像到你的应用程序,在那里做选择/删除,然后召回相机再试一次,而不是直接在相机内部重试。)

更新(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。

2021年5月,爪哇

在处理了本文旁边所述的必要权限后, 在manifest中添加:

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

and

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

and:

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

请使用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上获得更多详细信息

我希望它能帮助你!