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

Android生产构建中Native Module 'BoundingBox'找不到的问题排查

Android生产构建找不到Native Module问题排查

问题描述

开发首个支持iOS和Android的Expo Native Module,iOS端运行正常,Android开发构建无问题,但生产构建打包后应用崩溃。通过adb logcat捕获到报错:

2024-12-08 20:49:20.531 29294-29339 ReactNativeJS           com.identafly.preview                E  Error: Cannot find native module 'BoundingBox', js engine: hermes
2024-12-08 20:49:20.537 29294-29340 AndroidRuntime          com.identafly.preview                E  FATAL EXCEPTION: mqt_native_modules
                                                                                                    Process: com.identafly.preview, PID: 29294
                                                                                                    com.facebook.react.common.JavascriptException: Error: Cannot find native module 'BoundingBox', js engine: hermes, stack:
                                                                                                    requireNativeModule@1:688911

相关配置与代码

expo-module.config.json

{
  "platforms": ["ios", "tvos", "android", "web"],
  "ios": {
    "modules": ["BoundingBoxModule"]
  },
  "android": {
    "modules": ["expo.modules.boundingbox.BoundingBoxModule"]
  }
}

JS模块层代码(modules/bounding-box/index.ts)

import { type BoundingBoxProps } from './src/BoundingBox.types';
// Import the native module. On web, it will be resolved to BoundingBox.web.ts
// and on native platforms to BoundingBox.ts
import BoundingBoxModule from './src/BoundingBoxModule';

const drawBoundingBox = (props?: BoundingBoxProps) => {
  if (
    BoundingBoxModule &&
    typeof BoundingBoxModule.drawBoundingBox === 'function'
  ) {
    BoundingBoxModule.drawBoundingBox(props?.boundingBox, props?.color);
  } else {
    console.error('drawBoundingBox method not found');
  }
};

export { BoundingBoxProps, drawBoundingBox };

Native模块引入代码(modules/bounding-box/src/BoundingBoxModule.ts)

import { requireNativeModule } from 'expo-modules-core';

// It loads the native module object from the JSI or falls back to
// the bridge module (from NativeModulesProxy) if the remote debugger is on.
export default requireNativeModule('BoundingBox');

差异分析与解决方案

开发与生产bundle的核心差异

  • 模块打包策略:开发模式保留动态引用和调试逻辑,Native模块通过调试桥接(如NativeModulesProxy)加载;生产模式下Hermes会做激进压缩和树摇,若模块注册逻辑未被正确识别,可能被误删或无法绑定。
  • JSI vs 桥接模式:生产模式默认启用JSI直接调用Native模块,开发模式可能 fallback 到传统桥接。若Android端模块未正确注册到JSI,生产构建会找不到模块。

可能的问题点及修复方案

  1. Android模块注册不完整

    • 检查原生代码中BoundingBoxModule是否实现ExpoModule接口,类上标注@ExpoModule注解且name参数与JS端调用的BoundingBox完全一致:
      @ExpoModule(name = "BoundingBox")
      public class BoundingBoxModule extends ExpoModule {
        // 模块实现逻辑
      }
      
  2. expo-module.config.json配置问题

    • 确认Android模块全类名大小写与实际类一致(Java/Kotlin对包名大小写敏感),建议补充package配置帮助Expo识别模块位置:
      "android": {
        "package": "expo.modules.boundingbox",
        "modules": ["expo.modules.boundingbox.BoundingBoxModule"]
      }
      
  3. R8混淆导致模块被移除

    • Android生产构建默认启用R8混淆,需在proguard-rules.pro中添加规则保留模块类:
      -keep class expo.modules.boundingbox.BoundingBoxModule { *; }
      -keep class expo.modules.core.interfaces.ExpoModule { *; }
      
  4. Tree Shaking误删模块引用

    • 生产构建的Tree Shaking可能误将模块标记为未使用,可在JS端添加强制引用避免被摇掉:
      // 在index.ts中补充
      if (!__DEV__) {
        // 强制保留模块引用,防止Tree Shaking移除
        BoundingBoxModule;
      }
      

内容的提问来源于stack exchange,提问作者Phil Lucks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:11:20