1. 核心代码
打开系统相册功能,本代码使用两种方式打开本地相册,startActivityForResult 已经废弃,可以使用新的方式。
kotlin
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
xml
<?xml version="1.0" encoding="utf-8"?>
<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>