Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jar-Binding of ActionBarSherlock for Mono for Android

I'like to bind the jar-library of ActionBarSherlock in my Mono For Android project. I am reverencing to this documentation: http://docs.xamarin.com/android/tutorials/Binding_a_Java_Library_(.jar)

I have successfully bound android-support-v4.jar which is needed by ActionBarSherlock. But when I try to compile actionbarsherlock.jar, it gives me the following error message:

Target ResolveLibraryProjects:
    Skipping target "ResolveLibraryProjects" because it has no inputs.
    Target _ResolveMonoAndroidSdks:
        MonoAndroid Tools: C:\Program Files (x86)\MSBuild\Novell\
        MonoAndroid Framework: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v2.2\;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\
        Android SDK: C:\Program Files (x86)\Android\android-sdk\
        Java SDK: C:\Program Files (x86)\Java\jdk1.6.0_31\
    Target ExportJarToXml:
          SourceJars:
            Jars\actionbarsherlock.jar
          ReferenceJars:
            Jars\android-support-v4.jar
        C:\Program Files (x86)\Java\jdk1.6.0_31\bin\java.exe -jar "C:\Program Files (x86)\MSBuild\Novell\jar2xml.jar" --jar=C:\Users\assrock\Documents\JavaBind\JavaBind\Jars\actionbarsherlock.jar --ref="C:\Program Files (x86)\Android\android-sdk\platforms\android-8\android.jar" --out=C:\Users\assrock\Documents\JavaBind\JavaBind\obj\Release\api.xml --ref=C:\Users\assrock\Documents\JavaBind\JavaBind\Jars\android-support-v4.jar 
        Couldn't load class com/actionbarsherlock/internal/ActionBarSherlockNative$ActionModeCallbackWrapper
        Couldn't load class com/actionbarsherlock/internal/app/ActionBarWrapper$TabWrapper
        Couldn't load class com/actionbarsherlock/internal/app/ActionBarWrapper
        Couldn't load class com/actionbarsherlock/internal/view/ActionProviderWrapper
        Couldn't load class com/actionbarsherlock/internal/view/menu/MenuItemWrapper$1
        Exception in thread "main" java.lang.NoClassDefFoundError: com/actionbarsherlock/R
            at java.lang.Class.getDeclaringClass(Native Method)
            at jar2xml.JavaClass.getConstructorParameterOffset(JavaClass.java:149)
            at jar2xml.JavaClass.appendCtor(JavaClass.java:138)
            at jar2xml.JavaClass.appendToDocument(JavaClass.java:462)
            at jar2xml.JavaPackage.appendToDocument(JavaPackage.java:66)
            at jar2xml.Start.main(Start.java:157)
        Caused by: java.lang.ClassNotFoundException: com.actionbarsherlock.R
            at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
            ... 6 more
C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets(170,5): error MSB6006: "java.exe" exited with code 1.
    Task "JarToXml" execution -- FAILED
    Done building target "ExportJarToXml" in project "C:\Users\assrock\Documents\JavaBind\JavaBind\JavaBind.csproj".-- FAILED
Done building project "C:\Users\assrock\Documents\JavaBind\JavaBind\JavaBind.csproj".-- FAILED
Build FAILED.
Warnings:
C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets(40,11): warning MSB4011: There is a circular reference involving the import of file "c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.Targets". This file may have been imported more than once, or you may have attempted to import the main project file. All except the first instance of this file will be ignored.
Errors:
C:\Users\assrock\Documents\JavaBind\JavaBind\JavaBind.csproj (Build) ->
C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets (ExportJarToXml target) ->
    C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets(170,5): error MSB6006: "java.exe" exited with code 1.
     1 Warning(s)
     1 Error(s)
Time Elapsed 00:00:00.4730270
--------------------- Fertig ---------------------
Build: 1 Fehler, 0 Warnungen

For the android-support-v4.jar I found these xml-files and put them in the Transforms directory:

EnumFields.xml

<enum-field-mappings>
  <mapping jni-class="android/support/v4/app/FragmentActivity$FragmentTag" clr-enum-type="Android.Support.V4.App.FragmentTagType">
    <field  jni-name="Fragment_id"    clr-name="Id"   value="1" />
    <field  jni-name="Fragment_name"  clr-name="Name" value="0" />
    <field  jni-name="Fragment_tag"   clr-name="Tag"  value="2" />
  </mapping>
</enum-field-mappings>

EnumMethods.xml

<enum-method-mappings>
  <mapping jni-class="android/support/v4/app/Fragment$SavedState">
        <method jni-name="writeToParcel"  parameter="p1"    clr-enum-type="Android.OS.ParcelableWriteFlags" />
    <method jni-name="writeToParcel"  parameter="flags" clr-enum-type="Android.OS.ParcelableWriteFlags" />
    </mapping>
</enum-method-mappings>

Metadata.xml

<metadata>
  <remove-node path="/api/package[@name='android.support.v4.app']/class[@name='BackStackState']" />
  <remove-node path="/api/package[@name='android.support.v4.app']/class[@name='FragmentState']" />
  <remove-node path="/api/package[@name='android.support.v4.app']/class[@name='FragmentManagerState']" />
  <remove-node path="/api/package[@name='android.support.v4.widget']/class[@name='CursorAdapter']/implements[@name='android.support.v4.widget.CursorFilter.CursorFilterClient']" />
  <remove-node path="/api/package[@name='android.support.v4.widget']/class[@name='CursorAdapter']/field[@name='mCursorFilter']" />

  <remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
  <!-- FIXME:
        This method is an override of another method in the base types.
        The base method expects JLO, but this method returns Cursor.
        So we somehow have to fill the gap between them.
  -->
  <remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />

  <remove-node path="/api/package[@name='android.support.v4.view.accessibility']/class[@name='AccessibilityNodeInfoCompat.AccessibilityNodeInfoIcsImpl']" />
  <remove-node path="/api/package[@name='android.support.v4.widget']/class[@name='CursorAdapter.ChangeObserver']" />
  <remove-node path="/api/package[@name='android.support.v4.view.accessibility']/class[@name='AccessibilityNodeInfoCompat.AccessibilityNodeInfoIcsImpl']" />
  <remove-node path="/api/package[@name='android.support.v4.view.accessibility']/class[@name='AccessibilityNodeInfoCompat.AccessibilityNodeInfoStubImpl']" />
  <remove-node path="/api/package[@name='android.support.v4.view']/interface[@name='ViewPager.OnAdapterChangeListener']" />

  <attr path="/api/package[@name='android.support.v4.app']/class[@name='LoaderManager']/method[@name='initLoader']/parameter[@name='p2']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
  <attr path="/api/package[@name='android.support.v4.app']/class[@name='LoaderManager']/method[@name='initLoader']/parameter[@name='callback']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
  <attr path="/api/package[@name='android.support.v4.app']/class[@name='LoaderManager']/method[@name='initLoader']" name="return">android.support.v4.content.Loader</attr>
  <attr path="/api/package[@name='android.support.v4.app']/class[@name='LoaderManager']/method[@name='restartLoader']/parameter[@name='p2']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
  <attr path="/api/package[@name='android.support.v4.app']/class[@name='LoaderManager']/method[@name='restartLoader']/parameter[@name='callback']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
  <attr path="/api/package[@name='android.support.v4.app']/class[@name='LoaderManager']/method[@name='restartLoader']" name="return">android.support.v4.content.Loader</attr>
</metadata>
like image 376
Flo Avatar asked May 03 '12 19:05

Flo


3 Answers

ActionBarSherlock includes UI elements, styles, and other things that can't be compiled into a JAR file. There is a note about this on the ActionBarSherlock FAQ.

Q: Why is ActionBarSherlock a library project whereas the original compatibility library is only a .jar?

A: The custom action bar implementation within ActionBarSherlock relies on styles, themes, layouts, and drawables in order to display properly. Due to the limitations of Android and .jar files, this currently can not be accomplished any other way.

Edit: There is some additional information about trying to share resources across library projects in Mono for Android at this link: http://mono-for-android.1047100.n5.nabble.com/Resources-from-a-Library-Project-td4657828.html. Short answer is it doesn't look possible at the moment.

like image 79
Christian Avatar answered Oct 16 '22 10:10

Christian


I believe I have successfully bound ActionBarSherlock in Mono for Android.

You need to package the java files as a JAR file but without the resources and without the R java class files. Before you package the files make sure that you check the box in Android settings that says "Is Library" so that the resource IDs are not created as constants and inlined in your compiled java classes.

Once you have done this you can use the latest version of Mono for Android to bind the JAR file.

Resources need to be copied separately from the JAR file and placed directly in the main android application project. Unfortunately, at the present time there is no way to isolate the resources in a separate library project when using Mono for Android, but I expect that will change soon.

Finally, you need to edit your C-Sharp project file so that it automatically creates a new version of the com.actionbarsherlock.R java class file each time you rebuild. This is required to keep all your resource IDs in sync.

I may have missed a step or two but those are the most important ones.

Please see my blog post for more information and a download link with source code:

http://www.craigsprogramming.com/2012/07/actionbarsherlock-with-mono-for-android.html

like image 40
craigrs84 Avatar answered Oct 16 '22 09:10

craigrs84


This may seem like a sledgehammer approach, but will likely solve your problem...

I would suggest building using Maven, which handles these dependencies much better. You will be able to reference the ActionBarSherlock project in your POM, and MVN will manage the dependancies for you.

I can confirm the original answer as correct as well - there is a limitation to including JAR files that contain layout resources.

like image 1
Booger Avatar answered Oct 16 '22 08:10

Booger