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

React Native中Android InMobi Banner基于SimpleViewManager不显示求助

问题:React Native Android原生组件集成InMobi Banner不显示(SimpleViewManager方案)

我在开发React Native的Android原生UI组件以集成InMobi Banner时遇到问题:用继承SimpleViewManager的类创建UI模块,组件无法在屏幕上显示;但用Fragment实现时能正常运行。根据InMobi文档,Banner只能在UI线程显示,我尝试了Handler和runOnUiThread(通过React bridge)但无效。

我不想用Fragment方案,因为需要将Banner集成到现有布局中。以下是我的实现代码:

InMobiBannerManager类(继承SimpleViewManager)

public class InMobiBannerManager extends SimpleViewManager<InMobiBannerClass> {

    public static final String REACT_CLASS = "InMobibanner";
    ReactApplicationContext reactContext;

    public InMobiBannerManager(ReactApplicationContext reactContext) {
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    protected InMobiBannerClass createViewInstance(ThemedReactContext reactContext) {
        return new InMobiBannerClass(reactContext);
    }
}

InMobiBannerClass类(继承RelativeLayout)

public class InMobiBannerClass extends RelativeLayout  {
    Context context;
    InMobiBanner bannerAd;
    private static final String TAG = "InMobiBannerClass";

    BannerAdEventListener bannerAdEventListener = new BannerAdEventListener() {
        @Override
        public void onAdFetchFailed(@NonNull InMobiBanner inMobiBanner, @NonNull InMobiAdRequestStatus inMobiAdRequestStatus) {
            super.onAdFetchFailed(inMobiBanner, inMobiAdRequestStatus);
            Log.d(TAG, "INMOBIBANNNERonAdFetchFailed: "+inMobiAdRequestStatus.getMessage());
        }

        @Override
        public void onAdDisplayed(@NonNull InMobiBanner inMobiBanner) {
            super.onAdDisplayed(inMobiBanner);
            Log.d(TAG, "INMOBIBANNNERonAdDisplayed: ");
        }

        @Override
        public void onAdDismissed(@NonNull InMobiBanner inMobiBanner) {
            super.onAdDismissed(inMobiBanner);
            Log.d(TAG, "INMOBIBANNNERonAdDismissed: ");
        }

        @Override
        public void onUserLeftApplication(@NonNull InMobiBanner inMobiBanner) {
            super.onUserLeftApplication(inMobiBanner);
        }

        @Override
        public void onRewardsUnlocked(@NonNull InMobiBanner inMobiBanner, Map<Object, Object> map) {
            super.onRewardsUnlocked(inMobiBanner, map);
        }

        @Override
        public void onAdFetchSuccessful(@NonNull InMobiBanner inMobiBanner, @NonNull AdMetaInfo adMetaInfo) {
            super.onAdFetchSuccessful(inMobiBanner, adMetaInfo);
            Log.d(TAG, "onAdFetchSuccessful: ");
        }

        @Override
        public void onAdLoadSucceeded(@NonNull InMobiBanner inMobiBanner, @NonNull AdMetaInfo adMetaInfo) {
            super.onAdLoadSucceeded(inMobiBanner, adMetaInfo);
            Log.d(TAG, "INMOBIBANNNERonAdLoadSucceeded: ");
        }

        @Override
        public void onAdLoadFailed(@NonNull InMobiBanner inMobiBanner, @NonNull InMobiAdRequestStatus inMobiAdRequestStatus) {
            super.onAdLoadFailed(inMobiBanner, inMobiAdRequestStatus);
            Log.d(TAG, "INMOBIBANNNERonAdLoadFailed: "+inMobiAdRequestStatus.getMessage());
        }

        @Override
        public void onAdClicked(@NonNull InMobiBanner inMobiBanner, Map<Object, Object> map) {
            super.onAdClicked(inMobiBanner, map);
        }

        @Override
        public void onRequestPayloadCreated(byte[] bytes) {
            super.onRequestPayloadCreated(bytes);
        }

        @Override
        public void onRequestPayloadCreationFailed(@NonNull InMobiAdRequestStatus inMobiAdRequestStatus) {
            super.onRequestPayloadCreationFailed(inMobiAdRequestStatus);
        }

        @Override
        public void onAdImpression(@NonNull InMobiBanner inMobiBanner) {
            super.onAdImpression(inMobiBanner);
        }
    };

    @SuppressLint("MissingInflatedId")
    public InMobiBannerClass(Context context) {
        super(context);
        this.context = context;

        LayoutInflater inflater = LayoutInflater.from(context);
        View inflatedView = inflater.inflate(R.layout.activity_main3, null);
        RelativeLayout adContainer = (RelativeLayout) inflatedView.findViewById(R.id.ad_container);
        bannerAd = new InMobiBanner(context, 1683264304035L);
        RelativeLayout.LayoutParams bannerLp = new RelativeLayout.LayoutParams(dpToPx(350), dpToPx(200));

        adContainer.addView(bannerAd, bannerLp);

        bannerAd.setListener(bannerAdEventListener);

        // 原代码此处有语法错误,且createViewInstance本身就在UI线程,无需额外延迟
        new Handler(Looper.getMainLooper()).post(() -> {
            bannerAd.setEnableAutoRefresh(true);
            bannerAd.load();
        });
        
        // 给inflatedView设置LayoutParams,确保它能填满当前RelativeLayout
        addView(inflatedView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    }

    private int dpToPx(int dp) {
        return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
    }

    public void onReceiveNativeEvent() {
        WritableMap event = Arguments.createMap();
        event.putString("message", "MyMessage");
        ReactContext reactContext = (ReactContext)getContext();
        reactContext
                .getJSModule(RCTEventEmitter.class)
                .receiveEvent(getId(), "topChange", event);
    }
}

React Native侧调用代码

const InMobibanner = requireNativeComponent('InMobibanner');

// 使用时必须设置宽高,否则原生组件可能不显示
function App() {
  return (
    <View style={{flex: 1}}>
      {/* 给Banner组件设置明确的宽高 */}
      <InMobibanner style={{width: 350, height: 200}} />
    </View>
  );
}

解决方案分析

  1. UI线程问题:SimpleViewManager的createViewInstance方法本身就在UI线程执行,不需要额外用runOnUiThread延迟加载,原代码中的延迟反而可能导致初始化时机异常,且存在语法错误(多了闭合括号)。直接用Handler(Looper.getMainLooper())确保在主线程执行即可,甚至可以直接调用bannerAd.load()。

  2. 布局参数问题:

    • 将inflatedView添加到当前RelativeLayout时,必须设置LayoutParams为MATCH_PARENT,否则视图会没有尺寸而不显示。
    • React Native侧使用原生组件时,必须给组件设置明确的宽高样式,RN不会自动给原生组件分配尺寸。
  3. 注册Native组件:确保在自定义的ReactPackage中注册InMobiBannerManager,否则RN无法识别该原生组件:

public class CustomPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        List<ViewManager> modules = new ArrayList<>();
        modules.add(new InMobiBannerManager(reactContext));
        return modules;
    }
}
  1. 检查布局文件activity_main3:确保ad_container这个RelativeLayout设置了合适的宽高(比如match_parent),否则Banner添加进去后也无法显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 09:35:00