Android - 如何从相机或图库拍摄照片

时间:2013-11-16 17:26:47

标签: android image camera

我想让用户从相机或设备中的现有图片(图库或其他)拍摄照片。我怎么能这样做?

我已经实现了下面的解决方案,这似乎工作正常,但文档很混乱,所以我想知道是否有更好的解决方案。

另外,请查看此相关帖子。在那里,您将看到如何获取图像路径或位图:Get/pick an image from Android's built-in Gallery app programmatically

因此,在我的解决方案中,您将创建一个TakePictureHelper对象并执行以下操作。

假设您显示一个对话框,用户可以选择“相机”或“其他”。当用户选择一个选项时,您可以拨打takeFromCamera()takeFromOther()。拍摄(或不拍摄)照片时,将调用onActivityResult()方法。在那里你会调用retrievePicture,它会返回图片的Uri,如果没有拍照,则为null。

如果我不清楚,请告诉我你的想法,分享想法或问我任何事情。

非常感谢!

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TakePictureHelper {

    public final static int REQUEST_CAMERA = 1;
    public final static int REQUEST_OTHER = 2;

    private Uri cameraImageUri;

    /**
     * Request picture from camera using the given title
     */
    public void takeFromCamera(Activity activity, String title)
    {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File cameraImageOutputFile = new File(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                createCameraImageFileName());
        cameraImageUri = Uri.fromFile(cameraImageOutputFile);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri);
        activity.startActivityForResult(Intent.createChooser(intent, title), REQUEST_CAMERA);
    }

    /**
     * Request picture from any app (gallery or whatever) using the given title
     */
    public void takeFromOther(Activity activity, String title)
    {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        activity.startActivityForResult(Intent.createChooser(intent, title), REQUEST_OTHER);
    }

    /**
     * Retrieve the picture, taken from camera or gallery.
     *
     * @return the picture Uri, or null if no picture was taken.
     */
    public Uri retrievePicture(Activity activity, int requestCode, int resultCode, Intent data)
    {
        Uri result = null;

        if (resultCode == Activity.RESULT_OK) {

            if (requestCode == REQUEST_OTHER) {
                result = data.getData();
            } else if (requestCode == REQUEST_CAMERA) {
                result = cameraImageUri;
            }
        }

        return result;
    }

    private String createCameraImageFileName() {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        return timeStamp + ".jpg";
    }
}

4 个答案:

答案 0 :(得分:4)

基于@ yurezcv的回答,这是我想出的(最重要的是如何在onActivityResult中检索图像):

private List<File> cameraImageFiles;

private void popImageChooser(){
    // Camera.
    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    final PackageManager packageManager = getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);

    cameraImageFiles = new ArrayList<File>();

    int i=0;
    for(ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(packageName);
        intent.putExtra(MediaStore.MEDIA_IGNORE_FILENAME, ".nomedia");

        File cameraImageOutputFile = new File(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                createCameraImageFileName());
        cameraImageFiles.add(cameraImageOutputFile);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraImageFiles.get(i)));
        i++;

        cameraIntents.add(intent);
    }

    // Filesystem.
    final Intent galleryIntent = new Intent();
    galleryIntent.setType("image/*");
    galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

    // Chooser of filesystem options.
    final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.attach_images_title));

    // Add the camera options.
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
    startActivityForResult(chooserIntent, ACTIVITY_REQUEST_CODE_IMAGE);
}


protected void onActivityResult(int requestCode, int resultCode, 
           Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case ACTIVITY_REQUEST_CODE_IMAGE:
        if(resultCode == RESULT_OK){

            Uri uri = null;
            if(imageReturnedIntent == null){   //since we used EXTRA_OUTPUT for camera, so it will be null

                for(int i=0;i<cameraImageFiles.size();i++){
                    if(cameraImageFiles.get(i).exists()){
                        uri = Uri.fromFile(cameraImageFiles.get(i));
                        break;
                    }
                }
                Log.d("attachimage", "from camera: "+uri);
            }
            else {  // from gallery
                uri = imageReturnedIntent.getData();
                Log.d("attachimage", "from gallery: "+uri.toString());
            }

            if(uri != null){
                attachImage(uri);
            }
        }
    }
}

答案 1 :(得分:3)

此解决方案适用于我:

private void addPhoto() {   
       // Camera.
    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);     
    final PackageManager packageManager = getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
    for(ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(packageName);
        intent.putExtra(MediaStore.MEDIA_IGNORE_FILENAME, ".nomedia");

        cameraIntents.add(intent);
    }

    // Filesystem.
    final Intent galleryIntent = new Intent();
    galleryIntent.setType("image/*");
    galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

    // Chooser of filesystem options.
    final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.add_new));

    // Add the camera options.
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
    startActivityForResult(chooserIntent, YOUR_REQUEST_CODE);
}

它创建了一个意图对话框,其中包含来自摄像机,文件系统等的所选图像的所有可能变体。

答案 2 :(得分:1)

  1. 在您的布局中创建一个按钮(通过单击此按钮将打开一个对话框,您可以在其中选择是否选择相机或广场)。

  2. 现在初始化其类中的按钮:

    - 在onCreate之前:

    Button btu;

    - 在onCreate中:

    btu = (Button) findViewById(R.id.BtUp);

  3. 方法调用相机和图库

  4. - 在onCreate启动之前

    int CAMERA_REQUEST = 1;
    

    - 方法调用相机

    public void callCamera() {
        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        cameraIntent.putExtra("crop", "true");
        cameraIntent.putExtra("aspectX", 0);
        cameraIntent.putExtra("aspectY", 0);
        cameraIntent.putExtra("outputX", 200);
        cameraIntent.putExtra("outputY", 150);
        startActivityForResult(cameraIntent, CAMERA_REQUEST);
    }
    

    - 方法调用库

    public void callGallery() {
        Intent intent = new Intent(Intent.ACTION_PICK,
                                   MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent,0);
    }
    
    1. 创建一个显示AlertDialog的方法,该方法似乎选择:

      public void showAlertDialog(Context context) {
      this.context = context;
      final String items[] = {getString(R.string.TextTakeCam), getString(R.string.TextTakeGal)};
      
      AlertDialog.Builder ab = new AlertDialog.Builder(MainActivity.this);
      ab.setTitle(getString(R.string.TextTitleDia));
      AlertDialog.Builder builder = ab.setItems(items, new DialogInterface.OnClickListener() {
          public void onClick(DialogInterface d, int choice) {
              if (choice == 0) {
                  callCamera();
              } else if (choice == 1) {
                  image.setVisibility(View.INVISIBLE);
                  callGallery();
              }
          }});
      ab.show();
      

      }

    2. 按钮

      中调用AlertDialog
      btu.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          String title = getString(R.string.TextUp);
          String msg = getString(R.string.TextUp2);
          showAlertDialog2(MainActivity.this,title,msg,true);
          //maneger.UpdateC(edname.getText().toString(),edfoto.getText().toString(),ednum. getText().toString());
          }
      });
      
    3. AndroidManifest.xml内部

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

答案 3 :(得分:1)

我找到了一种更好,更简单的方法从相机或画廊拍照,即使用此库https://android-arsenal.com/details/1/3623

您可以点击上面的链接或按以下步骤操作:

在项目中使用此库的步骤是:

  1. 向Gradle添加依赖项:

    编译'com.frosquivel:magicalcamera:4.4'

  2. 实施代码:

    PermissionGranted permissionGranted = new PermissionGranted(this); MagicalCamera magicalCamera = new MagicalCamera(this,permissionGranted); //参数this是当前活动     //拍摄照片的权限,如果用户检查拒绝,则为false     permissionGranted.checkCameraPermission();     //用于在设备内存中搜索和写入照片     //正常或SD内存     permissionGranted.checkReadExternalPermission();     permissionGranted.checkWriteExternalPermission();

  3. 致电从相机拍照:

    magicalCamera.takePhoto();

  4. 致电从图库中选择照片:

    magicalCamera.selectedPicture( “my_header_name”);

  5. 覆盖OnActivityResult();获取位图和路径的方法:

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    magicalCamera.resultPhoto(requestCode, resultCode, data);//with this form you obtain the bitmap
    Bitmap bitmap = magicalCamera.getPhoto();
    imageView.setImageBitmap(bitmap);
    //if you need path of bitmap use this code
    String path = magicalCamera.savePhotoInMemoryDevice(magicalCamera.getPhoto(),"myPhotoName","myDirectoryName", MagicalCamera.JPEG, true);
    

    if(path!= null){        Toast.makeText(MainActivity.this,“照片保存在设备中,请检查此路径:”+ path,Toast.LENGTH_SHORT).show();    }其他{        Toast.makeText(MainActivity.this,“抱歉你的照片不要写在devide,请联系fabian7593 @gmail并说出这个错误”,Toast.LENGTH_SHORT).show();    } }

  6. 有关详细信息,请参阅上面的链接