Search Unity

Bug Ad shows in Editor but not in store build - logcat included

Discussion in 'Unity Mediation' started by nobluff67, Jul 21, 2022.

  1. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    The ad shows without any issues in the editor however when I build and run through play store internal testing, the ads will not show. There is an error in my logcat however I can not decipher the error after researching.

    Can anyone explain or help?

    In reward show method
    <ShowRewarded>d__5:MoveNext()
    System.Runtime.CompilerServices.AsyncVoidMethodBuilder:Start(TStateMachine&)
    AdRewardsController:ShowRewarded()
    UnityEngine.Events.UnityAction:Invoke()
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.EventSystems.EventFunction`1:Invoke(T1, BaseEventData)
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:processTouchPress(PointerEventData, Boolean, Boolean)
    UnityEngine.EventSystems.StandaloneInputModule:processTouchEvents()
    UnityEngine.EventSystems.StandaloneInputModule:process()

    AndroidJavaException: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.h.d, parameter userId
    java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.h.d, parameter userId
    at com.unity3d.mediation.RewardedAdShowOptions$S2SRedeemData.<init>(Unknown Source:2)
    at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
    at com.unity3d.player.UnityPlayer.access$300(Unknown Source:0)
    at com.unity3d.player.UnityPlayer$e$1.handleMessage(Unknown Source:95)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:214)
    at com.unity3d.player.UnityPlayer$e.run(Unknown Source:20)
    at UnityEngine.AndroidJNISafe.CheckException () [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.AndroidJNISafe.NewObject (System.IntPtr clazz, System.IntPtr methodID, UnityEngine.jvalue[] args) [0x00000] in <00000000000000000000000000000000>:0
    at UnityEngine.AndroidJavaObject._Android

    Rewarded failed to show: Failed to show - java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.h.d, parameter userId
    <ShowRewarded>d__5:MoveNext()
    System.Threading.ContextCallback:Invoke(Object)
    System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
    System.Runtime.CompilerServices.MoveNextRunner:Run()
    System.Action:Invoke()
    System.Threading.ContextCallback:Invoke(Object)
    System.Threading.Tasks.AwaitTaskContinuation:RunCallback(ContextCallback, Object, Task&)
    System.Threading.Tasks.Task:FinishContinuations()
    System.Threading.Tasks.Task:Finish(Boolean)
    System.Threading.Tasks.Task`1:TrySetException(Object)
    System.Threading.Tasks.TaskCompletionSource`1:TrySetException(Exception)
    Unity.Services.Mediation.RewardedAd:OnShowFailed(Object, ShowErrorEventArgs)
    System.EventHandler`1:Invoke(Object, TEventArgs)
    System.Threading.SendOrPostCallback:Invoke(Object)
    UnityEngine.WorkRequest:Invoke()
    UnityEngine.UnitySynchronizationContext
    AdUnit with adUnitId: Rewarded_Android has already loaded.​
     
  2. jcGrenier

    jcGrenier

    Unity Technologies

    Joined:
    Feb 23, 2021
    Posts:
    145
    Hi @nobluff67 !
    This would mean you are passing S2SData, without a userId (passing null). This is not allowed, and S2SData if used has to contain a userId.

    Hope this helps :)
     
    nobluff67 likes this.
  3. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    Pause on help.

    It might have to do with not having gameid (build version). Editor version doesnt seem to care. Creating another test build now.
     
  4. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    You beat me to it:). UserId = gameid maybe?
     
  5. DeclanMcPartlin

    DeclanMcPartlin

    Unity Technologies

    Joined:
    Nov 19, 2020
    Posts:
    146
    Hi @nobluff67,

    The S2S data is used to validate legitimate rewards, to avoid players cheating. Generally the userId is a game specific value used to identify the player getting rewarded. If you do not have a S2S system set up, we recommend you do not pass any values into the Show call (showOptions is an optional parameter for Show).

    Let us know if that's the case for you, thanks.
     
  6. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    Not sure about the S2S stuff, don't really understand what you are saying.

    I am using this code from the mediation code generator, is this code good enough or do I need to do something with S2S within this code?

    Do I remove the showOptions part of the code? "await ad.ShowAsync(showOptions);"

    Do I need S2S for ad mediation? i.e. is it a best practice or can I do without it?

    Code (CSharp):
    1. using System;
    2. using Unity.Services.Core;
    3. using Unity.Services.Mediation;
    4. using UnityEngine;
    5.  
    6. namespace Unity.Example
    7. {
    8.     public class RewardedAdExample
    9.     {
    10.         IRewardedAd ad;
    11.         string adUnitId = "Rewarded_Android";
    12.         string gameId = "XXXXXXXX";
    13.  
    14.         public async void InitServices()
    15.         {
    16.             try
    17.             {
    18.                 InitializationOptions initializationOptions = new InitializationOptions();
    19.                 initializationOptions.SetGameId(gameId);
    20.                 await UnityServices.InitializeAsync(initializationOptions);
    21.  
    22.                 InitializationComplete();
    23.             }
    24.             catch (Exception e)
    25.             {
    26.                 InitializationFailed(e);
    27.             }
    28.         }
    29.  
    30.         public void SetupAd()
    31.         {
    32.             //Create
    33.             ad = MediationService.Instance.CreateRewardedAd(adUnitId);
    34.  
    35.             //Subscribe to events
    36.             ad.OnClosed += AdClosed;
    37.             ad.OnClicked += AdClicked;
    38.             ad.OnLoaded += AdLoaded;
    39.             ad.OnFailedLoad += AdFailedLoad;
    40.             ad.OnUserRewarded += UserRewarded;
    41.  
    42.             // Impression Event
    43.             MediationService.Instance.ImpressionEventPublisher.OnImpression += ImpressionEvent;
    44.         }
    45.      
    46.         public async void ShowAd()
    47.         {
    48.             if (ad.AdState == AdState.Loaded)
    49.             {
    50.                 try
    51.                 {
    52.                     RewardedAdShowOptions showOptions = new RewardedAdShowOptions();
    53.                     showOptions.AutoReload = true;
    54.                     await ad.ShowAsync(showOptions);
    55.                     AdShown();
    56.                 }
    57.                 catch (ShowFailedException e)
    58.                 {
    59.                     AdFailedShow(e);
    60.                 }
    61.             }
    62.         }
    63.  
    64.         void InitializationComplete()
    65.         {
    66.             SetupAd();
    67.             LoadAd();
    68.         }
    69.  
    70.         async void LoadAd()
    71.         {
    72.             try
    73.             {
    74.                 await ad.LoadAsync();
    75.             }
    76.             catch (LoadFailedException)
    77.             {
    78.                 // We will handle the failure in the OnFailedLoad callback
    79.             }
    80.         }
    81.  
    82.         void InitializationFailed(Exception e)
    83.         {
    84.             Debug.Log("Initialization Failed: " + e.Message);
    85.         }
    86.  
    87.         void AdLoaded(object sender, EventArgs e)
    88.         {
    89.             Debug.Log("Ad loaded");
    90.         }
    91.  
    92.         void AdFailedLoad(object sender, LoadErrorEventArgs e)
    93.         {
    94.             Debug.Log("Failed to load ad");
    95.             Debug.Log(e.Message);
    96.         }
    97.      
    98.         void AdShown()
    99.         {
    100.             Debug.Log("Ad shown!");
    101.         }
    102.      
    103.         void AdClosed(object sender, EventArgs e)
    104.         {
    105.             Debug.Log("Ad has closed");
    106.             // Execute logic after an ad has been closed.
    107.         }
    108.  
    109.         void AdClicked(object sender, EventArgs e)
    110.         {
    111.             Debug.Log("Ad has been clicked");
    112.             // Execute logic after an ad has been clicked.
    113.         }
    114.      
    115.         void AdFailedShow(ShowFailedException e)
    116.         {
    117.             Debug.Log(e.Message);
    118.         }
    119.  
    120.         void ImpressionEvent(object sender, ImpressionEventArgs args)
    121.         {
    122.             var impressionData = args.ImpressionData != null ? JsonUtility.ToJson(args.ImpressionData, true) : "null";
    123.             Debug.Log("Impression event from ad unit id " + args.AdUnitId + " " + impressionData);
    124.         }
    125.      
    126.         void UserRewarded(object sender, RewardEventArgs e)
    127.         {
    128.             Debug.Log($"Received reward: type:{e.Type}; amount:{e.Amount}");
    129.         }
    130.  
    131.     }
    132. }
     
  7. DeclanMcPartlin

    DeclanMcPartlin

    Unity Technologies

    Joined:
    Nov 19, 2020
    Posts:
    146
    Hey @nobluff67,

    Thanks for clarifying. To help determine the issue, which version of Unity Mediation are you using?

    Thanks!
     
    nobluff67 likes this.
  8. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    Most recent version, Version 0.5.0-preview.5

    I am currently testing with this line of code:

    await ad.ShowAsync();

    instead of:

    await ad.ShowAsync(showOptions);
     
  9. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    FYI - await ad.ShowAsync(); works for me. No idea if I am doing this correctly.
     
  10. DeclanMcPartlin

    DeclanMcPartlin

    Unity Technologies

    Joined:
    Nov 19, 2020
    Posts:
    146
    Hey @nobluff67,

    Thanks for providing this extra insight. So far I haven't been able to reproduce this issue. In Player Settings > Publishing Settings, do you have Custom Main Gradle Template selected or not?

    Thanks,
     
  11. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    a couple of post up, I got it working by changing:

    await ad.ShowAsync();

    instead of:

    await ad.ShowAsync(showOptions);

    I am just not 100% sure of this is a recommended solution.
     
  12. DeclanMcPartlin

    DeclanMcPartlin

    Unity Technologies

    Joined:
    Nov 19, 2020
    Posts:
    146
    Hi @nobluff67,

    Thanks for sharing a solution that worked for you. Nonetheless, the original code snippet should be able to work, if you reply to my question above, we can continue researching the issue.

    Thanks!
     
    nobluff67 likes this.
  13. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    No I don't, just progaurd-user.txt. I believe I have added to this file since the issue, so I am not sure if this would have solved my specific issue. The additions to the progaurd file did resolve some other google related issues, so maybe they overlap. I will create a new build later on tonight, with the original code - await ad.ShowAsync(showOptions); to see if the issue persists on my side.

    upload_2022-7-25_15-36-20.png
     
  14. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    @DeclanMcPartlin i just tested and the problem still persists, in other words my previous changes to the progaurd file did not make a difference to this specific issue. In the mean time I have removed the showOptions portion of the await ad.ShowAsync(showOptions); As mentioned before, it works when I remove the showOptions, so at least its not halting my production work.
     
  15. DeclanMcPartlin

    DeclanMcPartlin

    Unity Technologies

    Joined:
    Nov 19, 2020
    Posts:
    146
    Hey @nobluff67,

    I've just checked with the team and this issue will be handled in the next patch release, thanks again for reaching out and sharing this. For the time being, I'd recommend using Autoreload by providing filler values for S2S like so:

    Code (CSharp):
    1. RewardedAdShowOptions showOptions = new RewardedAdShowOptions();
    2. S2SRedeemData s2SData;
    3. s2SData.UserId = "placeholder";
    4. s2SData.CustomData = "placeholder";
    5. showOptions.S2SData = s2SData;
    6. showOptions.AutoReload = true;
    7. await m_RewardedAd.ShowAsync(showOptions);
    I'll let you know in this thread once we have a new release out. Thanks!
     
    nobluff67 likes this.
  16. nobluff67

    nobluff67

    Joined:
    Nov 3, 2016
    Posts:
    338
    This works, however I would like to make sure we are not getting our wires crossed. I am using

    ShowRewarded() and not ShowRewardedWithOptions(). The ShowRewarded() method was the one that was giving me issues, and the one I changed with your suggested code.

    Code (CSharp):
    1.         public async void ShowRewarded()
    2.         {
    3.             Debug.Log("In reward show method");
    4.             Debug.Log("showad " + m_RewardedAd.AdState);
    5.             completeAdWatched = false;
    6.             if (m_RewardedAd?.AdState == AdState.Loaded)
    7.             {
    8.                 try
    9.                 {
    10.                     //RewardedAdShowOptions showOptions = new RewardedAdShowOptions();
    11.                     //showOptions.AutoReload = true;
    12.                     //await m_RewardedAd.ShowAsync();
    13.                     //Debug.Log("Rewarded Shown!");
    14.                    
    15.                     RewardedAdShowOptions showOptions = new RewardedAdShowOptions();
    16.                     S2SRedeemData s2SData;
    17.                     s2SData.UserId = "placeholder";
    18.                     s2SData.CustomData = "placeholder";
    19.                     showOptions.S2SData = s2SData;
    20.                     showOptions.AutoReload = true;
    21.                     await m_RewardedAd.ShowAsync(showOptions);
    22.                    
    23.                    
    24.                 }
    25.                 catch (ShowFailedException e)
    26.                 {
    27.                     Debug.LogWarning($"Rewarded failed to show: {e.Message}");
    28.                 }
    29.             }
    30.         }
    31.        
    32.         public async void ShowRewardedWithOptions()
    33.         {
    34.             if (m_RewardedAd?.AdState == AdState.Loaded)
    35.             {
    36.                 try
    37.                 {
    38.                     //Here we provide a user id and custom data for server to server validation.
    39.                     RewardedAdShowOptions showOptions = new RewardedAdShowOptions();
    40.                     showOptions.AutoReload = true;
    41.                     S2SRedeemData s2SData;
    42.                     s2SData.UserId = "my cool user id";
    43.                     s2SData.CustomData = "{\"reward\":\"Gems\",\"amount\":20}";
    44.                     showOptions.S2SData = s2SData;
    45.  
    46.                     await m_RewardedAd.ShowAsync(showOptions);
    47.                     Debug.Log("Rewarded Shown!");
    48.                 }
    49.                 catch (ShowFailedException e)
    50.                 {
    51.                     Debug.LogWarning($"Rewarded failed to show: {e.Message}");
    52.                 }
    53.             }
    54.         }
    55.  
     
  17. DeclanMcPartlin

    DeclanMcPartlin

    Unity Technologies

    Joined:
    Nov 19, 2020
    Posts:
    146
    Hey @nobluff67,

    Sounds fine, the function you use to show is set in your code so you are free to choose.

    Thanks again for pointing out this issue!
     
    nobluff67 likes this.