android 图片选择/拍照,使用总结

352 阅读1分钟
  1. 封装代码
class PictureSelectHelper(
    private val context: FragmentActivity,
    private val success: (imgPath: String?) -> Unit = {}
) {
    companion object {
        const val SELECT_CAMERA = 0
        const val SELECT_ALBUM = 1
        const val DEFAULT_PERMISSION_REQUEST_CODE = 100
    }

    private val registry = context.activityResultRegistry
    private var mImgPath = ""

    fun start() {
        showAddProfileImage()
    }

    private fun showAddProfileImage() {
        val items = arrayOf<CharSequence>(
            "Camera",
            "Gallery"
        )
        val builder = MaterialAlertDialogBuilder(context, R.style.AlertDialogStyle)
        builder.setTitle("")
        builder.setItems(items) { dialog, which ->
            dialog.dismiss()
            val i: Intent?
            when (which) {
                SELECT_ALBUM -> {
                    i = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
                    startForResultAlbum.launch(i)
                }
                SELECT_CAMERA -> {
                    i = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                    val photoURI: Uri? = getFileUri()
                    i.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                    startForResultCamera.launch(i)
                }
            }
        }
        val dlg = builder.create()
        dlg.show()
    }

    private fun mergeCameraData(result: ActivityResult) {
        if (result.resultCode == Activity.RESULT_OK) {
            val imgPath: String? = if (result.data == null || result.data!!.data == null) {
                mImgPath
            } else {
                val selImgUri: Uri? = result.data!!.data
                getImageNameToUri(selImgUri!!)
            }
            success(imgPath)
        }
    }

    private fun mergeALBUMData(result: ActivityResult) {
        if (result.resultCode == Activity.RESULT_OK) {
            result.data?.let {
                it.data?.let { it2 ->
                    val imgPath: String? = getImageNameToUri(it2)
                    success(imgPath)
                }
            }
        }
    }

    private fun getFileUri(): Uri? {
        val dir = File(context.filesDir, "img")
        if (!dir.exists()) {
            dir.mkdirs()
        }
        val file = File(dir, System.currentTimeMillis().toString() + ".png")
        mImgPath = file.absolutePath
        return FileProvider.getUriForFile(
            context,
            context.applicationContext.packageName.toString() + ".fileprovider",
            file
        )
    }

    private fun getImageNameToUri(selImgUri: Uri): String? {
        val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
        val imgCursor: Cursor =
            context.contentResolver
                ?.query(selImgUri, filePathColumn, null, null, null)!!
        val columnIndex =
            imgCursor.getColumnIndex(MediaStore.Images.Media.DATA)
        imgCursor.moveToFirst()
        val imgPath = imgCursor.getString(columnIndex)
        imgCursor.close()
        return imgPath
    }

    private var startForResultAlbum: ActivityResultLauncher<Intent> = registry.register(
        "key1",
        ActivityResultContracts.StartActivityForResult()
    ) { result: ActivityResult ->
        mergeALBUMData(result)
    }
    private var startForResultCamera: ActivityResultLauncher<Intent> = registry.register(
        "key2",
        ActivityResultContracts.StartActivityForResult()
    ) { result: ActivityResult ->
        mergeCameraData(result)
    }
}
  1. manifest文件下,需要加上配置
<!-- Camera File storage -->
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
  1. 新建 xml/file_paths 文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external"
        path="." />
    <external-files-path
        name="external_files"
        path="." />
    <cache-path
        name="cache"
        path="." />
    <external-cache-path
        name="external_cache"
        path="." />
    <files-path
        name="files"
        path="." />
</paths>
  1. 使用
//声明全局变量
private val pictureSelectHelper: PictureSelectHelper by lazy {
    PictureSelectHelper(this) {
        Log.d("imgPath", "$it")
        it?.let { it1 -> binding.img.load(it1) }
    }
}

合适的地方,调用,记得先申请权限

pictureSelectHelper.start()

image.png