谷歌官方已经将startActivityForResult()标记为过时,并强烈推荐使用Activity Result API作为Androidx中activity和fragment获取返回值的方式,本文主要记录其用法。
1.引入库
implementation 'androidx.appcompat:appcompat:1.3.1'
2.API简介
在ComponentActivity和Fragment中,Activity Result API提供registerForActivityResult()方法
参数1:ActivityContract<I, O>类型
用于定义启动时输入的类型和结果的输出类型,具体有以下这些Contract:
StartActivityForResult:通用的Contract,不做任何转换,Intent作为输入,ActivityResult作为输出
RequestPermission:用于请求单个权限,输入为权限值,例如:
android.Manifest.Permission.CALL_PHONE,输出为布尔值,表示权限申请是否成功
TakePicturePreview:调用M e di a S to re.ACTION_IMAGE_CAPTURE拍照,返回值为Bitmap
TakePicture:调用MediaStore.ACTION_VIDEO_CAPTURE拍照,并将图片保存到给定的Uri地址,返回true表示保存成功
TakeVideo:调用MediaStore.ACTION_VIDEO_CAPTURE拍摄视频,保存到给定的Uri地址,但会一张缩略图
PickContact:从通讯录App获取联系人
GetContent:提示选择一条内容,返回一个通过COntentResolver#openInputStream(Uri)访问原生数据的Uri地址(content://形式)默认情况下,它增加了
Intent#CATEGORY_OPENABLE,返回可以表示流的内容
CreateDocument:提示用户选择一个文档,返回一个(file: or http: or content:)开头的Uri
OpenMultipleDocuments: 提示用户选择文档(可以选择多个),分别返回它们的Uri,以List的形式。
OpenDocumentTree: 提示用户选择一个目录,并返回用户选择的作为一个Uri返回,应用程序可以完全管理返回目录中的文档。
参数2:ActivityResultCallback<O>,这是一个单一方法接口(SMA),带有onActivityResult(),可以接受ActivityContract中定义的输出类型的对象
返回值:ActivityResultLauncher,用于启动activity
如果有多个Contract或者单独回调的activity结果调用,可以多次调用registerForActivityResult()创建多个ActivityResultLauncher
3.示例
示例1:activity跳转和申请单个权限
private lateinit var mBtn: Button
private lateinit var dailBtn: Button
//跳转activity并请求结果
private val mMainActivityLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data = result.data?.getStringExtra("result")
Toast.makeText(this, "Result from SecondActivity is $data", Toast.LENGTH_SHORT).show()
}
}
//申请单个权限
private val mPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
call()
} else {
Toast.makeText(this, "you denied the permission request!", Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mBtn = findViewById<Button>(R.id.btn).apply {
setOnClickListener {
val intent = Intent(this@MainActivity, SecondActivity::class.java)
mMainActivityLauncher.launch(intent)
}
}
dailBtn = findViewById<Button>(R.id.dailBtn).apply {
setOnClickListener {
if (ContextCompat.checkSelfPermission(this@MainActivity, android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
mPermissionLauncher.launch(android.Manifest.permission.CALL_PHONE)
} else {
call()
}
}
}
}
private fun call() {
val intent = Intent(Intent.ACTION_CALL)
intent.data = Uri.parse("tel:10000")
startActivity(intent)
}
示例2:google官方示例,输入一个字符串,返回一个Uri
val getContent = registerForActivityResult(GetContent()) { uri: Uri? ->
// Handle the returned Uri
}
override fun onCreate(savedInstanceState: Bundle?) {
// ...
val selectButton = findViewById<Button>(R.id.select_button)
selectButton.setOnClickListener {
// Pass in the mime type you'd like to allow the user to select
// as the input
getContent.launch("image/*")
}
}
4.在单独的类中接受activity的结果
ComponentActivity和Fragment类通过使用ActivityResultCaller接口来允许使用registerForActivityResult() API。但是可以通过直接使用ActivityResultRegistry在为实现ActivityResultCaller的单独类中接收结果。
例如,实现一个LifecycleObserver,用于处理Contract的注册和启动器的启动:
Google官方示例:
class MyLifecycleObserver(private val registry : ActivityResultRegistry)
: DefaultLifecycleObserver {
lateinit var getContent : ActivityResultLauncher<String>
override fun onCreate(owner: LifecycleOwner) {
getContent = registry.register("key", owner, GetContent()) { uri ->
// Handle the returned Uri
}
}
fun selectImage() {
getContent.launch("image/*")
}
}
class MyFragment : Fragment() {
lateinit var observer : MyLifecycleObserver
override fun onCreate(savedInstanceState: Bundle?) {
// ...
observer = MyLifecycleObserver(requireActivity().activityResultRegistry)
lifecycle.addObserver(observer)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val selectButton = view.findViewById<Button>(R.id.select_button)
selectButton.setOnClickListener {
// Open the activity to select an image
observer.selectImage()
}
}
}
5.创建自定义Contract:待补充