NullPointerException in MoPubStaticNativeAdRenderer

mopub
crash
issues

#1

Crash is stable for months.

Seems like native ad instance still holding reference to MoPubNetworkListener after MoPubNative#destroy was called, and this listener continue to receive calls. Add renderer also still holding reference to context after it is nulled. Am I missing something in code? Looks like an SDK bug.

Full stack trace:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
       at android.view.LayoutInflater.from(LayoutInflater.java:234)
       at com.mopub.nativeads.MoPubStaticNativeAdRenderer.createAdView(Unknown Source)
       at com.mopub.nativeads.NativeAd.createAdView(Unknown Source)
       at ru.sports.ui.delegates.IndexPageDelegate$1.handle(IndexPageDelegate.java:248)
       at ru.sports.ui.delegates.IndexPageDelegate$1.handle(IndexPageDelegate.java:240)
       at ru.sports.ui.builders.NativeAdBuilder$1.onNativeLoad(NativeAdBuilder.java:44)
       at com.mopub.nativeads.MoPubNative$3.onNativeAdLoaded(Unknown Source)
       at com.mopub.nativeads.FacebookNative$FacebookStaticNativeAd$1.onImagesCached(FacebookNative.java:189)
       at com.mopub.nativeads.NativeImageHelper$1.onResponse(Unknown Source)
       at com.mopub.volley.toolbox.ImageLoader$4.run(Unknown Source)
       at android.os.Handler.handleCallback(Handler.java:739)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:7325)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

The code I use to load ad:

private MoPubNative ad;

private void displayAd() {

    ViewBinder binder = new ViewBinder.Builder(R.layout.item_mopub_big)
            .textId(R.id.text)
            .titleId(R.id.title)
            .iconImageId(R.id.icon)
            .mainImageId(R.id.image)
            .callToActionId(R.id.action)
            .privacyInformationIconImageId(R.id.privacy_information_icon)
            .build();

    final MoPubStaticNativeAdRenderer renderer = new MoPubStaticNativeAdRenderer(binder);

    MoPubNative ad = new MoPubNative(activity, moPubId,
            new MoPubNative.MoPubNativeNetworkListener() {

                @Override
                public void onNativeLoad(NativeAd nativeAd) {
                    if (nativeAd == null) {
                        Logger.error(this, "Failed to load ad");
                        return;
                    }

                    // The point where crash occurs
                    View adView = nativeAd.createAdView(activity, null);

                    nativeAd.getMoPubAdRenderer().renderAdView(adView, nativeAd.getBaseNativeAd());
                    nativeAd.prepare(adView);

                    adContainer.addView(adView);
                    adContainer.setVisibility(View.VISIBLE);
                }

                @Override
                public void onNativeFail(NativeErrorCode errorCode) {
                    Logger.error(this, "Failed to load ads");
                }

            }
    );

    ad.registerAdRenderer(renderer);
    ad.makeRequest();
}

@Override
public void onViewDestroyed() {
    if (ad != null) {
        ad.destroy();
        ad = null;
    }
    adContainer.removeAllViews();
    adContainer = null;
}


#2

Hi @ruslanarslan,

Thanks for getting in touch. I reviewed your code and also ran it, and it worked fine. Could you elaborate on your use case - is there anything else in your code that would affect the logic the MoPubStaticNativeAdRenderer needs, or is there any sequence of events that happens to trigger the crash? The crash is an NPE, so it might be worth inspecting your overall logic and add null checks where necessary before you invoke any ad logic.

I also noticed you are using NativeAd.createAdView() and NativeAd.renderAdView(). They are really intended for subclassing purposes, such as when you create your own native ad custom event (for mediation). If you are not writing custom events, and only want to do a manual integration of native ads, you can follow this tutorial, which utilizes AdapterHelper.getAdView() that can then be added to your view hierarchy.

Let us know if you have any questions!