在create-expo-module模块中处理Android权限回调的实现方案咨询
处理Expo自定义模块的Android权限回调
要解决Android权限请求后的回调问题,尤其是startActivityForResult的结果处理,你需要让Expo模块实现ActivityEventListener接口,通过Expo上下文注册监听器,并结合Promise将结果传递给JS端。以下是具体实现方案:
1. 让Module实现ActivityEventListener接口
在Kotlin模块类中实现该接口,监听Activity的结果事件,同时保存Promise用于回调JS端:
import expo.modules.core.interfaces.ActivityEventListener import android.app.Activity import android.content.Intent import expo.modules.core.Promise class MyExpoModule : Module(), ActivityEventListener { // 存储权限请求的Promise,用于回调结果 private var permissionPromise: Promise? = null override fun definition(): ModuleDefinitionData { return ModuleDefinition { Name("MyExpoModule") Function("requestPermissions") { promise: Promise -> permissionPromise = promise // 传递module实例给PermissionManager,用于回调结果 MyPermissionManager.requestPermissions(appContext.activityProvider?.currentActivity, this) } } } override fun onCreate(activity: Activity) { // 注册Activity事件监听器 appContext.addActivityEventListener(this) } override fun onDestroy(activity: Activity) { // 移除监听器避免内存泄漏 appContext.removeActivityEventListener(this) } override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) { // 处理通知策略权限的回调(对应requestCode=1000) if (requestCode == 1000) { val isGranted = (activity.getSystemService(android.app.NotificationManager::class.java) .isNotificationPolicyAccessGranted) permissionPromise?.let { promise -> promise.resolve(mapOf("status" to if (isGranted) "granted" else "denied")) permissionPromise = null } } } override fun onNewIntent(intent: Intent) { // 无需处理可留空 } // 供PermissionManager调用,传递33+版本的权限结果 fun onPermissionResult(granted: Boolean) { permissionPromise?.let { promise -> promise.resolve(mapOf("status" to if (granted) "granted" else "denied")) permissionPromise = null } } }
2. 修改PermissionManager,传递结果到Module
调整Java的MyPermissionManager,将权限结果传递给Module实例:
import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Build; import android.provider.Settings; import android.app.NotificationManager; import android.content.pm.PackageManager; import androidx.core.content.ContextCompat; import expo.modules.core.interfaces.PermissionAwareActivity; import expo.modules.core.interfaces.PermissionListener; public class MyPermissionManager { public static void requestPermissions(Activity activity, MyExpoModule module) { if (Build.VERSION.SDK_INT >= 33) { if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { PermissionAwareActivity permissionAwareActivity = (PermissionAwareActivity) activity; if (permissionAwareActivity != null) { permissionAwareActivity.requestPermissions(new String[]{android.Manifest.permission.POST_NOTIFICATIONS}, 101, new PermissionListener() { @Override public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { boolean isGranted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; module.onPermissionResult(isGranted); return false; } }); } } else { // 已授权,直接返回结果 module.onPermissionResult(true); } } else if (Build.VERSION.SDK_INT >= 30) { NotificationManager notificationManager = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE); // 修正原逻辑:未授权时跳转设置页面 if (!notificationManager.isNotificationPolicyAccessGranted()) { Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); activity.startActivityForResult(intent, 1000); } else { // 已授权,直接返回结果 module.onPermissionResult(true); } } } }
3. JS端调用并处理结果
在JS代码中通过Promise接收权限请求结果:
import { NativeModules } from 'react-native'; const { MyExpoModule } = NativeModules; async function requestAppPermissions() { try { const result = await MyExpoModule.requestPermissions(); console.log('权限请求结果:', result.status); // 根据结果执行后续逻辑 } catch (error) { console.error('权限请求失败:', error); } }
核心说明
- ActivityEventListener:Expo模块通过该接口监听Activity的结果事件,是处理
startActivityForResult回调的标准方式。 - Promise通信:通过保存Promise对象,在权限结果返回时调用
resolve将结果传递给JS端,这是Expo模块与JS层通信的常规模式。 - 逻辑修正:原代码中Android 30+的权限判断逻辑存在反向错误,已修正为未授权时跳转设置页面。
内容的提问来源于stack exchange,提问作者matusalem
相关产品推荐
相关产品推荐

