如何使用一个意图访问 android 中的照片和相机

How to access photos and camera in android using one intent

如果您使用 whatsapp 并单击附加按钮,menu/popup 将膨胀显示您可用于 select 图片甚至拍照的应用程序列表使用照片应用程序从您的相机

我正在制作一个应用程序,其功能几乎与 whatapp 的访问和拍照功能相同。问题是,我无法使用弹出对话框中列为应用程序之一的照片应用程序拍照,但使用 whatsapp 时我可以拍照。 当我从对话框中单击照片应用程序时在我的应用程序中显示,它显示了我所有的照片。但是当我从 whatsapp 弹出窗口点击照片应用程序时,它直接进入相机

public class ImagePickerActivity extends Activity {

private final int SELECT_PHOTO = 1;
private ImageView imageView;

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

    imageView = (ImageView)findViewById(R.id.imageView);

    Button pickImage = (Button) findViewById(R.id.btn_pick);
    pickImage.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View view) {                
            Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
            photoPickerIntent.setType("image/*");
            startActivityForResult(photoPickerIntent, SELECT_PHOTO);
        }
    });
}

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

    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK){
            try {
                final Uri imageUri = imageReturnedIntent.getData();
                final InputStream imageStream = getContentResolver().openInputStream(imageUri);
                final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
                imageView.setImageBitmap(selectedImage);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

        }
    }
}

在我的 android 清单中

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

我的代码需要更改什么才能从照片应用程序拍照?

因此,要将它们启动到本机相机应用程序或用户选择作为默认设置的相机应用程序,我相信您会使用它。

Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Intent chooser = Intent.createChooser(intent, title);
// Always use string resources for UI text.
// This says something like "Take a photo with"
String title = getResources().getString(R.string.chooser_title)

// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(chooser);
}
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
    startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}

编辑了它,并提供了一个样本,说明这样做需要什么。它可能不是简单地剪切和粘贴,但您应该能够从中弄清楚。抱歉,时间紧迫,所以我现在不能详细说明。

您可以通过以下代码拍照。

static final int REQUEST_IMAGE_CAPTURE = 1;

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
    }
}

并获取拍摄照片的缩略图。

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

由于需要保存截取的图片需要指定权限。

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

以下方法将创建一个抗碰撞图像文件。

字符串 mCurrentPhotoPath;

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

您可以像这样调用意图,

静态最终整数 REQUEST_TAKE_PHOTO = 1;

private void dispatchTakePictureIntent() {
    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) {
            // Error occurred while creating the File
            ...
        }
        // Continue only if the File was successfully created
        if (photoFile != null) {
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                    Uri.fromFile(photoFile));
            startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
        }
    }
}

If you saved your photo to the directory provided by getExternalFilesDir(), the media scanner cannot access the files because they are private to your app.

以下代码将调用系统的媒体扫描仪将您的照片添加到媒体提供商数据库中。使其在 Android 图库和其他图库应用程序中可用。

private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

资源是,

  1. Taking photos simply.
  2. Capture image from camera and display on Activity.
  3. Taking pictures with camera android programmatically

尝试添加android.permission.WRITE_EXTERNAL_STORAGE 到你的清单。

相机:

Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, 0);//zero can be replaced with any action code

图库:

Intent pickPhoto = new Intent(Intent.ACTION_PICK,
       android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto , 1);//one can be replaced with any action code

活动结果代码:

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 
    switch(requestCode) {
    case 1:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            imageview.setImageURI(selectedImage);
        }
    break;
    case 0:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            imageview.setImageURI(selectedImage);
        }
    break; 
    }

}

下面的代码将在本机对话框中显示相机和浏览存储选项。

 // Picks Camera first.
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.EXTRA_OUTPUT, outputFileUri);
  cameraIntents.add(intent);
}

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

// Chooser of filesystem options.
final Intent chooserIntent = Intent.createChooser(galleryIntent,
        "Select Image from");

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

startActivityForResult(chooserIntent, TAKE_PHOTO_CODE);

这对你有帮助!

并在自定义对话框中显示与 whatsapp 相同的内容,请参考下面的 link ..

使用一个 Intent 访问相机和照片

使用来自应用程序的意图填充自定义对话框的列表视图,这些应用程序可以像这样使用相机拍照或访问存储中的照片

private void acquirePicture(){
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");

Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

final Dialog dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
WindowManager.LayoutParams WMLP = dialog.getWindow().getAttributes();
WMLP.gravity = Gravity.CENTER;
dialog.getWindow().setAttributes(WMLP);
dialog.getWindow().setBackgroundDrawable(
        new ColorDrawable(android.graphics.Color.TRANSPARENT));
dialog.setCanceledOnTouchOutside(true);
dialog.setContentView(R.layout.about_dialog);
dialog.setCancelable(true);
lv=(ListView)dialog.findViewById(R.id.listView1);

populateDialogsListView();

dialog.show();
}

使用可以执行这两个操作的应用程序填充对话框的列表视图 (lv)

public void populateDialogListView(){

  PackageManager pm=getPackageManager();

 List<ResolveInfo> photoIntents = new ArrayList<>();

final List<ResolveInfo> listCam = packageManager.queryIntentActivities(
        captureIntent, PackageManager.GET_RESOLVED_FILTER);

final List<ResolveInfo> listGalley = packageManager.queryIntentActivities(photoPickerIntent, PackageManager.GET_RESOLVED_FILTER);

for (ResolveInfo activity : listCam) {
  photoIntents.add(activity);
}

for (ResolveInfo activity : listGalley) {
  photoIntents.add(activity);
}



Collections.sort(photoIntents,
        new ResolveInfo.DisplayNameComparator(pm));

AppAdapter appAdapter = new AppAdapter(pm, photoIntents);

lv.setAdapter(appAdapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                            long arg3) {
        // TODO Auto-generated method stub
        ResolveInfo launchable=appAdapter.getItem(position);
        ActivityInfo activity=launchable.activityInfo;
        ComponentName name=new ComponentName(activity.applicationInfo.packageName,
                activity.name);

       IntentFilter filter = launchable.filter;

        int actioncode;
        Intent  intent = new Intent();
        Uri uri;
        if(filter.hasAction(Intent.ACTION_PICK)){
            actioncode = 1;
            uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            intent.setData(uri);
        }else{
            actioncode = 0;
        }
        intent.setComponent(name);
        startActivityForResult(intent,actioncode);
    }
});

}

由于您正在使用列表视图创建自定义对话框,因此您必须为该列表视图创建适配器 (lv),它将用应用程序的名称和应用程序的图标填充列表视图

class AppAdapter extends ArrayAdapter<ResolveInfo> {
     private PackageManager pm=null;

  AppAdapter(PackageManager pm, List<ResolveInfo> apps) {
    super(Custom_chooser.this, R.layout.row, apps);
    this.pm=pm;
  }

@Override
public View getView(int position, View convertView,
                    ViewGroup parent) {
    if (convertView==null) {
        convertView=newView(parent);
    }

    bindView(position, convertView);

    return(convertView);
}

private View newView(ViewGroup parent) {
    return(getLayoutInflater().inflate(R.layout.row, parent, false));
}

private void bindView(int position, View row) {
    TextView label=(TextView)row.findViewById(R.id.label);

    label.setText(getItem(position).loadLabel(pm));

    ImageView icon=(ImageView)row.findViewById(R.id.icon);

    icon.setImageDrawable(getItem(position).loadIcon(pm));
}

有什么问题,告诉我