调用摄像头或者相册

372 阅读2分钟

调用摄像头拍照获得图片的步骤

  • 点击事件处理调用摄像头逻辑
  • 1:创建File对象,用于存放拍摄之后的图片
  • 2:存放在SD卡的应用关联缓存之下,为什么?因为6.0以后,读写SD卡被列为危险权限,所以使用应用关联目录则可以跳过这一步
  • 3:低于7.0使用Uri的fromFile()方法将File转换为Uri对象,这个Uri对象标识着output_image.jpg图片的本地真实路径。否则,就调用FileProvider的getUriForFile()方法将File对象转换为一个封装过的Uri对象。因为从7.0开始,直接使用本地真是路径的Uri被认为是不安全的,所以要使用FileProvider实际上是一种特殊的ContentProvider,它使用了和ContentProvider类似的机制来对数据进行保护,可以选择性的将封装过的Uri共享给外部,从而提高了应用的安全性。
  • 4:构建Intent对象,将action指定为android.media.action.IMAGE_CAPTURE,指定Uri,启动相机Activity
  • 5: 通过onActivityResult方法获取jpg并解析为Bitmap对象,设置到ImageView上即可
  • 6:添加判断图片旋转的方法,自动转屏
// 摄像头相关
    private val takePhoto = 1
    lateinit var imageUri: Uri
    lateinit var  outputImage: File
    
    // 调起摄像头
        cameraButton.setOnClickListener {
            // 创建File对象,暂存拍摄之后的图片
            outputImage = File(externalCacheDir, "output_image.jpg")
            if (outputImage.exists()) {
                outputImage.delete()
            }
            outputImage.createNewFile()
            // 将File转化为Uri对象,注意版本
            imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                FileProvider.getUriForFile(this, "com.example.camera.test", outputImage)
            } else {
                Uri.fromFile(outputImage)
            }
            // 启动相机程序
            val intent = Intent("android.media.action.IMAGE_CAPTURE")
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
            startActivityForResult(intent, takePhoto)
        }
        
        
        /**
     * 监听相机回调
     */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            takePhoto -> {
                if (resultCode == Activity.RESULT_OK) {
                    // 将拍照的结果取出来
                    val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
                    mImageView.setImageBitmap(rotateIfRequired(bitmap))
                }
            }
        }
    }

    /**
     * 如果需要旋转图片,先旋转图片
     */
    private fun rotateIfRequired(bitmap: Bitmap): Bitmap {
        val exif = ExifInterface(outputImage.path)
        val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
        ExifInterface.ORIENTATION_NORMAL)
        return when (orientation) {
            ExifInterface.ORIENTATION_ROTATE_90 -> rotateBitmap(bitmap, 90)
            ExifInterface.ORIENTATION_ROTATE_180 -> rotateBitmap(bitmap, 180)
            ExifInterface.ORIENTATION_ROTATE_270 -> rotateBitmap(bitmap, 270)
            else -> bitmap
        }
    }

    private fun rotateBitmap(bitmap: Bitmap, degree: Int): Bitmap {
        val matrix = Matrix()
        matrix.postRotate(degree.toFloat())
        val rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
        bitmap.recycle()
        return rotateBitmap
    }

调用相册获取图片的步骤

  • 1:实现点击方法
  • 2:打开文件选择器
  • 3:指定只显示图片
  • 4:调起
  • 5:回调方法中获取uri
// 从相册选择
        albumButton.setOnClickListener {
            // 打开文件选择器
            val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            // 指定只显示图片
            intent.type = "image/*"
            startActivityForResult(intent, fromAlbum)
        }
        
        /**
     * 监听相机回调
     */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            takePhoto -> {
                if (resultCode == Activity.RESULT_OK) {
                    // 将拍照的结果取出来
                    val bitmap = BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))
                    mImageView.setImageBitmap(rotateIfRequired(bitmap))
                }
            }

            fromAlbum -> {
                if (resultCode == Activity.RESULT_OK && data != null) {
                    data.data?.let { uri ->
                        val bitmap = getBitmapFromUri(uri)
                        mImageView.setImageBitmap(bitmap)
                    }
                }
            }
        }
    }

    private fun getBitmapFromUri(uri: Uri) = contentResolver
            .openFileDescriptor(uri, "r")?.use {
                BitmapFactory.decodeFileDescriptor(it.fileDescriptor)
            }