Bug 4571 - .jar Library binding doesn't work with GoogleAdMobAdsSdk-6.0.0.jar
Summary: .jar Library binding doesn't work with GoogleAdMobAdsSdk-6.0.0.jar
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: Tools and Addins ()
Version: 4.0
Hardware: PC Mac OS
: High normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2012-04-20 16:04 UTC by Jonathan Pryor
Modified: 2013-11-05 10:07 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Jonathan Pryor 2012-04-20 16:04:03 UTC
The .jar library binding doesn't work with the latest Google AdMob SDK.

1. Update your Android SDK to r19

2. Grab the Extras / Google AdMob Ads SDK package

3. Checkout the monodroid-samples monodroid-4.1-preview branch:

    git clone git@github.com:xamarin/monodroid-samples.git
    cd monodroid-samples
    git checkout -t origin/monodroid-4.1-preview

4. Add the AdMob SDK .jar into the AdMob/AdMob directory:

>   cd AdMob/AdMob
>   cp $ANDROID_SDK_PATH/extras/google/admob_ads_sdk/GoogleAdMobAdsSdk-6.0.0.jar .

5. Update AdMob.csproj to use the new AdMob SDK .jar. Note that the AdMob SDK now requires Android v3.1 or later to build, due to:

> Exception in thread "main" java.lang.NoClassDefFoundError: android/webkit/WebResourceResponse

$ git diff
diff --git a/AdMob/AdMob/AdMob.csproj b/AdMob/AdMob/AdMob.csproj
index 3d42ac6..66d2c21 100644
--- a/AdMob/AdMob/AdMob.csproj
+++ b/AdMob/AdMob/AdMob.csproj
@@ -14,6 +14,7 @@
     <MonoAndroidJavaPrefix>Java</MonoAndroidJavaPrefix>
     <MonoAndroidTransformPrefix>Transforms</MonoAndroidTransformPrefix>
     <AssemblyName>AdMob</AssemblyName>
+    <TargetFrameworkVersion>v3.1</TargetFrameworkVersion>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -57,8 +58,8 @@
   <Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
   <Import Project="$(MSBuildExtensionsPath)\Novell\Xamarin.Android.Bindings.targets" />
   <ItemGroup>
-    <InputJar Include="GoogleAdMobAdsSdk-4.3.1.jar">
-      <Link>Jars\GoogleAdMobAdsSdk-4.3.1.jar</Link>
+    <InputJar Include="GoogleAdMobAdsSdk-6.0.0.jar">
+      <Link>Jars\GoogleAdMobAdsSdk-6.0.0.jar</Link>
     </InputJar>
   </ItemGroup>
 </Project>

6. Build:

    xbuild /verbosity:diagnostic
    ...
> obj/Debug/generated/src/Com.Google.Ads.Internal.C.cs(123,38): error CS0542: `Com.Google.Ads.Internal.C.C': member names cannot be the same as their enclosing type
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(204,80): error CS0102: The type `Com.Google.Ads.Mediation.DismissScreenEventArgs' already contains a definition for `p0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(205,87): error CS0102: The type `Com.Google.Ads.Mediation.DismissScreenEventArgs' already contains a definition for `P0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(218,80): error CS0102: The type `Com.Google.Ads.Mediation.FailedToReceiveAdEventArgs' already contains a definition for `p0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(219,87): error CS0102: The type `Com.Google.Ads.Mediation.FailedToReceiveAdEventArgs' already contains a definition for `P0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(223,60): error CS0102: The type `Com.Google.Ads.Mediation.FailedToReceiveAdEventArgs' already contains a definition for `p1'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(224,67): error CS0102: The type `Com.Google.Ads.Mediation.FailedToReceiveAdEventArgs' already contains a definition for `P1'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(236,80): error CS0102: The type `Com.Google.Ads.Mediation.LeaveApplicationEventArgs' already contains a definition for `p0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(237,87): error CS0102: The type `Com.Google.Ads.Mediation.LeaveApplicationEventArgs' already contains a definition for `P0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(249,80): error CS0102: The type `Com.Google.Ads.Mediation.PresentScreenEventArgs' already contains a definition for `p0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(250,87): error CS0102: The type `Com.Google.Ads.Mediation.PresentScreenEventArgs' already contains a definition for `P0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(262,80): error CS0102: The type `Com.Google.Ads.Mediation.ReceivedAdEventArgs' already contains a definition for `p0'
> obj/Debug/generated/src/Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(263,87): error CS0102: The type `Com.Google.Ads.Mediation.ReceivedAdEventArgs' already contains a definition for `P0'

I'm not sure why some of this code is wrong; it looks right to me:

> public partial class DismissScreenEventArgs : global::System.EventArgs {
> 
>   public DismissScreenEventArgs (global::Com.Google.Ads.Mediation.IMediationInterstitialAdapter p0)
>   {
>     this.p0 = p0;
>   }
> 
>   // this is Com.Google.Ads.Mediation.IMediationInterstitialListener.cs(204,80)
>   // What's the error?
>   global::Com.Google.Ads.Mediation.IMediationInterstitialAdapter p0;
>   public global::Com.Google.Ads.Mediation.IMediationInterstitialAdapter P0 {
>     get { return p0; }
>   }
> }
Comment 1 Atsushi Eno 2012-04-23 04:11:20 UTC
This is expected behavior and you have to edit Metadata.xml to survive this situation. Here is an excerpt from our draft documentation (which should go into binding generator doc, so far it's in multi method listener doc):

----
If there is only one method in the interface, the EventHandler and EventArgs types, when required, are named after the *type* name.
On the other hand, if there are more than one methods, we use the method’s name and possibly cause name conflicts.
We could name AnimatorAnimationEndEventArgs instead of AnimationEndEventArgs, or TransitionStartTransitionEventArgs instead of StartTransitionEventArgs, but they look... weird.

...

This change brought some problem because without type name it will result in errors when more than one listener types have identically-named methods. This *actually* occurs between ISensorListener and ISensorEventListener. (The former is deprecated, so I gave longer argsType name on it.)

To give a way to workaround this issue, I added "argsType" attribute support on interface listener *methods* (argsType used to be supported on interfaces, but it does not work for multi-method listeners).
----

And here this also happens for MediationBannerListener and MediationInterstitialListener.
Hence, you have to edit Metadata.xml to add new mappings:

<metadata>
  <remove-node path="/api/package[@name='com.google.ads']/class[starts-with (@name, 'a')]" />
  <remove-node path="/api/package/class[string-length (@name) = 1]" />
  <remove-node path="/api/package/interface[string-length (@name) = 1]" />
  <remove-node path="/api/package/class[string-length (@name) = 3 and contains (@name, '.')]" />
  <remove-node path="/api/package[@name='com.google.ads']/class[@name='AdActivity']" />
  <remove-node path="/api/package[@name='com.google.ads']/class[@name='InstallReceiver']" />
  <remove-node path="/api/package[@name='com.google.ads.util']" />
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationBannerListener']/method[@name='onDismissScreen']" name="argsType">BannerDismissEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationBannerListener']/method[@name='onFailedToReceiveAd']" name="argsType">BannerFailedToReceiveAdEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationBannerListener']/method[@name='onLeaveApplication']" name="argsType">BannerLeaveApplicationEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationBannerListener']/method[@name='onPresentScreen']" name="argsType">BannerPresentScreenEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationBannerListener']/method[@name='onReceivedAd']" name="argsType">BannerReceivedAdEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationInterstitialListener']/method[@name='onDismissScreen']" name="argsType">InterstitialDismissEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationInterstitialListener']/method[@name='onFailedToReceiveAd']" name="argsType">InterstitialFailedToReceiveAdEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationInterstitialListener']/method[@name='onLeaveApplication']" name="argsType">InterstitialLeaveApplicationEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationInterstitialListener']/method[@name='onPresentScreen']" name="argsType">InterstitialPresentScreenEventArgs</attr>
  <attr path="/api/package[@name='com.google.ads.mediation']/interface[@name='MediationInterstitialListener']/method[@name='onReceivedAd']" name="argsType">InterstitialReceivedAdEventArgs</attr>
</metadata>

Now I'm seeing other couple of mcs errors for lots of:

The name `JavaTypeConverter' does not exist in the current context

but I'm not even sure which is to blame... the source looks fine unless I miss something significant.
Comment 2 Atsushi Eno 2012-04-23 04:25:08 UTC
It seems JavaTypeConverter is kept internal. Why? What is the public alternative that people can take to get mapped managed type from native type? If there is nothing else, we must make it public.
Comment 3 Jonathan Pryor 2012-04-23 16:47:08 UTC
JavaTypeConverter is internal with a horrible API. :-) I'd rather not make it public, and would prefer to make an API more akin to System.Convert and JNIEnv.

Assigning to me to fix the JavaTypeConverter issue.
Comment 4 Jonathan Pryor 2012-04-27 17:42:55 UTC
Fixed code generation in 653477ca by removing JavaTypeConverter use altogether (there were other, existing ways to do what it was being used for).

Fixed AdMob in: https://github.com/xamarin/monodroid-samples/commit/5ed1ef96