单一意图让用户拍照或从Android中的图库中选择图像

时间:2010-04-25 12:07:07

标签: android image camera android-intent gallery

我正在为Android 2.1开发一个应用程序。我想让我的用户在我的应用程序中选择个人资料图片(我没有使用联系人框架)。

理想的解决方案是启动一个使用户能够从图库中选择图像的意图,但如果没有合适的图像,则使用相机拍照(反之亦然,即允许用户拍摄)如果他们知道他们已经有了合适的图像了,那就让他们进入画廊并选择所说的图像。)

目前我可以做其中一个但不能两个都做。

如果我使用MediaStore.ACTION_IMAGE_CAPTURE直接进入相机模式,则无法进入图库。

如果我使用Intent.ACTION_PICK直接进入图库,那么我可以选择图像,但是如果我点击相机按钮(在图库的右上角),则会触发新的相机意图。因此,拍摄的任何照片都不会直接返回给我的应用程序。 (当然你可以按后退按钮退回到图库并从那里选择图像,但这是一个额外的不必要的步骤,并不是很直观)。

那么有没有办法将两者结合起来,或者我将不得不提供一个菜单来从我的应用程序中做一个或另一个?似乎这是一个常见的用例......当然我错过了什么?

3 个答案:

答案 0 :(得分:119)

您可以尝试这样做:

// ...
// Within your enclosing Class
// ...
private static final int SELECT_PICTURE = 1;

// ... 

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

Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

String pickTitle = "Select or take a new Picture"; // Or get from strings.xml
Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
chooserIntent.putExtra
(
  Intent.EXTRA_INITIAL_INTENTS, 
  new Intent[] { takePhotoIntent }
);

startActivityForResult(chooserIntent, SELECT_PICTURE);

要了解如何处理活动结果,请参阅this question


注意:关键点是如何确定是否使用了相机或图库。这个代码示例中显示了这一点:https://stackoverflow.com/a/12347567/294884

答案 1 :(得分:13)

更新:此时使用EXTRA_INITIAL_INTENTS的另一个答案是更好的答案。当我写回答时,EXTRA_INITIAL_INTENTS尚未存在,因为它已在API Level 5中添加。

  

那么有没有办法将两者结合起来   我将不得不提供菜单   从我的内心做一个或另一个   应用

编写自己的图库,其中包含您想要的功能。

我认为菜单会更简单。

  

似乎这是常用的   案件......当然我错过了什么?

您旁边的开发人员会认为图库应该允许您从本地图库中选择,或者跳到Flickr从那里进行选择。另一位开发人员会认为相机不仅应该允许通过相机“拍照”,而且可以通过从画廊中选择一些东西来“拍照”,从你想象的方式反转。另一位开发人员会认为图库应该允许从本地图库,Flickr或相机或网络连接的网络摄像头中进行选择。还有一个开发人员认为画廊是愚蠢的,用户应该只通过文件浏览器选择文件。等等。

所有这些都在一个环境(手机)中,其中操作系统的闪存非常宝贵。

因此,恕我直言,核心Android团队选择为你按照你认为合适的方式组装构建模块,而不是试图适应所有可能的模式,这并不完全令人震惊。

答案 2 :(得分:2)

我的答案几乎与@Macarse解决方案完全相同,但我还添加了另一个展示图库应用程序的意图(例如:Google照片),并用Kotlin编写:

val REQUEST_CODE_GET_IMAGE = 101

private fun addProfileImage() {
    val pickImageFileIntent = Intent()
    pickImageFileIntent.type = "image/*"
    pickImageFileIntent.action = Intent.ACTION_GET_CONTENT

    val pickGalleryImageIntent = Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI)

    val captureCameraImageIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

    val pickTitle = "Capture from camera or Select from gallery the Profile photo"
    val chooserIntent = Intent.createChooser(pickImageFileIntent, pickTitle)
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(captureCameraImageIntent, pickGalleryImageIntent))
    startActivityForResult(chooserIntent, REQUEST_CODE_GET_IMAGE)
}

从结果意图中提取图像:

private var imageTempFile: File? = null
private var imageMimeType: String? = null

private fun extractImage(intent: Intent?) {
    val imageUri = intent?.data
    imageUri?.let {
        Glide.with(this)
                .load(imageUri)
                .into(profileImageCiv)
        imageTempFile = MediaUtils.copyContentFromUriToCacheFile(this, imageUri, Settings.DIRECTORY_CACHE_TEMP_PROFILE_IMAGE)
        imageMimeType = MediaUtils.getMimeType(this, imageUri)
    } ?: run {
        intent?.extras?.get("data")?.let { bitmap ->    // Bitmap was returned as raw bitmap
            Glide.with(this)
                    .load(bitmap)
                    .into(profileImageCiv)
            imageTempFile = MediaUtils.writeBitmapToCacheFile(this, bitmap as Bitmap, Settings.DIRECTORY_CACHE_TEMP_PROFILE_IMAGE)
            imageMimeType = "image/jpeg"    // The bitmap was compressed as JPEG format. The bitmap itself doesn't have any format associated to it
        } ?: run {
            imageTempFile = null
            imageMimeType = null
            Log.e("Intent data is null.")
            Log.d("Error during photo selection")
        }
    }
}