Android Question Any news about Native Ads Advanced?

asales

Expert
Licensed User
Longtime User
Hi @Erel
I have several Native Ads Express in my apps and the existing units will stop serving ads on March 1, 2018 (https://developers.google.com/admob/android/native-express).

The new Native Ads Advanced is available now and I can create this Ads (I think the information in page "Native is currently in a closed beta with a limited group of publishers" is out of date), but I don't have a option in FirebaseAdmob library to use it, only NativeExpressAd.

native2.jpg


Any news about when we can get the updated FirebaseAdmob library?

Thanks in advance for your attention about this issue.
 

asales

Expert
Licensed User
Longtime User
Hi @Douglas Farias, please put your code of the LoadNativeAd sub.
I made a few modifications in the sub of Erel (like getCallToAction) and, until now, is works fine to me.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
someone please explain me more because I tested with erel's code but ContentAdLoaded_Event not raise.
Please start a new thread for this.

i m using the same code of Erel (no changes)
There was a bug in the code I posted. It tried to get the image from the logo instead of the images list. I've updated the code.
 
Upvote 0

Douglas Farias

Expert
Licensed User
Longtime User
@Erel
i m using your code and it works fine. thx for this.
with your code its possible to get the events?

B4X:
Sub _AdClosed
End Sub

Sub _ReceiveAd
End Sub

Sub _FailedToReceiveAd (ErrorCode As String)
End Sub

Sub _adopened
End Sub

Sub _PresentScreen
End Sub

the most importante is _FailedToReceiveAd, have a way to get this event with your code?

thx
 
Upvote 0

asales

Expert
Licensed User
Longtime User
If I created more than one native ad, how I can set the "eventName" string in "MyAdListener" class ?
I need to passed the string in Params()? If yes, how I can get the Params() in the Java code?
 
Upvote 0

asales

Expert
Licensed User
Longtime User
Is possible to return a panel from this sub?
I tried to change the code, but I get this error in compile: "incompatible types: ResumableSub cannot be converted to ViewGroup".

My changes are:
B4X:
Sub LoadNativeAd As ResumableSub
    (...)   
    Return pNativeAdView
End Sub

I tried to use this way:
B4X:
Dim pnl As Panel = LoadNativeAd
pContent.AddView(pnl, 0, 0, 100%x, 200dip)
 
Upvote 0

asales

Expert
Licensed User
Longtime User
Thanks! this is the code it works:
B4X:
    Wait for (LoadNativeAd) Complete (Result As Panel)
If Result <> Null Then
   Activity.AddView(Result, 0, 0, 100%x, 200dip)
End If
 
Upvote 0

asales

Expert
Licensed User
Longtime User
I made a few modifications in the @Erel's original code to show the "App Install Ad" instead "Content Ad".

native5.jpg


B4X:
Sub LoadNativeAd
   Dim AdUnitId As String = "ca-app-pub-3940256099942544/2247696110"
   Dim ctxt As JavaObject
   ctxt.InitializeContext
   
   Dim builder As JavaObject
   builder.InitializeNewInstance("com.google.android.gms.ads.AdLoader.Builder", Array(ctxt, AdUnitId))
   
   '*** Code changed
   Dim onAppInstallAdLoadedListener As Object = builder.CreateEventFromUI("com/google/android/gms/ads/formats/NativeAppInstallAd.OnAppInstallAdLoadedListener".Replace("/", "."), _
       "AppInstallAdLoaded", Null)
   builder.RunMethod("forAppInstallAd", Array(onAppInstallAdLoadedListener))
   '*** End Code changed
   
       Dim Listener As JavaObject
   Listener.InitializeNewInstance(Application.PackageName & ".main$MyAdListener", Array("NativeAd"))  'change 'main' with the current activity module name
   builder.RunMethod("withAdListener", Array(Listener))
   
   Dim AdLoader As JavaObject = builder.RunMethod("build", Null)
   Dim AdRequestBuilder As JavaObject
   AdRequestBuilder.InitializeNewInstance("com/google/android/gms/ads/AdRequest.Builder".Replace("/", "."), Null)
   AdLoader.RunMethod("loadAd", Array(AdRequestBuilder.RunMethod("build", Null)))
   
   '*** Code changed
   Wait For AppInstallAdLoaded_Event (MethodName As String, Args() As Object)
   '*** End Code changed
   
   Log("ContentAdLoaded_Event")
   Dim NativeContentAd As JavaObject = Args(0)
   Log(NativeContentAd.RunMethod("getHeadline", Null))
   
   Dim NativeContentAdView As JavaObject
   
   '*** Code changed     
   NativeContentAdView.InitializeNewInstance("com/google/android/gms/ads/formats/NativeAppInstallAdView".Replace("/", "."), _
       Array(ctxt))   
   '*** End Code changed
     
   Dim pNativeAdView As Panel = NativeContentAdView
   
   Dim content As Panel
   content.Initialize("")
   pNativeAdView.AddView(content, 0, 0, 100%x, 300dip)
   
   Dim lbl As Label
   lbl.Initialize("")
   lbl.TextSize = 20
   lbl.TextColor = Colors.Black
   lbl.Text = NativeContentAd.RunMethod("getHeadline", Null)
   content.AddView(lbl, 10dip, 10dip, 300dip, 50dip)
   NativeContentAdView.RunMethod("setHeadlineView", Array(lbl))
   
   Dim lbl2 As Label
   lbl2.Initialize("")
   lbl2.TextColor = Colors.Black
   lbl2.Text = NativeContentAd.RunMethod("getBody", Null)
   content.AddView(lbl2, 10dip, 60dip, 300dip, 50dip)
   NativeContentAdView.RunMethod("setBodyView", Array(lbl2))
   
   '*** Code changed (disable) -> show error: java.lang.RuntimeException: Method: getLogo not found in: com.google.android.gms.internal.zzqh
   Dim logo As JavaObject = NativeContentAd.RunMethod("getIcon", Null)
   If logo.IsInitialized Then
       Dim logoView As Panel
       logoView.Initialize("")
       logoView.Background = logo.RunMethod("getDrawable", Null)
       content.AddView(logoView, 260dip, 100dip, 80dip, 80dip)
       NativeContentAdView.RunMethod("setIconView", Array(logoView))
   End If
   '*** End Code changed
   
   Dim images As List = NativeContentAd.RunMethod("getImages", Null)
   If images.IsInitialized And images.Size > 0 Then
       Log("adding image")
       Dim imgView As Panel
       imgView.Initialize("")
       Dim image As JavaObject = images.Get(0)
       imgView.Background = image.RunMethod("getDrawable", Null)
       content.AddView(imgView, 130dip, 100dip, 100dip, 100dip)
       NativeContentAdView.RunMethod("setImageView", Array(imgView))
   End If
   
   '*** Code changed: new button to action
   Dim btAction As Button
   btAction.Initialize("")
   Dim cd As ColorDrawable
   cd.Initialize(Colors.RGB(65,105,225),3dip)
   btAction.Background = cd
   btAction.Text = NativeContentAd.RunMethod("getCallToAction", Null)
   content.AddView(btAction, 10dip, 120dip, 100dip, 50dip)
   NativeContentAdView.RunMethod("setCallToActionView", Array(btAction))
   
   NativeContentAdView.RunMethod("setNativeAd", Array(NativeContentAd))
   
   Activity.AddView(pNativeAdView, 0, 0, 100%x, 200dip)
End Sub
 
Last edited:
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
For what it's worth, here's my implementation of Native Ads Advanced. I wanted to show 2 ads in place of where I would normally put an interstitial, so modified the example to do that. Also, I add a listener for both content & install ads. The documentation states that if you do that, you will get served with whichever type will give the best yield. I'm sure there are some improvements I can make, so I'll probably go back over it & refine it - but it works for now.

This page is a good resource for details about the fields in the ad types -> https://support.google.com/admob/answer/6240809

This is what my ads look like. I use a layout with the 2 panels & I hide the second one if I only get one ad.

Screenshot_20180227-215824.png


B4X:
Sub LoadNativeAd
    Private adCount As Int = 0
    Private AdUnitId As String = "ca-app-pub-3940256099942544/2247696110"'
    Private ctxt As JavaObject
    Private builder As JavaObject
   
   
    ctxt.InitializeContext
    builder.InitializeNewInstance("com.google.android.gms.ads.AdLoader.Builder", Array(ctxt, AdUnitId))
    Private onAppInstallAdLoadedListener As Object = builder.CreateEventFromUI("com/google/android/gms/ads/formats/NativeAppInstallAd.OnAppInstallAdLoadedListener".Replace("/", "."), _
           "ContentAdLoaded", Null)
    builder.RunMethod("forAppInstallAd", Array(onAppInstallAdLoadedListener))
   
    Private OnContentAdLoadedListener As Object = builder.CreateEventFromUI("com/google/android/gms/ads/formats/NativeContentAd.OnContentAdLoadedListener".Replace("/", "."), _
       "ContentAdLoaded", Null)
    builder.RunMethod("forContentAd", Array(OnContentAdLoadedListener))
   
   
    Private Listener As JavaObject
    Listener.InitializeNewInstance(Application.PackageName & ".main$MyAdListener", Array("NativeAd"))  'change 'main' with the current activity module name
   
    builder.RunMethod("withAdListener", Array(Listener))
   
    Private AdLoader As JavaObject = builder.RunMethod("build", Null)
    Private AdRequestBuilder As JavaObject
    AdRequestBuilder.InitializeNewInstance("com/google/android/gms/ads/AdRequest.Builder".Replace("/", "."), Null)
    AdLoader.RunMethod("loadAds", Array(AdRequestBuilder.RunMethod("build", Null), 2))
    Wait For ContentAdLoaded_Event (MethodName As String, Args() As Object)
    adCount = 1
  
  Private NativeContentAdView As JavaObject
    NativeContentAdView.InitializeNewInstance("com/google/android/gms/ads/formats/NativeContentAdView".Replace("/", "."), _
       Array(ctxt))
    pnlNativeAdView = NativeContentAdView
  
    Private content As Panel
    content.Initialize("")
    Activity.AddView(content, 0, 0, 100%x, 100%y)
    content.LoadLayout("contentad")
    initAdViews
    content.RemoveView
    pnlNativeAdView.AddView(content, 0, 0, 100%x, 100%y)
    NativeContentAdView.RunMethod("setNativeAd", Array(setupAd(Args(0), NativeContentAdView, adCount - 1)))
   
    Do While AdLoader.RunMethod("isLoading", Null)
        Wait For ContentAdLoaded_Event (MethodName As String, Args() As Object)
        adCount = adCount + 1
        NativeContentAdView.RunMethod("setNativeAd", Array(setupAd(Args(0), NativeContentAdView, adCount - 1)))
        Log("Received an Ad")
    Loop
    If adCount = 1 Then adPanel(1).Visible = False
End Sub

Private Sub initAdViews
    Private adPanel() As Panel = Array As Panel(pnlAd, pnlAd2)
    Private adHeadline() As Label = Array As Label(lblAdHeadline, lblAdHeadline2)
    Private adBody() As Label = Array As Label(lblAdBody, lblAdBody2)
    Private adImage() As Panel = Array As Panel(pnlAdImage, pnlAdImage2)
    Private adAction() As Button = Array As Button(btnAdAction, btnAdAction2)
End Sub

Private Sub setupAd(adContent As JavaObject, nativeContentAdView As JavaObject, thisAd As Int) As JavaObject
    adHeadline(thisAd).Text = getTruncatedString(adContent.RunMethod("getHeadline", Null), adHeadline(thisAd))
    adBody(thisAd).Text = adContent.RunMethod("getBody", Null)
    Dim images As List = adContent.RunMethod("getImages", Null)
    If images.IsInitialized And images.Size > 0 Then
        Log("adding image")
        Dim image As JavaObject = images.Get(0)
        Log(image.RunMethod("getScale", Null))
        adImage(thisAd).Background = image.RunMethod("getDrawable", Null)
        nativeContentAdView.RunMethod("setImageView", Array(adImage(thisAd)))
    End If
    Dim cd As ColorDrawable
    cd.Initialize(Colors.RGB(76,190,153),3dip)
    adAction(thisAd).Background = cd
    adAction(thisAd).Text = adContent.RunMethod("getCallToAction", Null)
    nativeContentAdView.RunMethod("setCallToActionView", Array(adAction(thisAd)))
    Return adContent
End Sub

Sub NativeAd_FailedToReceiveAd (ErrorCode As String)
    Log("NativeAd_FailedToReceiveAd: " & ErrorCode)
End Sub

Sub NativeAd_AdOpened
    Log("NativeAd_AdOpened")
End Sub

Sub NativeAd_Receivead
    Log("Ad Received")
    adReady = True
End Sub

Private Sub NativeAd_AdClosed
    adReady = False
End Sub

Private Sub getTruncatedString(text As String, thisLabel As Label) As String
    Private sRetString As String
    Private cvsText As Canvas
    Private fMaxLen As Float
    Private fStringLen As Float
    Dim iCnt As Int
   
    cvsText.Initialize(Activity)
    If cvsText.MeasureStringWidth(text, Typeface.DEFAULT, thisLabel.TextSize) <= (thisLabel.Width) Then Return text
    fMaxLen = thisLabel.Width - cvsText.MeasureStringWidth("ZZZ", Typeface.DEFAULT, thisLabel.TextSize)
    For iCnt = 0 To text.Length - 1
        sRetString = text.SubString2(0, iCnt)
        fStringLen = cvsText.MeasureStringWidth(sRetString, Typeface.DEFAULT, thisLabel.TextSize)
        If fStringLen >= fMaxLen Or (fStringLen = Activity.Width And iCnt = text.Length - 1) Then
            Exit
        End If
    Next
    If iCnt < text.Length - 1 Then sRetString = sRetString & "..."
    Return sRetString
End Sub

#if Java
public static class MyAdListener extends com.google.android.gms.ads.AdListener {
   
   String eventName;
   public MyAdListener(String s) {
       eventName = s.toLowerCase(BA.cul);
   }
   @Override
   public void onAdClosed() {
       processBA.raiseEventFromDifferentThread(null, null, 0, eventName + "_adclosed", false, null);
   }
   @Override
   public void onAdFailedToLoad(int arg0) {
       processBA.raiseEventFromDifferentThread(null, null, 0, eventName + "_failedtoreceivead", false, new Object[] {String.valueOf(arg0)});
   }
   @Override
   public void onAdLeftApplication() {
       processBA.raiseEventFromDifferentThread(null, null, 0, eventName + "_adleftapplication", false, null);
   }
   @Override
   public void onAdOpened() {
       processBA.raiseEventFromDifferentThread(null, null, 0, eventName + "_adopened", false, null);
   }
   @Override
   public void onAdLoaded() {
       processBA.raiseEventFromDifferentThread(null, null, 0, eventName + "_receivead", false, null);
   }
}
#End If

- Colin.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
how do you test this stuff, Colin?

I still don't see the option to select native ads when I want to create a new placement.
 
Upvote 0

asales

Expert
Licensed User
Longtime User
how do you test this stuff, Colin?

I still don't see the option to select native ads when I want to create a new placement.
Did you see only banner, interstitial and reward?
I don't know why, but is not available to everyone.
I received an e-mail that show a deadline to stop serving native express ads on March 1, 2018 to Brazil. I still waiting to confirm this.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
Yes, I only see those 3 on both Android & IOS apps.

I can't remember seeing a mail passing by but it was mentioned on some links in this thread and also on the admob console.

I also asked admob via support (chat was not available then) but never got a reply on it.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
I forgot to mentioned that on one page they mentioned that you had to ask your account manager to enable it and if you don't have one you had to request an account manager via the contact form or so.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
how do you test this stuff, Colin?

I still don't see the option to select native ads when I want to create a new placement.
According to Google (https://support.google.com/admob/answer/6239795) it's still in beta. I started receiving emails back in October asking me to try it - so it seems to be a long beta period. Not sure what the performance will be like because I haven't released the game that I'm trying them in yet.

- Colin.
 
Upvote 0

Computersmith64

Well-Known Member
Licensed User
Longtime User
I forgot to highlight that there are 2 methods you can use to get ads - "loadAd" & "loadAds". If you use loadAd you will get a single ad, but you can request up to 5 ads using loadAds - although there's no guarantee you'll get them all. If you use loadAds, your listener will be fired every time an ad arrives. You can use "isLoading" to check if there are still ads to come.

B4X:
Do While AdLoader.RunMethod("isLoading", Null)
    Wait For ContentAdLoaded_Event (MethodName As String, Args() As Object)
    adCount = adCount + 1
    NativeContentAdView.RunMethod("setNativeAd", Array(setupAd(Args(0), NativeContentAdView, adCount - 1)))
    Log("Received an Ad")
Loop

- Colin.
 
Upvote 0
Top