谷歌照片与图库 - 意图选择器

时间:2014-07-10 23:49:28

标签: android android-intent camera android-photos

在我的应用中,我允许用户从他们的图库中选择个人资料图片,如下所示:

enter image description here

当您点击第一个选项时,在我的Android 5.0设备上,我得到了这个:

enter image description here

如果我使用基于AOSP项目的普通图库应用程序,一切正常,花花公子。但是,Photo的应用似乎使用了不同的意图。

以下是我处理普通图库代码的方法:

Intent photoPickerIntent = new Intent(
                    Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            photoPickerIntent.setType("image/*");
            photoPickerIntent.putExtra("crop", "true");
            photoPickerIntent.putExtra("outputX", 300);
            photoPickerIntent.putExtra("outputY", 300);
            photoPickerIntent.putExtra("aspectX", 1);
            photoPickerIntent.putExtra("aspectY", 1);
            photoPickerIntent.putExtra("scale", true);
            photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
            photoPickerIntent.putExtra("outputFormat",
                    Bitmap.CompressFormat.JPEG.toString());
            startActivityForResult(photoPickerIntent, RESULT_LOAD_IMAGE);

然后是意图结果处理程序:

public void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == RESULT_LOAD_IMAGE
            && resultCode == Activity.RESULT_OK) {

        if (data != null) {

            tempFile = getTempFile();

            filePath = Environment.getExternalStorageDirectory() + "/"
                    + "temporary_holder.jpg";
            Log.d("LOAD REQUEST filePath", filePath);

            Bitmap selectedImage = BitmapFactory.decodeFile(filePath);
            iPP.setImageBitmap(selectedImage);

        }

        imagePath = filePath;
        new UploadImage().execute();
    }
}

上面的一些帮助函数:

   private static Uri getTempUri() {
        return Uri.fromFile(getTempFile());
    }

    private static File getTempFile() {

        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {

            File file = new File(Environment.getExternalStorageDirectory(),
                    "temporary_holder.jpg");
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return file;
        }
        return null;
    }

其中一些可能不需要显示,但我将其全部包括在内,以防干扰。

当我使用Google相册来挑选照片时,我的ImageView是空白的(而不是填充选定的选项)。图像未被选中,我无法进入手动裁剪视图,就像我在图库中设置的那样。 基本上没有任何反应。


响应答案的新代码

        photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
        photoPickerIntent.setType("image/*");
        photoPickerIntent.putExtra("crop", "true");
        photoPickerIntent.putExtra("outputX", 300);
        photoPickerIntent.putExtra("outputY", 300);
        photoPickerIntent.putExtra("aspectX", 1);
        photoPickerIntent.putExtra("aspectY", 1);
        photoPickerIntent.putExtra("scale", true);
        photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
        photoPickerIntent.putExtra("outputFormat",
                Bitmap.CompressFormat.JPEG.toString());
        startActivityForResult(photoPickerIntent, RESULT_LOAD_IMAGE);



public void onActivityResult(int requestCode, int resultCode, Intent data) {



    if (resultCode == Activity.RESULT_OK) {

        if (data != null) {

            Log.i("data", data.toString());

            switch (requestCode) {

                case RESULT_LOAD_IMAGE:

                    Log.i("RESULT_LOAD_IMAGE", "MARK");
                    // Received an image from the picker, now send an Intent for cropping
                    final String CROP_ACTION = "com.android.camera.action.CROP";
                    Intent photoCropIntent = new Intent(CROP_ACTION);
                    photoCropIntent.putExtra("crop", "true");
                    photoCropIntent.putExtra("aspectX", 1);
                    photoCropIntent.putExtra("aspectY", 1);
                    photoCropIntent.putExtra("outputX", 300);
                    photoCropIntent.putExtra("outputY", 300);
                    photoCropIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
                    photoCropIntent.putExtra("outputFormat",
                            Bitmap.CompressFormat.JPEG.toString());
                    photoCropIntent.setData(data.getData());

                    startActivityForResult(photoPickerIntent, RESULT_CROP_IMAGE);

                    break;

                case RESULT_CROP_IMAGE:

                    Log.i("RESULT_CROP_IMAGE", "MARK");

                    tempFile = getTempFile();
                    imagePath = Environment.getExternalStorageDirectory() + "/"   + "temporary_holder.jpg";
                    Log.i("imagePath", imagePath);

                    Uri selectedImageURI = data.getData();
                    InputStream image_stream;
                    try {
                        image_stream = getActivity().getContentResolver().openInputStream(selectedImageURI);
                        Bitmap bitmap = BitmapFactory.decodeStream(image_stream);
                        iPP.setImageBitmap(bitmap);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                    new UploadImage().execute();

                    break;

                default:
                    // Handle default case
            }
        }

    }

}

以上代码也不起作用。我试着使它类似于下面的答案。会发生什么:

我点击"从图库中选择"。而且它不再给我一个选择,现在它直接从库存库开放(这不是什么大不了的事)。我点击图片,它似乎再次开始相同的intent - 它会让画廊想要我选择另一张图片:而不是裁剪Activity。然后在第二次之后,它将使用所选文件设置ImageView

2 个答案:

答案 0 :(得分:5)

<强>解决方案

首先,更新photoPickerIntent以使用ACTION_GET_CONTENT,并删除与裁剪相关的额外内容,因为裁剪将在稍后由另一个Intent处理:

        Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
        photoPickerIntent.setType("image/*");
        // Do not include the extras related to cropping here;
        // this Intent is for selecting the image only.
        startActivityForResult(photoPickerIntent, RESULT_LOAD_IMAGE);

然后,onActivityResult()必须处理两个结果:RESULT_LOAD_IMAGE将为裁剪发送另一个意图,而RESULT_CROP_IMAGE将继续像以前一样处理:

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            if (data != null) {
                switch (requestCode) {
                case RESULT_LOAD_IMAGE:
                    // Received an image from the picker, now send an Intent for cropping
                    final String CROP_ACTION = "com.android.camera.action.CROP";
                    Intent photoCropIntent = new Intent(CROP_ACTION);
                    photoCropIntent.setData(data.getData());

                    // TODO: first get this running without extras, then test each one here
                    startActivityForResult(photoCropIntent, RESULT_CROP_IMAGE);
                    break;
                case RESULT_CROP_IMAGE:
                    // Received the cropped image, continue processing.  Note that this 
                    // is just copied and pasted from your question and may have 
                    // omissions.
                    tempFile = getTempFile();

                    filePath = Environment.getExternalStorageDirectory() + "/"
                            + "temporary_holder.jpg";
                    Log.d("LOAD REQUEST filePath", filePath);

                    Bitmap selectedImage = BitmapFactory.decodeFile(filePath);
                    iPP.setImageBitmap(selectedImage);

                    imagePath = filePath;
                    new UploadImage().execute();
                    break;
                default:
                    // Handle default case
                }
            }
        }

请注意,尽管我测试了此代码的一部分,但我还没有在运行时测试整个代码块。但是,如果它开箱即用,它应该非常接近。如果您有任何问题或疑问,请发表评论,我会相应地更新我的答案。

<强>背景

在安装了AOSP Gallery2(com.android.gallery3d)和照片的Android 5.0.1(API 21)设备上,我运行了您的Intent。我被提示在图库或照片之间进行选择。

当我选择照片时,会出现一个选择器,然后我选择了一个图像。我立即回到Activity,没有裁剪选项。

当我选择Gallery时,会出现一个选择器,然后我选择了一个图像。然后我被提示选择一个用于裁剪的应用程序。 照片和图库均作为裁剪选项提供。

选择图库时,这是有趣的日志输出:

// Send the Intent
3-07 15:20:10.347      719-817/? I/ActivityManager﹕ Displayed android/com.android.internal.app.ResolverActivity: +127ms

// Choose Gallery
03-07 15:20:27.762      719-735/? I/ActivityManager﹕ START u0 {act=android.intent.action.PICK typ=image/* flg=0x3000000 cmp=com.android.gallery3d/.app.GalleryActivity (has extras)} from uid 10084 on display 0
// (fixing highlighting after MIME type on previous line) */
03-07 15:20:27.814  22967-22967/? W/GalleryActivity﹕ action PICK is not supported
03-07 15:20:27.814  22967-22967/? V/StateManager﹕ startState class com.android.gallery3d.app.AlbumSetPage
03-07 15:20:27.967      719-817/? I/ActivityManager﹕ Displayed com.android.gallery3d/.app.GalleryActivity: +190ms

// Pick an image
3-07 15:21:45.993  22967-22967/? V/StateManager﹕ startStateForResult class com.android.gallery3d.app.AlbumPage, 1
03-07 15:21:46.011  22967-22967/? D/AlbumPage﹕ onSyncDone: ********* result=0
03-07 15:21:46.034  22967-24132/? I/GLRootView﹕ layout content pane 1080x1701 (compensation 0)
03-07 15:21:48.447     719-1609/? I/ActivityManager﹕ START u0 {act=com.android.camera.action.CROP dat=content://media/external/images/media/1000 flg=0x2000000 cmp=android/com.android.internal.app.ResolverActivity (has extras)} from uid 10100 on display 0

首先,请注意W/GalleryActivity﹕ action PICK is not supported。我不确定它为什么会起作用,但据Dianne Hackborn说,"...you should consider ACTION_PICK deprecated. The modern action is ACTION_GET_CONTENT which is much better supported..."我在上面的解决方案中已经解决了这个问题。

然而,好消息是,在选择图片后,.putExtra("crop", "true");会导致图库发送另一个Intent进行裁剪。日志清楚地显示了要使用的操作和数据。

我测试了这个裁剪意图,我被提示选择一个用于裁剪的应用程序,就像之前一样。同样,照片和图库都作为选项呈现,它们都带来了裁剪界面。

虽然照片支持按Intent进行裁剪,但它只会忽略与ACTION_PICK中的裁剪相关的额外内容,而图库则会在选择图像后通过发送另一个Intent进行响应。无论如何,拥有工作裁剪的细节Intent会导致上述解决方案。

答案 1 :(得分:2)

我已经用这种方式解决了这个问题。

选择图片:

private void pickUserImage() {

    if (doHavePermission()) {
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        photoPickerIntent.setType("image/*");
        photoPickerIntent.putExtra("crop", "true");
        photoPickerIntent.putExtra("scale", true);
        photoPickerIntent.putExtra("outputX", 256);
        photoPickerIntent.putExtra("outputY", 256);
        photoPickerIntent.putExtra("aspectX", 1);
        photoPickerIntent.putExtra("aspectY", 1);
        photoPickerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT, getTempUri());
        startActivityForResult(photoPickerIntent, PICK_FROM_GALLERY);
    }
}

使用的方法 getTempUri()

private Uri getTempUri() {
    return Uri.fromFile(getTempFile());
}

private File getTempFile() {

    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

        File file = new File(Environment.getExternalStorageDirectory(),TEMP_PHOTO_FILE);
        try {
            file.createNewFile();
        } catch (IOException e) {
            Log.printStackTrace(e);
        }

        return file;
    } else {

        return null;
    }
}

获取所选图片

    @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == PICK_FROM_GALLERY) {
            if (data!=null) {

                Uri selectedImageUri = data.getData();
                //String tempPath = getPath(selectedImageUri, UserProfileActivity.this);
                String url = data.getData().toString();
                if (url.startsWith("content://com.google.android.apps.photos.content")){
                    try {
                        InputStream is = getContentResolver().openInputStream(selectedImageUri);
                        if (is != null) {
                            Bitmap selectedImage = BitmapFactory.decodeStream(is);
                            //You can use this bitmap according to your purpose or Set bitmap to imageview
                            if (selectedImage != null) {
                                isImageUpdated = true;
                                isImageUpdated = true;
                                Bitmap resizedBitmap = null;
                                if (selectedImage.getWidth() >= 256 && selectedImage.getHeight() >= 256) {
                                    resizedBitmap = Bitmap.createBitmap(selectedImage,
                                            selectedImage.getWidth() - 128,
                                            selectedImage.getHeight() - 128,
                                            256, 256);
                                }
                                if (resizedBitmap != null) {
                                    imageViewUserImage.setImageDrawable(ImageHelper.getRoundedCornerImage(resizedBitmap, 20));
                                } else {
                                    imageViewUserImage.setImageDrawable(ImageHelper.getRoundedCornerImage(selectedImage, 20));
                                }
                            }
                        }
                    } catch (FileNotFoundException e) {
                        Log.printStackTrace(e);
                    }
                } else {
                    File tempFile = getTempFile();
                    String filePath = Environment.getExternalStorageDirectory() + "/" + TEMP_PHOTO_FILE;
                    Log.d(TAG, "path " + filePath);

                    Bitmap selectedImage = BitmapFactory.decodeFile(filePath);
                    if (selectedImage != null) {
                        isImageUpdated = true;
                        imageViewUserImage.setImageDrawable(ImageHelper.getRoundedCornerImage(selectedImage, 20));
                    }
                    if (tempFile.exists()) {
                        tempFile.delete();
                    }
                }
            }
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}

图像转换为圆角图像,如下所示:

public class ImageHelper {

    public static RoundedBitmapDrawable getRoundedCornerImage(Bitmap bitmap, int cornerRadius) {
        RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(null, bitmap);
        dr.setCornerRadius(cornerRadius);
        return dr;
    }
}

回答太晚了,但它可以帮助别人。