[Android] Incorrect @NonNull annotations

128 views
Skip to first unread message

Alex

unread,
Jul 4, 2023, 9:42:23 AM7/4/23
to Interactive Media Ads SDK
IMA SDK 3.30.1 has incorrect @NonNull annotations on methods `AdEvent.getAd()` and `AdEvent.getAdData)`. Using them in Kotlin code results in NullPointerException at runtime for some events (and adding null checks manually triggers compilation warning because of annotations):

16:35:22.884 15683-15683 ImaAdEventListener       D  event = AdEvent[type=CONTENT_RESUME_REQUESTED, ad=null]
16:35:22.884 15683-15683 System.err               W  java.lang.NullPointerException: event.adData must not be null
16:35:22.885 15683-15683 System.err               W   at com.gsgroup.exovideoplayer.ads.ima.ImaAdEventListener.onAdEvent(ImaAdEventListener.kt:30)
16:35:22.885 15683-15683 System.err               W   at com.google.ads.interactivemedia.v3.impl.zzab.onAdEvent(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:31)
16:35:22.885 15683-15683 System.err               W   at com.google.ads.interactivemedia.v3.impl.zzt.onAdEvent(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:16)
16:35:22.885 15683-15683 System.err               W   at com.google.ads.interactivemedia.v3.impl.JavaScriptMessageRouter.onJavaScriptMsg(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:48)
16:35:22.885 15683-15683 System.err               W   at com.google.ads.interactivemedia.v3.impl.JavaScriptWebView.receiveJavaScriptMsg(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:7)
16:35:22.885 15683-15683 System.err               W   at com.google.ads.interactivemedia.v3.impl.zzav.onPostMessage(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:2)
16:35:22.885 15683-15683 System.err               W   at androidx.webkit.internal.WebMessageListenerAdapter.onPostMessage(WebMessageListenerAdapter.java:55)
16:35:22.885 15683-15683 System.err               W   at java.lang.reflect.Method.invoke(Native Method)
16:35:22.885 15683-15683 System.err               W   at org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil$InvocationHandlerWithDelegateGetter.invoke(BoundaryInterfaceReflectionUtil.java:162)
16:35:22.885 15683-15683 System.err               W   at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
16:35:22.885 15683-15683 System.err               W   at $Proxy32.onPostMessage(Unknown Source)
16:35:22.885 15683-15683 System.err               W   at org.chromium.android_webview.WebMessageListenerHolder.onPostMessage(chromium-TrichromeWebViewGoogle.aab-stable-573519631:80)
16:35:22.885 15683-15683 System.err               W   at android.os.MessageQueue.nativePollOnce(Native Method)
16:35:22.885 15683-15683 System.err               W   at android.os.MessageQueue.next(MessageQueue.java:339)
16:35:22.885 15683-15683 System.err               W   at android.os.Looper.loopOnce(Looper.java:179)
16:35:22.885 15683-15683 System.err               W   at android.os.Looper.loop(Looper.java:344)
16:35:22.885 15683-15683 System.err               W   at android.app.ActivityThread.main(ActivityThread.java:8249)
16:35:22.885 15683-15683 System.err               W   at java.lang.reflect.Method.invoke(Native Method)
16:35:22.885 15683-15683 System.err               W   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589)
16:35:22.885 15683-15683 System.err               W   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)


16:36:39.005 18077-18077 ImaAdEventListener       D  event = AdEvent[type=CONTENT_RESUME_REQUESTED, ad=null]
16:36:39.005 18077-18077 System.err               W  java.lang.NullPointerException: event.ad must not be null
16:36:39.006 18077-18077 System.err               W   at com.gsgroup.exovideoplayer.ads.ima.ImaAdEventListener.onAdEvent(ImaAdEventListener.kt:33)
16:36:39.006 18077-18077 System.err               W   at com.google.ads.interactivemedia.v3.impl.zzab.onAdEvent(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:31)
16:36:39.006 18077-18077 System.err               W   at com.google.ads.interactivemedia.v3.impl.zzt.onAdEvent(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:16)
16:36:39.006 18077-18077 System.err               W   at com.google.ads.interactivemedia.v3.impl.JavaScriptMessageRouter.onJavaScriptMsg(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:48)
16:36:39.006 18077-18077 System.err               W   at com.google.ads.interactivemedia.v3.impl.JavaScriptWebView.receiveJavaScriptMsg(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:7)
16:36:39.006 18077-18077 System.err               W   at com.google.ads.interactivemedia.v3.impl.zzav.onPostMessage(com.google.ads.interactivemedia.v3:interactivemedia@@3.30.1:2)
16:36:39.006 18077-18077 System.err               W   at androidx.webkit.internal.WebMessageListenerAdapter.onPostMessage(WebMessageListenerAdapter.java:55)
16:36:39.006 18077-18077 System.err               W   at java.lang.reflect.Method.invoke(Native Method)
16:36:39.006 18077-18077 System.err               W   at org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil$InvocationHandlerWithDelegateGetter.invoke(BoundaryInterfaceReflectionUtil.java:162)
16:36:39.006 18077-18077 System.err               W   at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
16:36:39.006 18077-18077 System.err               W   at $Proxy32.onPostMessage(Unknown Source)
16:36:39.006 18077-18077 System.err               W   at org.chromium.android_webview.WebMessageListenerHolder.onPostMessage(chromium-TrichromeWebViewGoogle.aab-stable-573519631:80)
16:36:39.006 18077-18077 System.err               W   at android.os.MessageQueue.nativePollOnce(Native Method)
16:36:39.006 18077-18077 System.err               W   at android.os.MessageQueue.next(MessageQueue.java:339)
16:36:39.006 18077-18077 System.err               W   at android.os.Looper.loopOnce(Looper.java:179)
16:36:39.006 18077-18077 System.err               W   at android.os.Looper.loop(Looper.java:344)
16:36:39.006 18077-18077 System.err               W   at android.app.ActivityThread.main(ActivityThread.java:8249)
16:36:39.006 18077-18077 System.err               W   at java.lang.reflect.Method.invoke(Native Method)
16:36:39.006 18077-18077 System.err               W   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589)
16:36:39.006 18077-18077 System.err               W   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)

IMA SDK

unread,
Jul 4, 2023, 1:10:26 PM7/4/23
to aroch...@gmail.com, ima...@googlegroups.com

Hi Alex,

Thank you for reaching out to us.

Can you confirm if you are able to encounter this error in any of our sample apps (https://github.com/googleads/googleads-ima-android/releases)? For us to further check this Incorrect @NonNull annotations that you're encountering, can you provide us the following information for us to further check?

  • Sample app project where the behavior is reproducible
  • Steps to replicate
  • Affected device and versions

In addition to that, you may use our sample app (https://github.com/googleads/googleads-ima-android/releases) for reference in your implementation to avoid any error.

If the file(s) you are looking to share are less than 25mb in total you can attach them to this case on your next reply. If you are having trouble attaching your file to this case or if your file(s) are larger than 25mb, you can share your files with me by performing the following steps:

1. Navigate to https://docs.google.com/forms/d/e/1FAIpQLSfkAiXMeYP-fw1W3Z-tT9uwmATEKO5X6S-th0gR2ezdKaaqfg/viewform?usp=pp_url&entry.400550049=IMA+SDK&entry.460850823=5004Q00002mrJvlQAE&entry.80707362=00187125

2. Fill out all fields, and attach your file(s).

3. Please reply back on this thread when you have uploaded your file(s). Please do not share this link. 

This message is in relation to case "ref:_00D1U1174p._5004Q2mrJvl:ref"

Thanks,
 
Google Logo IMA SDK Team


Alex

unread,
Nov 15, 2023, 11:25:17 AM11/15/23
to Interactive Media Ads SDK
Here is sample app branch that you can use to reproduce the issue: https://github.com/equeim/googleads-ima-android/tree/kotlin-npe. Use VMAP sample.
AdEvent.getAdData() NPE happens with LOADED events, AdEvent.getAd() NPE happens with CONTENT_RESUME_REQUESTED events.
BTW this is reproducible with 3.31.0.

IMA SDK

unread,
Nov 16, 2023, 6:02:02 AM11/16/23
to aroch...@gmail.com, ima...@googlegroups.com

Hi Alex,

Thank you for contacting the IMA SDK support team.

By reviewing your concern, I understand that you are getting NPE on AdEvent.getAdData() happens with LOADED events, AdEvent.getAd() NPE happens with CONTENT_RESUME_REQUESTED events. I would like to inform you that our team is currently working on this issue. One of our teammates will get back to you once we have an update on this. Meanwhile your patience is appreciated.
 

This message is in relation to case "ref:!00D1U01174p.!5004Q02qCVan:ref"


Thanks,
 
Google Logo IMA SDK Team


IMA SDK

unread,
Nov 17, 2023, 4:03:14 AM11/17/23
to ima...@googlegroups.com, aroch...@gmail.com

Hi Alex,

We have noticed that this is an intended behavior. Prior to invoking the adEvent.getAd() method, it is necessary to verify if it contains a value or is null. 

Please check the below workaround:

Ad currentAd = adEvent.getAd();

if (currentAd) {

  currentAd.getAdPodInfo();

  // Or do other things with the Ad.

Alex

unread,
Nov 17, 2023, 5:20:29 AM11/17/23
to Interactive Media Ads SDK
That doesn't work in Kotlin, because Kotlin compiler automatically inserts `Intrinsics.checkNotNullExpressionValue()` calls into generated bytecode after getAd() and getAdData() calls due to presence of `@NonNull` annotation on these methods. These checks throw NPE if returned value is null, and they are performed *before* any manual checks that are written in Kotlin source code. I.e. this code:

```
val ad = event.ad
if (ad != null) {
   val pod = ad.podInfo
   Log.d(TAG, "pod = $pod")
}
```

Will still throw NPE, because there is hidden check just before if block that throws it, because of `@NonNull`.

In order for this to work as intended these methods should have `@Nullable` annotation to indicate that it can return null, or no annotaion at all (but it's better to be explicit).
пятница, 17 ноября 2023 г. в 12:03:14 UTC+3, IMA SDK:

IMA SDK

unread,
Nov 17, 2023, 8:02:31 AM11/17/23
to aroch...@gmail.com, ima...@googlegroups.com

Hi Alex,

Thank you for getting back to us.

We can achieve this by using the Kotlin Null safety operators. Please find below Kotlin work around:

val ad = event?.ad

val adPodInfo:AdPodInfo? = ad?.adPodInfo

Log.d(TAG,adPodInfo.toString())
 

Alex

unread,
Nov 17, 2023, 8:41:06 AM11/17/23
to Interactive Media Ads SDK
Surprisingly this works, which is strange since '?' operator here is supposed to refer to `event`, not return value of `getAd()`.
Another workaround I found is to explicitly specify type of the variable as nullable:

val ad: Ad? = event.ad

However these workarounds are suboptimal since they result in IDE and/or compiler misleadingly warning you that these checks are unnecessary. This should be fixed in IMA SDK itself by replacing @NonNull annotation with @Nullable.
пятница, 17 ноября 2023 г. в 16:02:31 UTC+3, IMA SDK:

IMA SDK

unread,
Nov 17, 2023, 9:22:17 AM11/17/23
to aroch...@gmail.com, ima...@googlegroups.com

Hi Alex,

Thank you for your feedback. I will convey your suggestion to our team.

Reply all
Reply to author
Forward
0 new messages