2018 年 Android 上图库的选图方法是什么?

What's the way to pick images from gallery on Android in 2018?

我想了解社区对从常见来源获取图像以在我们的应用程序中使用的问题的意见 Android。 我知道早在 2010 年就有关于堆栈溢出的问题,但我发现这个简单任务的答案有点多。

也许任何人都知道一些轻量级库可以从画廊(或其他常见来源)获取图像,因此代码可以保持简单和可读性

可能是这样的:

            Bitmap image;

            SomeCoolLib.
            .performImageSelect()
            .asBitmap()  
            .listener(new RequestListener<String, Bitmap>() {
                @Override
                public boolean onException(Exception e) {
                    e.printStackTrace();
                    return false;
                }

                @Override
                public boolean onCancel() {
                    return false;
                }
            }).into(image);

让用户:

最好的方法是使用 Android 存储访问框架 (https://developer.android.com/guide/topics/providers/document-provider.html)。

例如,在您的 activity 中,您可以请求设备和文档类型(如果要过滤,请注意 intent.setType 方法按文档类型)。

此代码将打开 android 文档选择器并让用户选择图像:

public class MainActivity extends AppCompatActivity {

    private static final int OPEN_DOCUMENT_CODE = 2;

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

        findViewById(R.id.floatingActionButton).setOnClickListener(view ->    {
            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");
            startActivityForResult(intent, OPEN_DOCUMENT_CODE);
        });

    }
}

然后,只需在相同的 activity 中执行 onActivityResult 即可接收所选图像:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    if (requestCode == OPEN_DOCUMENT_CODE && resultCode == RESULT_OK) {
        if (resultData != null) {
            // this is the image selected by the user
            Uri imageUri = resultData.getData();
        }
    }
}

1、选择图片

如果你使用这个(旧样式):

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");

或者这个(官方推荐):

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");

这些代码将在 Android 8 中打开 FileManager,这很难用。

如果你想在用户设备上打开相册应用程序并选择一张照片,你应该使用这个(我推荐):

Intent intent = new Intent(Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

之前所有这些方式都会在 onActivityResult(int, int, Intent).

中得到一个 Uri

2、处理Uri

有时候我们需要图片的真实路径,你应该使用那些代码:

@Nullable
public static String getImagePathFromUri(@Nullable Uri aUri) {
    String imagePath = null;
    if (aUri == null) {
        return imagePath;
    }
    if (DocumentsContract.isDocumentUri(ApplicationContext.get(), aUri)) {
        String documentId = DocumentsContract.getDocumentId(aUri);
        if ("com.android.providers.media.documents".equals(aUri.getAuthority())) {
            String id = documentId.split(":")[1];
            String selection = MediaStore.Images.Media._ID + "=" + id;
            imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
        } else if ("com.android.providers.downloads.documents".equals(aUri.getAuthority())) {
            Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
                    Long.valueOf(documentId));
            imagePath = getImagePath(contentUri, null);
        }
    } else if ("content".equalsIgnoreCase(aUri.getScheme())) {
        imagePath = MediaUtils.getImagePath(aUri, null);
    } else if ("file".equalsIgnoreCase(aUri.getScheme())) {
        imagePath = aUri.getPath();
    }
    return imagePath;
}

private static String getImagePath(Uri aUri, String aSelection) {
    String path = null;
    Cursor cursor = ApplicationContext.get()
            .getContentResolver()
            .query(aUri, null, aSelection, null, null);
    if (cursor != null) {
        if (cursor.moveToFirst()) {
            path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        }
        cursor.close();
    }
    return path;
}