背景
startActivityForResult()方法过期了!!!
原因是onActivityResult()方法中代码逻辑复杂,混乱。
研究
Android推出了新的API,Activity Results API。
学习文档:https://mp.weixin.qq.com/s/lWayiBS4T4EHcsUIgnhJzA
Demo
- ActivityResultContract: 协议,它定义了如何传递数据和如何处理返回的数据。ActivityResultContract是一个抽象类,你需要继承它来创建自己的协议,每个 ActivityResultContract 都需要定义输入和输出类,如果您不需要任何输入,可使用 Void(在 Kotlin 中,使用 Void? 或 Unit)作为输入类型。
- ActivityResultLauncher: 启动器,调用ActivityResultLauncher的launch方法来启动页面跳转,作用相当于原来的startActivity()
//选择本地照片例子void selectImage() {String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE};if (hasPermission(permissions)) {launcher.launch(1);} else {initPermissions(permissions, new PermissionResult() {@Overridepublic void onSuccess() {launcher.launch(1);}@Overridepublic void onFailure() {toast("请授予读写权限");}@Overridepublic void onFailureWithNeverAsk() {toast("请到应用设置中授予读写权限");}});}}ActivityResultLauncher<Integer> launcher = registerForActivityResult(new ResultContract(), new ActivityResultCallback<Bitmap>() {@Overridepublic void onActivityResult(Bitmap result) {binding.image.setImageBitmap(result);}});//Integer是输入类型,Bitmap是输出类型class ResultContract extends ActivityResultContract<Integer, Bitmap> {@NonNull@Overridepublic Intent createIntent(@NonNull Context context, Integer input) {Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);intent.addCategory(Intent.CATEGORY_OPENABLE);intent.setType("image/*");return intent;}@Overridepublic Bitmap parseResult(int resultCode, @Nullable Intent intent) {if (resultCode == RESULT_OK) {if (intent != null) {Uri uri = intent.getData();if (uri != null) {try {ParcelFileDescriptor descriptor = getContentResolver().openFileDescriptor(uri, "r");if (descriptor != null) {Bitmap bitmap = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor());return bitmap;}} catch (FileNotFoundException e) {e.printStackTrace();}}}}return null;}}
对于每次定义Contract的问题!!!
官方定义的Contract
- StartActivityForResult: 通用的Contract,不做任何转换,Intent作为输入,ActivityResult作为输出,这也是最常用的一个协定。
- RequestMultiplePermissions:用于请求一组权限
- RequestPermission: 用于请求单个权限
- TakePicturePreview: 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,返回值为Bitmap图片
- TakePicture: 调用MediaStore.ACTION_IMAGE_CAPTURE拍照,并将图片保存到给定的Uri地址,返回true表示保存成功。
- TakeVideo: 调用MediaStore.ACTION_VIDEO_CAPTURE 拍摄视频,保存到给定的Uri地址,返回一张缩略图。
- PickContact: 从通讯录APP获取联系人
- GetContent: 提示用选择一条内容,返回一个通过ContentResolver#openInputStream(Uri)访问原生数据的Uri地址(content://形式) 。默认情况下,它增加了Intent#CATEGORY_OPENABLE, 返回可以表示流的内容。
- CreateDocument: 提示用户选择一个文档,返回一个(file:/http:/content:)开头的Uri。
- OpenMultipleDocuments: 提示用户选择文档(可以选择多个),分别返回它们的Uri,以List的形式。
- OpenDocumentTree: 提示用户选择一个目录,并返回用户选择的作为一个Uri返回,应用程序可以完全管理返回目录中的文档。
优点
不用第三方权限框架了
request_permission.setOnClickListener {requestPermission.launch(permission.BLUETOOTH)}request_multiple_permission.setOnClickListener {requestMultiplePermissions.launch(arrayOf(permission.BLUETOOTH,permission.NFC,permission.ACCESS_FINE_LOCATION))}// 请求单个权限private val requestPermission =registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->// Do something if permission grantedif (isGranted) toast("Permission is granted")else toast("Permission is denied")}// 请求一组权限private val requestMultiplePermissions =registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions : Map<String, Boolean> ->// Do something if some permissions granted or deniedpermissions.entries.forEach {// Do checking here}}
