Android 拍照并获取图片缩略图的实现

更新日期: 2022-10-29 阅读次数: 4749 字数: 794 分类: Android

逻辑上是点击自己 Anroid APP 的拍照按钮,然后调用系统内置的相机应用,拍照后,将照片返回给我的 APP。

实际上就是启动一个 activity,并接收其返回的结果数据,然后再处理。

Android 官方推荐使用 AndroidX Activity 和 Fragment 中引入的 Activity Result API,以替代 startActivityForResult() 和 onActivityResult() API。

记录一下实现。

注意,这个方式获取到是图片的缩略图,并不是原始图片的尺寸,而且小非常多,几乎看不清的尺寸,如果要获取原始尺寸,需要参考Android 通过 ACTION_IMAGE_CAPTURE 拍照获取原尺寸的 bitmap 图片

第一步:XML 模板

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:orientation="vertical"
    >
   
   <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        >
      <ImageView
          android:id="@+id/imageViewResult"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />
   </ScrollView>

   <Button
        android:id="@+id/btnTakePicture"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/take_picture" />
</LinearLayout>

主要是两部分:

  • 按钮:点击触发拍照
  • ImageView: 展示拍摄的照片

第二步:Kotlin 实现

class SeedActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_seed)

        val launcher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    handleCameraImage(result.data)
                }
            }

        val btnTakePicture = findViewById<Button>(R.id.btnTakePicture)
        btnTakePicture.setOnClickListener {
            // intent to open camera app
            val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            launcher.launch(cameraIntent)
        }
    }

    private fun handleCameraImage(intent: Intent?) {
        val bitmap = intent?.extras?.get("data") as Bitmap
        val imageView = findViewById<ImageView>(R.id.imageViewResult)
        imageView.setImageBitmap(bitmap)
    }
}

核心是:

  • registerForActivityResult: 注册回调逻辑,处理返回的图片
  • launch intent: 打开手机摄像头

需要申请的权限

我模拟器里测试,manifest 文件是否配置权限好像都不影响。需要在真机上测试一下。确实需要,可能之前测试有问题。

<uses-feature android:name="android.hardware.camera"
	android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • required 可以设置为 false,代表即便没有摄像头也可以用这个 app,但是需要在运行时检测是否有摄像头。
  • 要保存完整尺寸的照片,Android 相机应用会保存一张完整尺寸的照片,前提是您为该照片指定了一个文件来保存它。这就需要 WRITE_EXTERNAL_STORAGE 权限。

废弃的方式:startActivityForResult

网上很多实现都是用的 startActivityForResult,甚至《第一行代码 - Android》第三版里也是

private fun dispatchTakePictureIntent() {
    val requestImageCapture = 1
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    try {
        startActivityForResult(takePictureIntent, requestImageCapture)
    } catch (e: ActivityNotFoundException) {
        // display error state to the user
    }
}

但是,在 Android Studio 里,会提示警告:

'startActivityForResult(Intent!, Int): Unit' is deprecated. Deprecated in Java

即,startActivityForResult 已废弃。

要了解 registerForActivityResult 的使用,详细可以参考我整理的两个例子

是否需要用到 CameraX, Camera2, Camera

从 Android 官方文档看,有三个摄像头相关类库 CameraX, Camera2, Camera。

但是否一定要用那三个库,我看直接用 intent 也行。

https://developer.android.com/training/camerax

CameraX is a Jetpack support library, built to help you make camera app development easier. It provides a consistent and easy-to-use API surface that works across most Android devices, with backward-compatibility to Android 5.0 (API level 21).

While CameraX leverages the capabilities of camera2, it uses a simpler approach that is lifecycle-aware and is based on use cases.

而 Camera 已废弃,所以目前首选是 CameraX。

但是文档看起来非常复杂,我猜测可能是要在自己 APP 内独立实现拍照功能才会用到吧。

如果是未来要实现用摄像头实时分析图片,大概会用到吧。

参考

  • 一个完整的流程介绍 https://intensecoder.com/android-open-camera-and-take-picture-in-kotlin
  • 官方的文档,用的不是拍照的案例 https://developer.android.com/training/basics/intents/result
  • 相对水的一个介绍 https://medium.com/swlh/intro-to-androidx-activity-result-apis-taking-a-picture-6013c3852c0b

tags: registerForActivityResult

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式