• Android Kotlin 打开相册选择图片(多选)


    1. 核心代码

    打开系统相册功能,本代码使用两种方式打开本地相册,startActivityForResult 已经废弃,可以使用新的方式。

    package com.example.facedetectordemo
    
    import android.content.pm.PackageManager
    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import android.util.Log
    import android.view.View
    import android.widget.TextView
    import androidx.activity.result.contract.ActivityResultContracts
    import androidx.core.app.ActivityCompat
    import androidx.core.content.ContextCompat
    import com.example.facedetectordemo.databinding.ActivityMainBinding
    import com.example.facedetectordemo.entity.FaceInfo
    import android.Manifest;
    import android.annotation.SuppressLint
    import android.annotation.TargetApi
    import android.app.Activity
    import android.content.ContentUris
    import android.content.Intent
    import android.graphics.BitmapFactory
    import android.net.Uri
    import android.os.Build
    import android.provider.DocumentsContract
    import android.provider.MediaStore
    import com.google.android.material.snackbar.Snackbar
    
    class MainActivity : AppCompatActivity() {
    
        private lateinit var binding: ActivityMainBinding
        private val CHOOSE_PHOTO = 1
    
        private val requestPermissionLauncher =
            registerForActivityResult(
                ActivityResultContracts.RequestPermission()
            ) { isGranted: Boolean ->
                if (isGranted) {
                    Log.i("Permission: ", "Granted")
                } else {
                    Log.i("Permission: ", "Denied")
                }
            }
    
        private val launcherActivity = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()) {
            val data = it.data
            if (it.resultCode == Activity.RESULT_OK) {
                    // 判断手机系统版本号
                    if (Build.VERSION.SDK_INT >= 19) {
                        // 4.4及以上系统使用这个方法处理图片
                        if (data != null) {
                            if(data.clipData != null) {
                                handleImageOnKitKat(data.clipData!!.getItemAt(0).uri)
                            } else if(data.data != null) {
                                handleImageOnKitKat(data.data!!)
                            }
    
                        }
                    }
    
            }
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            // Example of a call to a native method
            binding.openGallery.setOnClickListener{
                val intent = Intent("android.intent.action.GET_CONTENT")
                intent.type = "image/*" // */
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
                //startActivityForResult(intent, CHOOSE_PHOTO) // 打开相册, 废弃API
                launcherActivity.launch(intent)
            }
    
            val infos = getFaceInfoList()
            Log.d("zhouyong", "onCreate: size " + infos.size)
    
            requestPermission();
        }
    
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            when (requestCode) {
                CHOOSE_PHOTO -> if (resultCode == Activity.RESULT_OK) {
                    // 判断手机系统版本号
                    if (Build.VERSION.SDK_INT >= 19) {
                        // 4.4及以上系统使用这个方法处理图片
                        if (data != null) {
                            if(data.clipData != null) {
                                handleImageOnKitKat(data.clipData!!.getItemAt(0).uri)
                            } else if(data.data != null) {
                                handleImageOnKitKat(data.data!!)
                            }
    
                        }
                    } else {
                    }
                }
                else -> {
                }
            }
        }
    
        @TargetApi(19)
        private fun handleImageOnKitKat(uri: Uri) {
            var imagePath: String? = null
            //val uri = data.data
            Log.d("TAG", "handleImageOnKitKat: uri is $uri")
            if (DocumentsContract.isDocumentUri(this, uri)) {
                // 如果是document类型的Uri,则通过document id处理
                val docId = DocumentsContract.getDocumentId(uri)
                if ("com.android.providers.media.documents" == uri!!.authority) {
                    val id = docId.split(":".toRegex()).toTypedArray()[1] // 解析出数字格式的id
                    val selection = MediaStore.Images.Media._ID + "=" + id
                    imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection)
                } else if ("com.android.providers.downloads.documents" == uri.authority) {
                    val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(docId))
                    imagePath = getImagePath(contentUri, null)
                }
            } else if ("content".equals(uri!!.scheme, ignoreCase = true)) {
                // 如果是content类型的Uri,则使用普通方式处理
                imagePath = getImagePath(uri, null)
            } else if ("file".equals(uri.scheme, ignoreCase = true)) {
                // 如果是file类型的Uri,直接获取图片路径即可
                imagePath = uri.path
            }
            displayImage(imagePath) // 根据图片路径显示图片
        }
    
        @SuppressLint("Range")
        private fun getImagePath(uri: Uri?, selection: String?): String? {
            var path: String? = null
            // 通过Uri和selection来获取真实的图片路径
            val cursor = contentResolver.query(uri!!, null, selection, null, null)
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA))
                }
                cursor.close()
            }
            return path
        }
    
        private fun displayImage(imagePath: String?) {
            if (imagePath != null) {
                val bitmap = BitmapFactory.decodeFile(imagePath)
                binding.imageView.setImageBitmap(bitmap)
            } else {
                //Toast.makeText(this, "failed to get image", Toast.LENGTH_SHORT).show()
            }
        }
    
    
        fun requestPermission() {
            when {
                ContextCompat.checkSelfPermission(
                    this,
                    Manifest.permission.READ_EXTERNAL_STORAGE
                ) == PackageManager.PERMISSION_GRANTED -> {
                }
    
                ActivityCompat.shouldShowRequestPermissionRationale(
                    this,
                    Manifest.permission.CAMERA
                ) -> {
                    requestPermissionLauncher.launch(
                        Manifest.permission.CAMERA
                    )
                    requestPermissionLauncher.launch(
                        Manifest.permission.READ_EXTERNAL_STORAGE
                    )
                    requestPermissionLauncher.launch(
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                    )
                }
    
                else -> {
                    requestPermissionLauncher.launch(
                        Manifest.permission.CAMERA
                    )
                    requestPermissionLauncher.launch(
                        Manifest.permission.READ_EXTERNAL_STORAGE
                    )
                    requestPermissionLauncher.launch(
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                    )
                }
            }
        }
    
        fun View.showSnackbar(
            view: View,
            msg: String,
            length: Int,
            actionMessage: CharSequence?,
            action: (View) -> Unit
        ) {
            val snackbar = Snackbar.make(view, msg, length)
            if (actionMessage != null) {
                snackbar.setAction(actionMessage) {
                    action(this)
                }.show()
            } else {
                snackbar.show()
            }
        }
    
        /**
         * A native method that is implemented by the 'facedetectordemo' native library,
         * which is packaged with this application.
         */
        external fun stringFromJNI(): String
    
        external fun getFaceInfoList(): Array<FaceInfo>
    
        companion object {
            // Used to load the 'facedetectordemo' library on application startup.
            init {
                System.loadLibrary("facedetectordemo")
            }
        }
    }
    

    2. main_layout.xml

    
    <androidx.constraintlayout.widget.ConstraintLayout 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"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/openGallery"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="212dp"
            android:text="打开相册"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            app:layout_constraintVertical_bias="1.0" />
    
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_marginTop="96dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:srcCompat="@tools:sample/avatars" />
    
    androidx.constraintlayout.widget.ConstraintLayout>
    
  • 相关阅读:
    Android性能优化系列-腾讯matrix-IO监控-IOCanaryPlugin源码分析
    vue快速入门(四十二)ref与$refs的使用
    Java定时器(多线程的知识)----会一种就好,一看就懂
    Netty学习——实战篇5 Netty 心跳监测/WebSocket长连接编程 备份
    基于JavaWeb+SSM+社区居家养老服务平台—颐养者端微信小程序系统的设计和实现
    代码随想录62——额外题目【数组】:189轮转数组、724寻找数组的中心下标、922按奇偶排序数组II
    Android网络请求(3) 网络请求框架OkHttp
    24、Flink 的table api与sql之Catalogs(java api操作分区与函数、表)-4
    【JQuery】JQuery入门——知识点讲解(一)
    【autodl/linux配环境心得:conda/本地配cuda,cudnn及pytorch心得】
  • 原文地址:https://blog.csdn.net/ZHOUYONGXYZ/article/details/139370248