5

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

在此处输入图像描述

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

在此处输入图像描述

如果我使用基于 AOSP 项目的普通 Gallery 应用程序,一切正常且花花公子。但是,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 Photos 挑选照片时,我的 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- 它带回画廊希望我选择另一个图像:而不是 Cropping Activity。然后在第二次之后,它将ImageView使用所选文件设置我的。

4

2 回答 2

5

解决方案

首先,更新photoPickerIntentto use 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,没有裁剪选项。

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

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

// 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 的说法,“......你应该考虑ACTION_PICK弃用。现代行动是ACTION_GET_CONTENT更好的支持......” 我已经在上面的解决方案中解决了这个问题。

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

我测试了这种裁剪意图,并提示我选择一个应用程序进行裁剪,就像以前一样。再一次,照片和画廊都作为选项呈现,它们都带来了裁剪界面。

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

于 2015-03-07T07:19:53.150 回答
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;
    }
}

现在回答为时已晚,但它可以帮助别人。

于 2017-05-26T05:05:04.300 回答