用易语言做刷网站注册软件wordpress中文视频插件
用易语言做刷网站注册软件,wordpress中文视频插件,wordpress图片播放,设计网单项目场景#xff1a;
为项目封装可一键调用的权限授权功能实现方案
一、权限常量统一管理
先定义一个权限常量类#xff0c;把权限字符串统一管理#xff0c;同时可以进行权限的版本兼容。#xff08;例如#xff1a;Android 13 存储权限分区#xff08;Android 13 把存储…项目场景为项目封装可一键调用的权限授权功能实现方案一、权限常量统一管理先定义一个权限常量类把权限字符串统一管理同时可以进行权限的版本兼容。例如Android 13 存储权限分区Android 13 把存储权限拆分为图片 / 视频 / 音频权限旧版存储权限失效/** * 权限常量管理类 */objectPermissionConstant{// 相机权限constvalCAMERAandroid.Manifest.permission.CAMERA// 录音/语音权限constvalRECORD_AUDIOandroid.Manifest.permission.RECORD_AUDIO// 定位权限 精确定位粗略定位建议两个都申请constvalACCESS_FINE_LOCATIONandroid.Manifest.permission.ACCESS_FINE_LOCATIONconstvalACCESS_COARSE_LOCATIONandroid.Manifest.permission.ACCESS_COARSE_LOCATIONvalLOCATION_PERMISSIONSarrayOf(ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION)// 存储权限 兼容 Android 13 / Android 12及以下valSTORAGE_PERMISSIONSif(android.os.Build.VERSION.SDK_INTandroid.os.Build.VERSION_CODES.TIRAMISU){// Android 13 分区权限图片视频音频按需取舍arrayOf(android.Manifest.permission.READ_MEDIA_IMAGES,android.Manifest.permission.READ_MEDIA_VIDEO,android.Manifest.permission.READ_MEDIA_AUDIO)}else{// Android 12及以下 旧存储权限arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE,android.Manifest.permission.WRITE_EXTERNAL_STORAGE)}// 一键申请全部权限定位录音相机存储valALL_PERMISSIONSLOCATION_PERMISSIONSRECORD_AUDIOCAMERASTORAGE_PERMISSIONS}二、封装通用权限工具类【工具类要求】1.无需Context传参、无Activity耦合Compose中直接调用2.支持「单个权限申请」「多个权限批量申请」3.自带权限是否已授予的判断逻辑避免重复申请4.回调返回权限申请结果未授予的权限列表方便自行书写业务逻辑5.全局通用/** * Compose 通用权限请求工具类 */objectComposePermissionManager{/** * 单个权限申请 * param permission 单个权限字符串如PermissionConstant.CAMERA * param onResult 权限申请结果回调 true授予 false拒绝 */ComposablefunrequestSinglePermission(permission:String,onResult:(Boolean)-Unit){// 注册单个权限申请的LaunchervalpermissionLauncherrememberLauncherForActivityResult(contractActivityResultContracts.RequestPermission(),onResultonResult)// 检查权限是否已授予未授予则申请remember(permission){valisGrantedContextCompat.checkSelfPermission(getAppContext(),permission)android.content.pm.PackageManager.PERMISSION_GRANTEDif(!isGranted){permissionLauncher.launch(permission)}else{onResult(true)}}}/** * 多个权限批量申请 【重点你的需求核心用法】 * param permissions 权限数组如PermissionConstant.ALL_PERMISSIONS * param onResult 批量权限申请结果回调 * grantedAll是否全部授予 * deniedPermissions拒绝的权限列表为空则全部授予 */ComposablefunrequestMultiplePermissions(permissions:ArrayString,onResult:(grantedAll:Boolean,deniedPermissions:ListString)-Unit){// 注册多个权限申请的LaunchervalmultiplePermissionLauncherrememberLauncherForActivityResult(contractActivityResultContracts.RequestMultiplePermissions(),onResult{permissionMap-// 筛选出拒绝的权限列表valdeniedListpermissionMap.filter{!it.value}.keys.toList()// 回调结果是否全部授予 拒绝的权限onResult(deniedList.isEmpty(),deniedList)})// 检查权限未授予的才申请remember(permissions){// 筛选出未授予的权限valneedRequestPermissionspermissions.filter{ContextCompat.checkSelfPermission(getAppContext(),it)!android.content.pm.PackageManager.PERMISSION_GRANTED}.toTypedArray()if(needRequestPermissions.isNotEmpty()){multiplePermissionLauncher.launch(needRequestPermissions)}else{// 所有权限都已授予onResult(true,emptyList())}}}// 获取全局ApplicationContext无内存泄漏风险privatefungetAppContext():Context{returnandroidx.multidex.MultiDexApplication.getContext()}}三、页面调用完成前面步骤后实现业务逻辑页面的实际调用。以相机授权为例ComposablefunTestPage(){// 定义状态通过状态控制来实现主动调起授权操作varneedRequestCamerabyremember{mutableStateOf(false)}// 状态驱动执行你的Composable权限申请函数if(needRequestCamera){requestCameraPermission{isGranted-if(isGranted){//授权成功}else{//授权失败}}}Column(modifierModifier.fillMaxWidth().background(Color.White).padding(16.dp),horizontalAlignmentAlignment.CenterHorizontally){Button(onClick{needRequestCameratrue}){Text(text申请相机权限)}}}四、AndroidManifest.xml 声明权限必写不写申请无效manifest...!-- 相机权限 --uses-permissionandroid:nameandroid.permission.CAMERA/!-- 录音权限 --uses-permissionandroid:nameandroid.permission.RECORD_AUDIO/!-- 定位权限 --uses-permissionandroid:nameandroid.permission.ACCESS_FINE_LOCATION/uses-permissionandroid:nameandroid.permission.ACCESS_COARSE_LOCATION/!-- Android 12及以下 存储权限 --uses-permissionandroid:nameandroid.permission.READ_EXTERNAL_STORAGE/uses-permissionandroid:nameandroid.permission.WRITE_EXTERNAL_STORAGE/!-- Android 13 分区存储权限 --uses-permissionandroid:nameandroid.permission.READ_MEDIA_IMAGES/uses-permissionandroid:nameandroid.permission.READ_MEDIA_VIDEO/uses-permissionandroid:nameandroid.permission.READ_MEDIA_AUDIO/!-- 可选声明应用需要使用相机/定位硬件 --uses-featureandroid:nameandroid.hardware.cameraandroid:requiredfalse/uses-featureandroid:nameandroid.hardware.location.gpsandroid:requiredfalse/application....../application/manifest可能遇到的问题Composable invocations can only happen from the context of a Composable function解决方案按照【步骤三】中的方式使用状态调用的方式报错的本质含义被 Composable 注解标记的组合函数只能在「有Composable上下文的代码里调用」绝对不能在「无Composable注解的普通函数 / 普通代码块」中直接调用 Compose 组合函数。报错的原因Compose 的核心运行机制是所有带 Composable 注解的函数都会被编译器注入「重组上下文、生命周期管理、状态订阅」等核心逻辑这些逻辑需要一个连续的 Composable 上下文链路才能生效。· 允许调用Composable 函数A 内部 → 调用 Composable 函数B 上下文链路连续· 禁止调用普通函数C 内部 → 调用 Composable 函数B 上下文链路中断无 Compose 运行环境示例1.在「按钮 onClick 普通 lambda」中调用 Composable 函数ComposablefunPermissionPage(){Button(onClick{// onClick 是「普通lambda回调」无Composable上下文// requestCameraPermission是Composable函数在这里调用必报错requestCameraPermission{isGranted-if(isGranted){println(相机权限申请成功)}}}){Text(申请相机权限)}}2.在「普通 kotlin 函数 / 工具类普通函数」中调用 Composable 函数// 无Composable注解的普通函数funinitPermission(){// 在这里调用你的Compose权限申请函数必报该错误requestAllPermissions{_,_-}}// 自定义的普通监听回调funsetPermissionListener(){vallistenerobject:PermissionCallback{overridefunonRequest(){requestCameraPermission{}// 普通接口的普通方法无Composable上下文}}}3.在 if/for/while 等代码块中脱离 Composable 作用域调用ComposablefunTestPage(){valisShowtruevallistlistOf(1,2,3)if(isShow){// 正确if块在Composable函数内上下文保留Text(测试)}// 错误把Composable函数写在普通代码块的嵌套逻辑中且赋值给变量valtextComposeif(isShow){Text(错误示范)// 直接赋值Composable函数无上下文}}4.在协程 launch 中直接调用 Composable 函数ComposablefunCoroutineError(){valscoperememberCoroutineScope()Button(onClick{scope.launch{// 错误协程是普通挂起函数无Composable上下文requestCameraPermission{}}}){Text(协程申请权限)}}扩展提示快捷权限申请函数方便页面中快捷调用/** * 快捷权限申请函数 - 与页面解耦一键调用 */// 相机权限ComposablefunrequestCameraPermission(onResult:(Boolean)-Unit){ComposePermissionManager.requestSinglePermission(PermissionConstant.CAMERA,onResult)}// 录音权限ComposablefunrequestRecordPermission(onResult:(Boolean)-Unit){ComposePermissionManager.requestSinglePermission(PermissionConstant.RECORD_AUDIO,onResult)}// 定位权限批量ComposablefunrequestLocationPermission(onResult:(Boolean,ListString)-Unit){ComposePermissionManager.requestMultiplePermissions(PermissionConstant.LOCATION_PERMISSIONS,onResult)}// 存储权限批量兼容ComposablefunrequestStoragePermission(onResult:(Boolean,ListString)-Unit){ComposePermissionManager.requestMultiplePermissions(PermissionConstant.STORAGE_PERMISSIONS,onResult)}// 全部权限定位录音相机存储ComposablefunrequestAllPermissions(onResult:(Boolean,ListString)-Unit){ComposePermissionManager.requestMultiplePermissions(PermissionConstant.ALL_PERMISSIONS,onResult)}权限拒绝后引导用户到【应用设置页】开启权限/** * 跳转到应用的系统设置页面引导用户手动开启权限 */fungoToAppSetting(context:Context){valintentIntent().apply{if(Build.VERSION.SDK_INTBuild.VERSION_CODES.P){actionSettings.ACTION_APPLICATION_DETAILS_SETTINGSdataUri.fromParts(package,context.packageName,null)}else{actionSettings.ACTION_APPLICATION_DETAILS_SETTINGSdataUri.parse(package:$context.packageName)}flagsIntent.FLAG_ACTIVITY_NEW_TASK}context.startActivity(intent)}