谷歌照片与图库 - 意图选择器 [英] Google Photos vs Stock Gallery - Intent Picker

查看:38
本文介绍了谷歌照片与图库 - 意图选择器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my app, I allow the user to pick a profile image from their gallery, like so:

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

When You click the first option, on my Android 5.0 device, I get this:

如果我使用基于 AOSP 项目的普通 Gallery 应用程序,则一切正常且花花公子.但是,照片的应用似乎使用了不同的意图.

If I use the normal Gallery app that is based off the AOSP project, everything works fine and dandy. However, the Photo's app appears to use a different intent.

这是我处理普通画廊代码的方式:

Here is how I handle code for the normal gallery:

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

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

And then the intent result handler:

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

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

Some of that is probably not needed to show but I included it all in case it is interfering.

当我使用 Google 相册挑选照片时,我的 ImageView 是空白的(而不是用选定的照片填充).未选择图像,我无法像在图库中设置的那样进入手动裁剪视图.所以基本上什么都不会发生.

When I use Google Photos to pick a photo, my ImageView is blank (instead of filling with selected pick). The image is not selected and I can't go to the manual cropping view like I have it set with the Gallery. So basically, nothing happens.

响应答案的新代码

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

    }

}

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

The above code isn't working either. I tried to make it resemble the answer below. What happens is:

我点击从图库中选择".它不再给我选择,现在它直接从库存画廊打开(这没什么大不了的).我单击图像,它...似乎再次开始相同的 intent —— 它带回了画廊希望我选择另一个图像:而不是裁剪 Activity.然后在第二次之后,它将使用所选文件设置我的 ImageView.

I click "Choose from Gallery". And it does not give me a choice anymore, now it opens directly from the stock Gallery (that is not a big deal). I click on the image, and it ... appears to start the same intent over again -- it brings back the gallery wanting me to pick another image: instead of the Cropping Activity. Then after the second time, it will set my ImageView with the selected file.

推荐答案

解决方案

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

First, update the photoPickerIntent to use ACTION_GET_CONTENT, and remove the extras related to cropping, since cropping will be handled by another Intent later:

        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 将继续处理和以前一样:

Then, onActivityResult() will have to handle two results: RESULT_LOAD_IMAGE will send another intent for the crop, and RESULT_CROP_IMAGE will continue processing as you did before:

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

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

Note that although I've tested parts of this code, I haven't tested this entire block of code at runtime. If it doesn't work right out-of-the-box, though, it should be pretty close. Please comment if you have any questions or issues, and I'll update my answer accordingly.

背景

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

On an Android 5.0.1 (API 21) device with both AOSP Gallery2 (com.android.gallery3d) and Photos installed, I ran your Intent. I was prompted to choose between Gallery or Photos.

当我选择照片时,出现了一个选择器,我选择了一张图片.我立即返回到我的 Activity,没有任何裁剪选项.

When I chose Photos, a picker was presented, and I picked an image. I was immediately returned to my Activity, with no cropping options.

当我选择图库时,出现了一个选择器,我选择了一张图片.然后我被提示选择一个应用程序进行裁剪.照片和图库均作为裁剪选项呈现.

When I chose Gallery, a picker was presented, and I picked an image. I was then prompted to choose an app for cropping. Both Photos and Gallery were presented as options for cropping.

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

Here's the interesting log output when choosing 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:不支持动作 PICK.我不确定它为什么有效,但根据 Dianne Hackborn,"...您应该考虑不推荐使用 ACTION_PICK.现代操作是 ACTION_GET_CONTENT,它得到了更好的支持..." 我已经在我的上面的解决方案.

First, note W/GalleryActivity﹕ action PICK is not supported. I'm not sure why it works, but according to Dianne Hackborn, "...you should consider ACTION_PICK deprecated. The modern action is ACTION_GET_CONTENT which is much better supported..." I've addressed this in my solution above.

不过,好消息是,似乎在选择了一张图片之后,.putExtra("crop", "true"); 会导致 Gallery 发送另一个 Intent用于种植.日志清楚地显示了要使用的操作和数据.

The good news is, however, it seems that after picking an image, .putExtra("crop", "true"); causes Gallery to send another Intent for cropping. And the log clearly shows the action and data to use.

我测试了这种裁剪意图,并提示我选择一个应用进行裁剪,就像以前一样.再一次,照片和图库都作为选项提供,它们都提供了裁剪界面.

I tested this cropping intent, and I was prompted to choose an app for cropping, just like before. And again, both Photos and Gallery were presented as options, and they both brought up cropping interfaces.

看起来虽然照片支持 Intent 裁剪,但它只是忽略了 ACTION_PICK 中与裁剪相关的额外内容,而 Gallery 通过发送另一个 Intent 选择图像后.无论如何,拥有工作裁剪 Intent 的详细信息会导致上述解决方案.

It seems that although Photos supports cropping by Intent, it just ignores the extras relating to cropping in ACTION_PICK, whereas Gallery responds by sending another Intent after picking an image. Regardless, having the details of a working cropping Intent leads to the solution above.

这篇关于谷歌照片与图库 - 意图选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆