android - 在不使用 startActivityForResult 从图库中选择图像时,如何获得真实路径?
问题描述
正如startActivityForResult
已被弃用的那样,我宁愿不使用它来从图库中获取所选图像的绝对路径。
因此,我已经尝试不使用它作为下面的代码,但是它不起作用。我究竟做错了什么?
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
android:gravity="center_horizontal"
tools:context=".MainActivity">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/img_camera"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
android:src="@drawable/camera"/>
<TextView
android:id="@+id/txt_path"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Path"
android:layout_marginTop="30dp"/>
</LinearLayout>
主要活动.kt
package com.gearsrun.choosephotoapplication
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.graphics.drawable.toBitmap
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.gearsrun.choosephotoapplication.databinding.ActivityMainBinding
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
import java.util.*
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
private var mImagePath = ""
private lateinit var activityResultLauncher:ActivityResultLauncher<Intent>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val getImage = registerForActivityResult(
ActivityResultContracts.GetContent(),
ActivityResultCallback {
Glide.with(this)
.load(it)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.listener(object : RequestListener<Drawable>{
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
Log.e("TAG", "Error loading image", e)
return false // important to return false so the error placeholder can be placed
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
val bitmap: Bitmap = (resource?.toBitmap() ?: null) as Bitmap
mImagePath = saveImageToInternalStorage(bitmap)
binding.txtPath.text = mImagePath
return false
}
})
}
)
binding.imgCamera.setOnClickListener {
getImage.launch("image/*")
}
}
private fun saveImageToInternalStorage(bitmap: Bitmap): String {
val wrapper = ContextWrapper(applicationContext)
var file = wrapper.getDir(IMAGE_DIRECTORY, Context.MODE_PRIVATE)
file = File(file,"${UUID.randomUUID()}.jpg")
try{
val stream :OutputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream)
stream.flush()
stream.close()
}catch (e:IOException){
e.printStackTrace()
}
return file.absolutePath
}
companion object {
private const val IMAGE_DIRECTORY = "GearsRunImages"
}
}
解决方案
我相信问题发生在Glide
.
Glide 用于加载图像,我假设imgCamera
用于预览加载的图像。因此,需要into(binding.imgCamera)
在您的Glide
实现中添加。
因此,在加载图像后,onResourceReady()
将触发并且您的逻辑可能会在那里运行。
我认为,getImage
如下代码中的更新可能有效
val getImage = registerForActivityResult(
ActivityResultContracts.GetContent(),
ActivityResultCallback {
Glide.with(this)
.load(it)
.centerCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.listener(object : RequestListener<Drawable>{
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
Log.e("TAG", "Error loading image", e)
return false // important to return false so the error placeholder can be placed
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
val bitmap: Bitmap = (resource?.toBitmap() ?: null) as Bitmap
mImagePath = saveImageToInternalStorage(bitmap)
binding.txtPath.text = mImagePath
return false
}
})
.into(binding.imgCamera)
}
)
推荐阅读
- haskell - 为什么我可以直接在 REPL 中从 typeclass 实例调用函数(比如从 Ord 进行比较)?
- python - 在 django 中使用两个匹配的外键时出错
- python - Python turtle 模块导致 OS X 崩溃
- macos - 使用 Applescript 在 Powerpoint 幻灯片中对齐照片
- java - SSL 连接问题 - 未发送所需的 SSL 证书
- hybris - 自定义必填字段的 Excel 导入不起作用 [Hybris 6.7.0]
- google-cloud-stackdriver - Stackdriver 监控的 CPU 类型和 CPU 利用率指标
- r - 使用summary.table时如何修复'object'必须从类“table”继承?
- php - 子域路由覆盖并运行 web.php 中的最后一个子域
- excel - 仅当行包含一个值时,将特定行复制到另一个工作表