registerForActivityResult()是startActivityForResult()的替代,简化了数据回调的写法
//java写法
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback() {
@Override
public void onActivityResult(ActivityResult result) {
Intent data = result.getData();
int resultCode = result.getResultCode();
}
}).launch(new Intent(context,BActivity.class));
//kotlin写法
registerForActivityResult(ActivityResultContracts.StartActivityForResult()
) {
val data = it.data
val resultCode = it.resultCode
}.launch(Intent(context,BActivity::class.java))
//launch()方法,输入Intent,ActivityResultCallback:获取返回的数据,
//ActivityResultContracts.StartActivityForResult 是官方提供用来处理回调数据的ActivityResultContract类
//跳转到BActivity后,调用setResult()方法传递数据,这部分和以前一样
使用registerForActivityResult方法,可以简化许多相关操作,举几个例子
registerForActivityResult(ActivityResultContracts.PickContact()){
if(it != null){
val cursor = contentResolver.query(it, null, null, null, null)
cursor?.run {
if(cursor.moveToFirst()){
val name =
cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
LogUtils.e("联系人姓名:$name")
if(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)) == "1"){
//该联系人名下存在手机号,查询方法自行实现
}
}
}
}
}.launch(null)
//需要WRITE_EXTERNAL_STORAGE权限
val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "图片名称.jpg")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
}else{
FileProvider.getUriForFile(this,BuildConfig.authorities,File(externalCacheDir!!.absolutePath+"图片名称.jpg"))
}
registerForActivityResult(ActivityResultContracts.TakePicture()){
if(it)
Glide.with(this).load(uri).into(binding.imageView)
}.launch(uri)
//或者可以用更简单的方法
registerForActivityResult(ActivityResultContracts.TakePicturePreview()){
Glide.with(this).load(it).into(binding.imageView)
}.launch(null)
调用文件选择器,获取指定类型的文件,可在launch()方法里使用mimetype指定调用文件类型,这里以调用文本文档为例
registerForActivityResult(ActivityResultContracts.GetContent()){
}.launch("text/plain")
如果需要选择多种文件类型,可以使用OpenDocument
registerForActivityResult(ActivityResultContracts.OpenDocument()){
Glide.with(this).load(it).into(binding.imageView)
}.launch(arrayOf("image/*","text/plain"))
使用registerForActivityResult获取权限,也会变得非常简单
获取一个权限
registerForActivityResult(ActivityResultContracts.RequestPermission()){
if(it){
//用户同意了该权限
}else{
//用户拒绝了该权限
}
}.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
获取多个权限
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()){it->
//通过的权限
val grantedList = it.filterValues { it }.mapNotNull { it.key }
//是否所有权限都通过
val allGranted = grantedList.size == it.size
val list = (it - grantedList).map { it.key }
//未通过的权限
val deniedList = list.filter { ActivityCompat.shouldShowRequestPermissionRationale(this, it) }
//拒绝并且点了“不再询问”权限
val alwaysDeniedList = list - deniedList
}.launch(arrayOf("权限1","权限2","权限3"))
ActivityResultContract 官方提供的,通过输入类型I构建意图并将回调数据转换成输入类型O的契约类,官方总共给我们提供了14个ActivityResultContract实现类,通过ActivityResultContracts构建,可以非常轻松地调用文件,联系人,敏感权限等等,另外,我们也可以实现自己的ActivityResultContract来简化意图操作,这里写一个裁剪图片的ActivityResultContract为例
class ResultCropImage: ActivityResultContract(){
var outUri:Uri? = null
//构建意图
override fun createIntent(context: Context, input: CropImageResult): Intent {
//把CropImageResult转换成裁剪图片的意图
val intent = Intent("com.android.camera.action.CROP")
val mimeType = context.contentResolver.getType(input.uri)
val imageName:String = "${System.currentTimeMillis()}.${MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)}"
outUri = Uri.fromFile(File(context.externalCacheDir!!.absolutePath,imageName))
context.grantUriPermission(
context.getPackageName(),
outUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.putExtra("noFaceDetection", true) //去除默认的人脸识别,否则和剪裁匡重叠
intent.setDataAndType(input.uri, mimeType)
intent.putExtra("crop", "true") // crop=true 有这句才能出来最后的裁剪页面.
intent.putExtra("output", outUri)
intent.putExtra("outputFormat", "JPEG") // 返回格式
intent.putExtra("return-data", false)
if (input.outputX != 0 && input.outputY != 0) {
intent.putExtra("outputX", input.outputX)
intent.putExtra("outputY", input.outputY)
}
if(input.aspectX != 0 && input.aspectY != 0){
if(input.aspectY == input.aspectX && Build.MANUFACTURER == "HUAWEI"){
intent.putExtra("aspectX", 9999)
intent.putExtra("aspectY", 9998)
}else{
intent.putExtra("aspectX", input.aspectX)
intent.putExtra("aspectY", input.aspectY)
}
}
return intent
}
//接收意图并处理数据
override fun parseResult(resultCode: Int, intent: Intent?): Uri {
if(outUri != null)
return outUri!!
else
return Uri.parse("")
}
}
/**
* uri:需要裁剪的图片
* aspect:长宽比例
* output:图片输出长宽
*/
class CropImageResult(val uri: Uri,val aspectX:Int = 0,val aspectY:Int = 0, @IntRange(from = 0 ,to = 1080)val outputX:Int = 0, @IntRange(from = 0 ,to = 1080)val outputY:Int = 0)
使用:
//调用文件选择器获取图片
registerForActivityResult(ActivityResultContracts.GetContent()){
crop(it)
}.launch("image/*")
//裁剪图片
private fun crop(uri: Uri?) {
registerForActivityResult(ResultCropImage()){
Glide.with(this).load(it).into(binding.imageView)
}.launch(CropImageResult(uri!!))
}