Android Camera拍照学习

499 阅读2分钟

1.相机

1.在Manifest中添加相机权限

<uses-permission android:name="android.permission.CAMERA"/>

2.打开相机

 companion object {
    private const val REQUEST_PERMISSION:Int = 0x11
    private const val REQUEST_IMAGE_CAPTURE:Int = 0x12
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      //判断用户是否赋予过权限
      val isGranted = checkSelfPermission(android.Manifest.permission.CAMERA)
      if (isGranted != PackageManager.PERMISSION_GRANTED){//如果没有则请求权限
            requestPermissions(arrayOf(android.Manifest.permission.CAMERA), REQUEST_PERMISSION)

      }else{
           takePhoto()
      }
}else{
      takePhoto()
}
//打开相机
private fun takePhoto() {
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    if (takePictureIntent.resolveActivity(packageManager) != null) {
          startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
    }
}

//请求权限回调
override fun onRequestPermissionsResult(requestCode: Int, 
    permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == REQUEST_PERMISSION){
          permissions.forEachIndexed { index, s ->
                if (s == android.Manifest.permission.CAMERA){
                      if (grantResults[index] == PackageManager.PERMISSION_GRANTED){
                            takePhoto()
                      }
                }
          }

    }
}

3.获取缩略图

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK){
              val imageBitmap = data?.extras?.get("data") as Bitmap
              log("$imageBitmap")
        }
  }

4.获取原图

一般来说,用户用设备摄像头捕捉到的任何照片都应该保存在设备的公共外部存储中,以便所有应用程序都可以访问这些照片。共享照片的正确目录由getExternalStoragePublicDirectory()提供,带有DIRECTORY_PICTURES参数。由于此方法提供的目录在所有应用程序之间共享,因此对其进行读写分别需要READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限。写权限隐式地允许读取,所以如果您需要写到外部存储,那么您只需要请求一个权限:

  • 申请权限
<manifest ...>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>
  • 一旦确定了文件的目录,就需要创建一个抗冲突的文件名。您可能还希望将路径保存在成员变量中以供以后使用。下面是一个示例解决方案,该方法使用日期-时间戳为新照片返回唯一的文件名:
private var mCurrentPhotoPath: String? = null//图片路径
private fun createImageFile(): File {
    // 时间戳
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss",Locale.CHINA).format(Date())
    // 图片文件名
    val imageFileName = "JPEG_" + timeStamp + "_"
    //外部存储中图片存储目录
    val storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    //创建图片保存文件
    val image = File.createTempFile(
            imageFileName, /* prefix */
            ".jpg", /* suffix */
            storageDir      /* directory */
    )

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.absolutePath
    return image
}
private fun takeFullPhoto() {
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    if (takePictureIntent.resolveActivity(packageManager) != null) {
    val imageFile = createImageFile()
    if (imageFile != null) {
        val photoURI = FileProvider.getUriForFile(this,
                "你的包名.fileprovider",
                imageFile)
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
    
    }
    }
}
  • Android7.0以后需要使用FileProvider
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="你的包名.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/image_file_path"/>
</provider>
  • 在Android的res目录中新建xml/image_file_path
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path
    name="images"
    path="Android/data/你的包名/files/Pictures"/>
</paths>

5.添加图片到相册

如果您将照片保存到getExternalFilesDir()提供的目录中,媒体扫描程序无法访问这些文件,因为它们是应用程序的私有文件。

private fun galleryAddPic() {
    MediaStore.Images.Media.insertImage(contentResolver, mImageFile.absolutePath, mImageFile.name, null);//图片插入到系统图库
    val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
    val f = File(mCurrentPhotoPath)
    val contentUri = Uri.fromFile(f)
    mediaScanIntent.data = contentUri
    this.sendBroadcast(mediaScanIntent)
}

6.解码缩放图像

private fun  setScalePicture() {
    // Get the dimensions of the View
    val targetW = imageView.width
    val targetH = imageView.height

    // Get the dimensions of the bitmap
   val bmOptions: BitmapFactory.Options =  BitmapFactory.Options()
    bmOptions.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(imageFile?.absolutePath, bmOptions);
    val photoW = bmOptions.outWidth
    val photoH = bmOptions.outHeight

    // Determine how much to scale down the image
    val scaleFactor = Math.min(photoW/targetW, photoH/targetH);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false
    bmOptions.inSampleSize = scaleFactor
    bmOptions.inPurgeable = true
    val bitmap = BitmapFactory.decodeFile(imageFile?.absolutePath, bmOptions);
    imageView.setImageBitmap(bitmap)
}