Android Tutorial FirebaseAdMob and User Consent

Status
Not open for further replies.
Use instead: AdsHelper extends FirebaseAdMob2 / Google Mobile Ads v20.0+

More information: https://developers.google.com/admob/android/eu-consent
By default, AdMob serves personalized ads.
With the new GDPR law, publishers (you) need to request consent before the private data can be used to serve personalized ads to EU users.

The main steps are:

1. Check the current consent state, usually in the starter service.
2. If the consent state is unknown and the user is from the EU (or his location is unknown) then show the consent form.

SS-2018-05-23_15.56.06.png


This step must be done from an Activity.

3. Show non-personalized or personalized ads based on the consent state and location.

The limit on 12 providers was removed. Make sure to use FirebaseAdMob v1.55+.

Note that the Google consent form will only work if there are 12 or less ad technology providers. There are 200 by default so you need to change it in your AdMob console:
Blocking Controls - EU USER CONSENT tab:


SS-2018-05-23_16.09.16.png



Testing

In order to test the behavior you can can add your device as a test device and set whether the location should be treated as coming from the EU:
B4X:
consent.AddTestDevice("D4AC977CA12D122C4563730CC762C302") 'check the unfiltered logs for the device id after calling RequestInfoUpdate
consent.SetDebugGeography(True) 'True = EU, False = Non-EU

You can set the consent state yourself and it will be saved automatically by setting the ConsentState property. This can be useful for debugging and to allow the user to change the previously selected option.

Starter service code:

B4X:
Sub Service_Create
   consent.Initialize("consent")
   consent.AddTestDevice("D4AC977CA12D122C4563730CC762C302")
   consent.SetDebugGeography(True) 'comment for regular operation
   consent.RequestInfoUpdate(Array("pub-144444444"))
   Wait For consent_InfoUpdated (Success As Boolean)
   If Success = False Then
       Log($"Error getting consent state: ${LastException}"$)
   End If
   Log($"Consent state: ${consent.ConsentState}"$)
   Log("EU: " & consent.IsRequestLocationInEeaOrUnknown)
   Do While IsPaused(Main)
       Sleep(100)
   Loop
   CallSubDelayed(Main, "ConsentStateAvailable")
End Sub

Main activity code:

B4X:
'show the consent form if needed
Sub ConsentStateAvailable
   Dim consent As ConsentManager = Starter.consent
   If consent.ConsentState = consent.STATE_UNKNOWN And consent.IsRequestLocationInEeaOrUnknown Then
       'Set last parameter to False if you don't want to show the "pay for ad-free" option.
       'Change privacy policy URL.
       consent.ShowConsentForm("https://www.mysite.com/privacy.html", True, True, True)
       Wait For Consent_FormResult (Success As Boolean, UserPrefersAdFreeOption As Boolean)
       If Success Then
           Log($"Consent form result: ${consent.ConsentState}, AdFree: ${UserPrefersAdFreeOption}"$)
       Else
           Log($"Error: ${LastException}"$)
       End If
   End If
   LoadAd
End Sub

'load ads:
Sub LoadAd
   Dim builder As AdRequestBuilder
   builder.Initialize
   Dim consent As ConsentManager = Starter.consent
   If consent.IsRequestLocationInEeaOrUnknown Then
       If consent.ConsentState = consent.STATE_NON_PERSONALIZED Then
           builder.NonPersonalizedAds
       Else if consent.ConsentState = consent.STATE_UNKNOWN Then
           Return
       End If
   End If
   builder.AddTestDevice("D4AC977CA12D122C4563730CC762C302")
   adview1.LoadAdWithBuilder(builder)
End Sub

Ad free option

If the user selects this option then the ConsentState will be kept UNKNOWN and UserPrefersAdFreeOption will be true (nothing else happens).


Dependencies: FirebaseAdmob v1.50+ (https://www.b4x.com/android/forum/threads/updates-to-internal-libraries.59340/#post-590564)
 
Last edited:

sorex

Expert
Licensed User
Then this is absurd. Why would anyone decrease the number of providers and decrease their income.

I doubt using admob without mediation shows anything else than admob banners.

They probably are the market leader in web/mobile marketing so I doubt you'll lose much (if any) when you only select 12 extra.
 

Filippo

Expert
Licensed User
Hi,
does this option have to be implemented in the app settings?
You can change your choice anytime for App Name in the app settings.
 

sorex

Expert
Licensed User
My guess is that they had enough work to make all their web apps GDPR proof so the next step will be adding limitation to their admob backend to prevent ad feeding to those that didn't have the consent sdk implemented.
 

Computersmith64

Well-Known Member
Licensed User
I doubt using admob without mediation shows anything else than admob banners.

They probably are the market leader in web/mobile marketing so I doubt you'll lose much (if any) when you only select 12 extra.

That might be the case for banners, but it isn't for interstitials in my apps. If you want to find out for sure which providers your revenue is coming from, go to your AdSense (not AdMob) account, then click on Performance Reports->Advanced Reports->Ad Networks. You will get a list showing you the revenue from all the ad networks serving ads in your apps. In my case, the top 11 non-Google providers account for about 10% of my revenue.

- Colin.
 
Last edited:

SMOOTSARA

Active Member
Licensed User
Hello guys :)

I sometimes encounter this error (pic1)

and my cod is :

B4X:
'load ads:
Sub Load_Ad

    AdRequestBuilder1.Initialize

    Log("consent.IsRequestLocationIn Eea Or Unknown ==> "&consent.IsRequestLocationInEeaOrUnknown)

    If consent.IsRequestLocationInEeaOrUnknown Then
        If consent.ConsentState = consent.STATE_NON_PERSONALIZED Then
            AdRequestBuilder1.NonPersonalizedAds
        Else if consent.ConsentState = consent.STATE_UNKNOWN Then
            Return
        End If
    End If
   
    RewardedVideoAd_1.LoadAdWithBuilder(CodeModule.Ad_unit_ID,AdRequestBuilder1)

End Sub
 

Attachments

  • 1.PNG
    1.PNG
    111.4 KB · Views: 278
  • 2.PNG
    2.PNG
    60.2 KB · Views: 254

Computersmith64

Well-Known Member
Licensed User
Hello guys :)

I sometimes encounter this error (pic1)

and my cod is :

B4X:
'load ads:
Sub Load_Ad

    AdRequestBuilder1.Initialize

    Log("consent.IsRequestLocationIn Eea Or Unknown ==> "&consent.IsRequestLocationInEeaOrUnknown)

    If consent.IsRequestLocationInEeaOrUnknown Then
        If consent.ConsentState = consent.STATE_NON_PERSONALIZED Then
            AdRequestBuilder1.NonPersonalizedAds
        Else if consent.ConsentState = consent.STATE_UNKNOWN Then
            Return
        End If
    End If
  
    RewardedVideoAd_1.LoadAdWithBuilder(CodeModule.Ad_unit_ID,AdRequestBuilder1)

End Sub
It looks like your consent object is uninitialized. Where are you declaring it?

- Colin.
 

Computersmith64

Well-Known Member
Licensed User
Try declaring it in your Starter service.

- Colin.
Or if you leave it declared in your activity, check that it's initialized in your Activity_Resume & if it's not, then re-initialize it. If you do this though, you will also have to call getConsent again, otherwise when you do your check of consent.ConsentState it will not contain a valid value.

Your best option is to declare it in the Starter service - then you only have to initialize & call getConsent once, plus you won't have to check the initialization state of it (assuming you aren't calling ExitApplication anywhere).

- Colin.
 

eps

Expert
Licensed User
Well that was painful!

I needed to go to here : https://adexchanger.com/online-adve...-will-limit-publishers-to-12-ad-tech-vendors/

and here : https://stackoverflow.com/questions...rm-can-be-used-with-custom-provider-selection

To understand and find the items I needed to update to get Rewarded Ads working.

The annoying thing is that the Demo Rewarded Ad worked but then I needed to bolt on a whole set of consents and forms and options and settings and and and..! Oh well, at least it's all clear now... ;)

I'll try and put together an 'idiots' guide to all of this, but of course it changes quite significantly..
 

eps

Expert
Licensed User
Actually.... Can we not avoid having to request permission to show Rewarded Ads? Golf Clash didn't ask me if I minded getting Rewarded Ads.... I guess they're using a different service?
 

Gunther

Active Member
Licensed User
Hello,

I am getting a "FirebaseAuthRegistrar is not an found". I am not using this lib but the necessary Manifest settings are done for Firebase.

Manifest part: it doesn't make a difference if FirebaseAuth.FirebaseAuth is enabled or not.

Nevertheless no Consent Form is displayed.

B4X:
'
' ############# Google Play Services and Ads and Firebase ################
'
' Google Play Services Base - Always required when using Google Play Services or Firebase:
CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)
'
' Firebase - Always required when using Firebase
CreateResourceFromFile(Macro, FirebaseAnalytics.Firebase)
'
' Firebase Notifications / Push messages
'CreateResourceFromFile(Macro, FirebaseNotifications.FirebaseNotifications)
'
' Firebase Analytics
CreateResourceFromFile(Macro, FirebaseAnalytics.FirebaseAnalytics)
'
' Firebase Ads
CreateResourceFromFile(Macro, FirebaseAdMob.FirebaseAds)
'
' Firebase Auth
'CreateResourceFromFile(Macro, FirebaseAuth.FirebaseAuth)
'
' #######################################################################
'


In the Starter Service
B4X:
    consent.Initialize("consent")
    LogColor("***Request state!*** ",  4287889619)
    consent.AddTestDevice("557E8FB9CEF9419114223BE9E601FB61") ' my ID
    consent.SetDebugGeography(True) 'comment for regular operation
'    consent.RequestInfoUpdate(Array("pub-144444444"))
    consent.RequestInfoUpdate(Array("pub-xxxxxxxxxxxxxxxxxx"))
    LogColor("***Request done!*** ",  4287889619)
    Wait For consent_InfoUpdated (Success As Boolean)
    If Success = False Then
        Log($"Error getting consent state: ${LastException}"$)
    End If
    LogColor($"Consent state: ${consent.ConsentState}"$,  4287889619)
    LogColor("EU: " & consent.IsRequestLocationInEeaOrUnknown, 4287889619)
  
    Do While IsPaused(Main)
        Sleep(100)
    Loop
  
   CallSubDelayed(Main, "ConsentStateAvailable")

So, it tells me:

This request is sent from a test device.
Consent state: UNKNOWN
EU: true

which is ok so far.

B4X:
Class com.google.firebase.auth.FirebaseAuthRegistrar is not an found.
java.lang.ClassNotFoundException: com.google.firebase.auth.FirebaseAuthRegistrar
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:453)
    at java.lang.Class.forName(Class.java:378)
    at com.google.firebase.components.ComponentDiscovery.instantiate(com.google.firebase:firebase-common@@16.0.4:78)
    at com.google.firebase.components.ComponentDiscovery.discover(com.google.firebase:firebase-common@@16.0.4:71)
    at com.google.firebase.FirebaseApp.<init>(com.google.firebase:firebase-common@@16.0.4:532)
    at com.google.firebase.FirebaseApp.initializeApp(com.google.firebase:firebase-common@@16.0.4:355)
    at com.google.firebase.FirebaseApp.initializeApp(com.google.firebase:firebase-common@@16.0.4:324)
    at com.google.firebase.FirebaseApp.initializeApp(com.google.firebase:firebase-common@@16.0.4:310)
    at com.google.firebase.provider.FirebaseInitProvider.onCreate(com.google.firebase:firebase-common@@16.0.4:53)
    at android.content.ContentProvider.attachInfo(ContentProvider.java:1927)
    at android.content.ContentProvider.attachInfo(ContentProvider.java:1902)
    at com.google.firebase.provider.FirebaseInitProvider.attachInfo(com.google.firebase:firebase-common@@16.0.4:47)
    at android.app.ActivityThread.installProvider(ActivityThread.java:6572)
    at android.app.ActivityThread.installContentProviders(ActivityThread.java:6127)
    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6037)
    at android.app.ActivityThread.-wrap1(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1764)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6938)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.firebase.auth.FirebaseAuthRegistrar" on path: DexPathList[[zip file "/data/app/twinnypoints.gg.goilsoft.de-wrnOsIWW084ssHTR3bLaUw==/base.apk"],nativeLibraryDirectories=[/data/app/twinnypoints.gg.goilsoft.de-wrnOsIWW084ssHTR3bLaUw==/lib/arm64, /system/lib64, /vendor/lib64]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    ... 24 more
Class com.google.firebase.analytics.connector.internal.AnalyticsConnectorRegistrar is not an found.
java.lang.ClassNotFoundException: com.google.firebase.analytics.connector.internal.AnalyticsConnectorRegistrar
    at java.lang.Class.classForName(Native Method)
    at java.lang.Class.forName(Class.java:453)
    at java.lang.Class.forName(Class.java:378)
    at com.google.firebase.components.ComponentDiscovery.instantiate(com.google.firebase:firebase-common@@16.0.4:78)
    at com.google.firebase.components.ComponentDiscovery.discover(com.google.firebase:firebase-common@@16.0.4:71)
    at com.google.firebase.FirebaseApp.<init>(com.google.firebase:firebase-common@@16.0.4:532)
    at com.google.firebase.FirebaseApp.initializeApp(com.google.firebase:firebase-common@@16.0.4:355)
    at com.google.firebase.FirebaseApp.initializeApp(com.google.firebase:firebase-common@@16.0.4:324)
 
Status
Not open for further replies.
Top