B4A Library Admob Interstitial Library

Because the old Admob SDK will be deprecated in August, I have written a library for interstitials using the new Google Play Services library. You'll need to follow initial steps noted in Erel's post for the Admob banner library to get your app ready for this library.

The new library should be compatible with your old code with the exception of a change to the AdFailedToReceive event. It should be declared in your app as follows.

B4X:
Sub mwadi_AdFailedToLoad (ErrorMessage As String)
    Log("failed to load ad: " & ErrorMessage)
End Sub

This new library also supports a new event that triggers when the user closes an ad. You can use this event to queue a new ad to load or run other code.

B4X:
Sub mwadi_AdClosed
    mwAdInterstitial.LoadAd
End Sub

The new library is called mwAdmobInterstitial2. I added the 2 to the end of the name so you can preserve your old library in case it is needed with other apps. The new library and example app for the library is attached at the end of this post.

============================================
Below is for the old version (not using Google Play Services)
============================================
I was able to put together a library to display interstitial ads from Admob. You'll need to create an interstitial ad unit in Admob and use it with the initialization process.

Make sure the following is added to your AndroidManifest.xml.
B4X:
AddApplicationText(<activity android:name="com.google.ads.AdActivity"
          android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>)

Here is code from the included sample app that shows how to use the library. Because the interstitial is running as an activity, I'm not able to raise an event in B4A when it is dismissed. Instead, you can check the status in Activity_Resume as shown in the code below.

A good practice would be to initialize the ad in Activity_Create, and then show the ad later when desired. This will allow the ad to fully load while other processes are taking place allowing you to show the ad immediately.

This is a beta version and the first library I've shared, so please report any problems.

NOTE: There is a bug in older versions of the SDK that causes a crash on some devices when you try to load the interstitial. Make sure you download an updated SDK from Admob.

1.1 Update: Fixed a bug in the library code used to raise the AdFailedToLoad event. Separated out the LoadAd routine from the Initialize routine. This allows you to load a new ad after an ad has been dismissed without re-initializing the class.

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim mwAdInterstitial As mwAdmobInterstitial
    Dim Button1 As Button
    Dim Label2 As Label
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    mwAdInterstitial.Initialize("mwadi","INSERT_YOUR_AD_UNIT_ID")
    mwAdInterstitial.LoadAd
    Activity.LoadLayout("1")
    Label2.Text="Attempting to load ad...  Please wait."
End Sub

Sub Activity_Resume
    If mwAdInterstitial.Status=mwAdInterstitial.Status_Dismissed Then Label2.Text="Ad dismissed by user."
End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub mwadi_AdLoaded
    Log("ad loaded")
    Label2.Text="Ad loaded - Click Show Ad to Display"

End Sub

Sub mwadi_AdFailedToLoad (ErrorCode As String)
    Label2.Text="Ad failed to load with error code: " & ErrorCode
    Log("failed to load ad: " & ErrorCode)
End Sub

Sub Button1_Click
    If mwAdInterstitial.Status=mwAdInterstitial.Status_AdReadyToShow Then mwAdInterstitial.Show
    If mwAdInterstitial.Status=mwAdInterstitial.Status_Dismissed Then
        Label2.Text="Attempting to load ad...  Please wait."
        mwAdInterstitial.LoadAd
    End If
End Sub
 

Attachments

  • interstitial.png
    interstitial.png
    86 KB · Views: 771
  • AdmobInterstitial1.1.zip
    10.6 KB · Views: 1,046
  • AdmobInterstitialPlayServices.zip
    11.5 KB · Views: 1,054
Last edited:

Jaames

Active Member
Licensed User
Longtime User
You can easily set them to use the same jar. Just open the XML file of one of them. Scroll to the bottom and change the DependsOn node.

Thats true if we use old version Admob wrapper, but how to solve this if we use new one v2 which depends On google-play-services?
 

palmzac

Active Member
Licensed User
Longtime User
Thats true if we use old version Admob wrapper, but how to solve this if we use new one v2 which depends On google-play-services?

I have a same problem.

B4X:
PackageAdded: package:mobi.mindware.admob
main_globals (java line: 406)
main_globals (java line: 406)
java.lang.NoClassDefFoundError: mobi.mindware.admob.interstitial.AdmobInterstitialsAds
    at mobi.mindware.admob.main._globals(main.java:406)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:173)
    at mobi.mindware.admob.main.initializeGlobals(main.java:263)
    at mobi.mindware.admob.main.afterFirstLayout(main.java:95)
    at mobi.mindware.admob.main.access$100(main.java:16)
    at mobi.mindware.admob.main$WaitForLayout.run(main.java:76)
    at android.os.Handler.handleCallback(Handler.java)
    at android.os.Handler.dispatchMessage(Handler.java)
    at android.os.Looper.loop(Looper.java)
    at android.app.ActivityThread.main(ActivityThread.java)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
    at dalvik.system.NativeStart.main(Native Method)
java.lang.NoClassDefFoundError: mobi.mindware.admob.interstitial.AdmobInterstitialsAds
    at mobi.mindware.admob.main._globals(main.java:406)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:173)
    at mobi.mindware.admob.main.initializeGlobals(main.java:263)
    at mobi.mindware.admob.main.afterFirstLayout(main.java:95)
    at mobi.mindware.admob.main.access$100(main.java:16)
    at mobi.mindware.admob.main$WaitForLayout.run(main.java:76)
    at android.os.Handler.handleCallback(Handler.java)
    at android.os.Handler.dispatchMessage(Handler.java)
    at android.os.Looper.loop(Looper.java)
    at android.app.ActivityThread.main(ActivityThread.java)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
    at dalvik.system.NativeStart.main(Native Method)
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = true **
 

jalle007

Active Member
Licensed User
Longtime User
I am unable to combine banner and Interstitials ads in one app.

I have referenced Admob 2.0 and mwAdInterstitial too.

the error is like this
B4X:
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lcom/google/ads/AdRequest$ErrorCode;

andy ideas, please?
 

palmzac

Active Member
Licensed User
Longtime User
Hi Jack,

It is a great library. Would you release a new version for Google Play Service ? Thanks ! ;)
 

jalle007

Active Member
Licensed User
Longtime User
Great. I know already wich one it is. because mwAdmobInterstitial use GoogleAdMobAdsSdk-6.4.1.jar and the admob wrapper for b4a use GoogleAdMobAdsSdk.jar and i have the both in my library folder... to me,mwAdmobInterstitial.jar & admob.jar should call the same GoogleAdMobAdsSdk 6.4.1 jar file (i mean with the same filename) :(

I believe that this applies to Admob 1.40 that used Android SDK.
I really nee to implement Admob 2.0 (gms) with this library.

Tried many things, like altering xml files to point so same jar file but w/o success

Anyone have solution for this ?
 

jalle007

Active Member
Licensed User
Longtime User
Hi Jack

here is what I have

Admob.xml
<version>2.0</version>
<dependsOn>google-play-services</dependsOn>

mwAdmobInterstitial.xml
<version>1.1</version>
<author>Jack Cole</author>
<dependsOn>GoogleAdMobAdsSdk-6.4.1</dependsOn>

#AdditionalRes: c:\Users\jalle\Downloads\_Android\adt-bundle-windows-x86_64-20130917\sdk\extras\google\google_play_services\libproject\google-play-services_lib\res, com.google.android.gms

I guess those are 3 files that interfere each other.
Tried removing <dependsOn> form mwAdmobInterstitial file but that did not help

B4X:
java.lang.NoClassDefFoundError: mobi.mindware.admob.interstitial.AdmobInterstitialsAds
  at com.jalle.pacdroid.main._globals(main.java:692)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:511)
  at anywheresoftware.b4a.BA.raiseEvent2(BA.java:174)
  at com.jalle.pacdroid.main.initializeGlobals(main.java:263)
  at com.jalle.pacdroid.main.afterFirstLayout(main.java:95)
  at com.jalle.pacdroid.main.access$100(main.java:16)
  at com.jalle.pacdroid.main$WaitForLayout.run(main.java:76)
  at android.os.Handler.handleCallback(Handler.java:615)
  at android.os.Handler.dispatchMessage(Handler.java:92)
  at android.os.Looper.loop(Looper.java:137)
  at android.app.ActivityThread.main(ActivityThread.java:4905)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:511)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
  at dalvik.system.NativeStart.main(Native Method)

if I remove tag from Admob.xml get error also.
Do you have working sample of this setup ?
 

DavideV

Active Member
Licensed User
Longtime User
Hi Jack, thk you for your lib, i added it to my existing app and worked immediately.
Just a question, is there a way to center the ad in the activity? To be more clear, in my phone (4.3inch) the ad is almost centered in the screen as in your example in first post.
In my tablet (7inch) is displayed on top-left angle.
Maybe it depends on wich ad is received at that moment?
It would be nice to have it always centered into the activity.
Thank you again.
DavideV
 

tuhatinhvn

Active Member
Licensed User
Longtime User
can not use with admob 2.0
admob 1.4 will be removed from 1/8/2014

remove depends on tag:
B4X:
main_globals (java line: 331)

java.lang.NoClassDefFoundError: mobi.mindware.admob.interstitial.AdmobInterstitialsAds
    at mobi.mindware.admob.main._globals(main.java:331)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:174)
    at mobi.mindware.admob.main.initializeGlobals(main.java:263)
    at mobi.mindware.admob.main.afterFirstLayout(main.java:95)
    at mobi.mindware.admob.main.access$100(main.java:16)
    at mobi.mindware.admob.main$WaitForLayout.run(main.java:76)
    at android.os.Handler.handleCallback(Handler.java:587)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:130)
    at android.app.ActivityThread.main(ActivityThread.java:3683)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:880)

    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:638)
    at dalvik.system.NativeStart.main(Native Method)

with depends on
B4X:
Parsing code.                          0.00
Compiling code.                        0.03
Compiling layouts code.                0.00
Generating R file.                      0.67
Compiling generated Java code.          1.06
Convert byte code - optimized dex.      Error
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lcom/google/ads/AdRequest$ErrorCode;
    at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
    at com.android.dx.dex.file.DexFile.add(DexFile.java:163)
    at com.android.dx.command.dexer.Main.processClass(Main.java:486)
    at com.android.dx.command.dexer.Main.processFileBytes(Main.java:455)
    at com.android.dx.command.dexer.Main.access$400(Main.java:67)
    at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:394)
    at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:245)
    at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:131)
    at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:109)
    at com.android.dx.command.dexer.Main.processOne(Main.java:418)
    at com.android.dx.command.dexer.Main.processAllFiles(Main.java:329)
    at com.android.dx.command.dexer.Main.run(Main.java:206)
    at com.android.dx.command.dexer.Main.main(Main.java:174)
    at com.android.dx.command.Main.main(Main.java:91)
1 error; aborting
    Optimized dexer failed. Switching to Standard dexer.
 

Inman

Well-Known Member
Licensed User
Longtime User
can not use with admob 2.0
admob 1.4 will be removed from 1/8/2014

That is true. This library is working very well as of now. But on August 1st, Google will stop supporting Admob SDKs under 2.0. That means there won't be any ads from then on.

Jack, I hope you will soon make it compatible with Admob 2.x that uses google-play-services instead of GoogleAdMobAdsSdk-6.4.1.
 

rafaelbr20

Member
Licensed User
Longtime User
Hi Jack,

Thanks so much for this library ! I´m using it on my projects !

I´m waiting for a release also, because i can´t combine your library with Admob 2.x !

I hope you can release a new version !!

Rafael

I Got this error when compiling

B4X:
Convert byte code - optimized dex.      Error
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lcom/google/ads/AdRequest$ErrorCode;
    at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:122)
    at com.android.dx.dex.file.DexFile.add(DexFile.java:161)
    at com.android.dx.command.dexer.Main.processClass(Main.java:685)
    at com.android.dx.command.dexer.Main.processFileBytes(Main.java:634)
    at com.android.dx.command.dexer.Main.access$600(Main.java:78)
    at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:572)
    at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
    at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
    at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
    at com.android.dx.command.dexer.Main.processOne(Main.java:596)
    at com.android.dx.command.dexer.Main.processAllFiles(Main.java:498)
    at com.android.dx.command.dexer.Main.runMonoDex(Main.java:264)
    at com.android.dx.command.dexer.Main.run(Main.java:230)
    at com.android.dx.command.dexer.Main.main(Main.java:199)
    at com.android.dx.command.Main.main(Main.java:103)
1 error; aborting
    Optimized dexer failed. Switching to Standard dexer.
 
Top