Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to invoke virtual method 'com.google.firebase.inappmessaging.model.MessageType kb.i.c()' #4214

Closed
gonojuarez opened this issue Oct 17, 2022 · 19 comments · Fixed by #4691

Comments

@gonojuarez
Copy link

gonojuarez commented Oct 17, 2022

[READ] Step 1: Are you in the right place?

Issues filed here should be about bugs in the code in this repository.
If you have a general question, need help debugging, or fall into some
other category use one of these other channels:

  • For general technical questions, post a question on StackOverflow
    with the firebase tag.
  • For general Firebase discussion, use the firebase-talk
    google group.
  • For help troubleshooting your application that does not fall under one
    of the above categories, reach out to the personalized
    Firebase support channel.

[REQUIRED] Step 2: Describe your environment

  • Android Studio version: 2021.2.1 Patch 2
  • Firebase Component: inAppMessaging
  • Component version: 20.2.0

[REQUIRED] Step 3: Describe the problem

Firebase crash.

Steps to reproduce:

message.getMessageType is null

Relevant Code:

// branch code
private List<Action> extractActions(InAppMessage message) {
 List<Action> actions = new ArrayList<>();
 switch (message.getMessageType()) {
  case BANNER:
   actions.add(((BannerMessage) message).getAction());
  break;
  case CARD:
    actions.add(((CardMessage) message).getPrimaryAction());
    actions.add(((CardMessage) message).getSecondaryAction());
   break;
  case IMAGE_ONLY:
    actions.add(((ImageOnlyMessage) message).getAction());
  break;
  case MODAL: 
    actions.add(((ModalMessage) message).getAction());
  break;
  default:
   // An empty action is treated like a dismiss
     actions.add(Action.builder().build());
  }
   return actions;
}

// Log
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.inappmessaging.model.MessageType kb.i.c()' on a null object reference
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay.extractActions(FirebaseInAppMessagingDisplay.java:437)
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay.inflateBinding(FirebaseInAppMessagingDisplay.java:308)
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay.access$000(FirebaseInAppMessagingDisplay.java:79)
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay$1.run(FirebaseInAppMessagingDisplay.java:286)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:246)
       at android.app.ActivityThread.main(ActivityThread.java:8512)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1139)


// suggested code
private List<Action> extractActions(InAppMessage message) {
 List<Action> actions = new ArrayList<>();
  if(InAppMessage != null){
      switch (message.getMessageType()) {
         case BANNER:
            actions.add(((BannerMessage) message).getAction());
         break;
        case CARD:
           actions.add(((CardMessage) message).getPrimaryAction());
           actions.add(((CardMessage) message).getSecondaryAction());
         break;
         case IMAGE_ONLY:
           actions.add(((ImageOnlyMessage) message).getAction());
         break;
         case MODAL: 
           actions.add(((ModalMessage) message).getAction());
         break;
        default:
        // An empty action is treated like a dismiss
         actions.add(Action.builder().build());
      }
  }

   return actions;
}
@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@argzdev
Copy link
Contributor

argzdev commented Oct 18, 2022

Hi @gonojuarez, thanks for reporting and for the proposed solution! Let me pull up a PR real quick.

@argzdev
Copy link
Contributor

argzdev commented Oct 19, 2022

Hi @gonojuarez, it looks like the InAppMessage there shouldn't be a null when reaching the method extractActions since we will start the inapp message rendering only if we have a valid object. Could you provide steps how were you able to reproduce this behavior? Or if there's any chance you could provide a MCVE, that'll help us a lot. Thanks!

@thatfiredev
Copy link
Member

This seems to be similar to #3596

@gonojuarez
Copy link
Author

I don't know how to reproduce it.
I read the code and understand the bug are related with the inAppMessage.

@argzdev
Copy link
Contributor

argzdev commented Oct 20, 2022

Thanks for confirming @gonojuarez. Do you remember which type of message layout was selected in Firebase console?

Screen Shot 2022-03-30 at 5 24 26 PM

Also can you confirm how frequent does this issue occur? Maybe that'll give us a hint what triggered the issue.

Thanks!

@gonojuarez
Copy link
Author

I used the card option
In the last 90 days, This bug has affected 12 users and appeared 15 times.

@argzdev
Copy link
Contributor

argzdev commented Oct 20, 2022

That is interesting, thank you for these details. I'll try to inform our engineer about this.

@gonojuarez
Copy link
Author

Thank you @argzdev

@argzdev
Copy link
Contributor

argzdev commented Nov 30, 2022

Hi @gonojuarez, sorry for the delayed response. We're still investigating this. May I ask how are you running your campaigns? Are you triggering multiple campaigns at the same time? If so, could you share what setup are you doing? It might give us a hint how your users encounter the issue.

We think that the issue might be due to a multithreading race condition. Since FirebaseInAppMessagingDisplay keeps a single instance of inAppMessage, I'm assuming If multiple inAppMessage is present, it might be possible that the moment one inAppMessage is set to null due to (see below) and another inAppMessage tries to access the extractAction, then that throws the NullPointerException.

Scenarios when inAppMessage is set to null:

  1. Upon onClick of a button of an inAppMessage with action
  2. Upon dismissFiam of a FIAM
  3. Upon onError of loading an image of a FIAM.

@vijayshuru
Copy link

Yes, I am also getting the same crash again and again on the app open in testing mode. We have 3 active campaigns to test. I have completed two campaigns. Now my app is not crashing.

@argzdev
Copy link
Contributor

argzdev commented Dec 1, 2022

Hi @vijayshuru, can you share your steps how to reproduce this behavior? Thanks!

@viniciusalvesmello
Copy link

I have the same problem 😥!

In this version 11.18.2 it was necessary to update the targetSdkVersion from 30 to 31, due to Google Play rules.

image

Trace Crashlytics

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.inappmessaging.model.MessageType com.google.firebase.inappmessaging.model.InAppMessage.getMessageType()' on a null object reference
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay.extractActions(FirebaseInAppMessagingDisplay.java:437)
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay.inflateBinding(FirebaseInAppMessagingDisplay.java:308)
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay.access$000(FirebaseInAppMessagingDisplay.java:79)
       at com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay$1.run(FirebaseInAppMessagingDisplay.java:286)
       at android.os.Handler.handleCallback(Handler.java:883)
       at android.os.Handler.dispatchMessage(Handler.java:100)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:7438)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:989)

@gonojuarez
Copy link
Author

gonojuarez commented Dec 1, 2022

@argzdev
In my case, My teams have 3 or 4 campaigns activate using the in-app message.
That campaign contains a picture inside the dialogue and the message.

@vijayshuru
Copy link

Hi @vijayshuru, can you share you steps how to reproduce this behavior? Thanks!

Sorry, This does not happen with all users. Also a user gets a message once in a day through the campaign. So It is difficult to reproduce.

@lotdrops
Copy link

lotdrops commented Jan 3, 2023

I am also facing this issue.
We have around 200k "active devices" on the play store console, and about 50 crashes (about 15 users). We send our campaigns to all users, so it is not something that is reproducible, it occurs "randomly to a few users". And it happens in different devices and android versions

@argzdev
Copy link
Contributor

argzdev commented Jan 16, 2023

Hi all, while we investigate this further. Kindly leave a thumbs up on the author's post. So that we can track the issue and prioritize a deeper investigation depending on severity. Thanks!

@eldhosembabu
Copy link
Contributor

eldhosembabu commented Feb 16, 2023

After analyzing the issue, the inappmessage instance shouldn't be null when calling the extractActions method because if we check the call stack, it is getting called from showActiveFIAM method where we are already checking for null inappmessage instance as you can see here.

So i believe the inappmessage instance getting null is because of some race condition happening when dealing with displaying multiple inapp messages one after the other and probably the countdown timers of the prior inappmessage (say impressiontimer) resetting the current inapp message when they call dismiss fiam even though we are cancelling the timers. This is because, we have a timer tick reporting delay of 1 second as you can see here.

So I think the use case in which this issue could happen is when 1st inapp message gets dismissed which clears the inappmessage instance, but still waiting for timers to settle, before which the second inappmessage is processed for displaying and in between the previous "escaped timers" clears the inappmessage instance again and leads to the null pointer exception.

If the use case I think is correct, we could do the following fixes:

  1. Simply adding a null check before calling the extractActions method - This will prevent the crash, but might postpone the inapp message to be displayed during the next event.
  2. We could try reducing the timer reporting interval - This could reduce the crash if my theory is right.
  3. Refactor the code to properly isolate the instances used for processing one inappmessage from other. This can be a long term fix if we find No. 1 and No. 2 fix is not useful enough.

I'll create a PR with null check and post here soon.

@xiaomochn
Copy link

I am also facing this issue, which version of the bom upgrade can solve the problem

@firebase firebase locked and limited conversation to collaborators Mar 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants