You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 04:21:31