3/7/2013 - I updated the blog post so everything should be current and relevant as of today. This was long overdue, sorry.
For instant gratification try downloading the Xamarin sample project. However this will most likely yield an outdated version of the ActionBarSherlock library.
Today I will explain how to bind the ActionBarSherlock Java library so that it can be used with Mono for Android. ActionBar compatibility is important since over 90% of Android users are still running a pre 3.0 platform. It's a luxury Java programmers have enjoyed for awhile now, which can finally be shared with fellow C# programmers.
The required steps are listed below:
Build the ActionBarSherlock Zip
- First, if necessary, download and install the latest version of Eclipse along with the ADT Plugin.
- Next, download the latest version of ActionBarSherlock. After the download finishes extract the library folder from archive.
- Rename the library folder to actionbarsherlock. In this tutorial, the library folder has been renamed/moved to c:\downloads\actionbarsherlock.
- Start Eclipse and create a new workspace. In this tutorial, I created a workspace located at c:\projects\actionbarsherlock.
- Begin creating a new Android project by clicking File -> New -> Other -> Android -> Android Project From Existing Code. Click Next.
- In the "Root Directory" field, browse to c:\downloads\actionbarsherlock. Check the "Copy projects into workspace" field. Click Finish.
- Click Project -> Clean and wait for Eclipse to finish building the project. Exit Eclipse after the build is complete. If you encounter any compile errors ensure that you are targetting Java 6+.
- Open Windows Explorer, and browse to c:\projects\actionbarsherlock\actionbarsherlock. Select the bin, assets, and res folders and add them to a new Zip file. Name the file actionbarsherlock.zip.
- Now browse to c:\projects\actionbarsherlock\actionbarsherlock\libs and locate the file android-support-v4.jar. No action is required yet, but remember this file location for future use.
- Later, both the actionbarsherlock.zip and android-support-v4.jar files will be copied into Visual Studio.
Create the Binding Library
- Open Visual Studio and create a new JAR Bindings Library project (click File -> New -> Project -> Mono for Android -> Java Bindings Library). Name the project ActionBarSherlockBinding and click OK.
- Click Project -> ActionBarSherlockBinding Properties and change the Target API level to 14+.
- Add a reference to the Mono.Android.Support.v4 binding library by clicking Project -> Add Reference and switching to the .NET tab. Select the Mono.Android.Support.v4 library and click OK.
- Now copy the actionbarsherlock.zip and android-support-v4.jar files (from the previous section) into the Jars folder of the ActionBarSherlockBinding project in Visual Studio.
- In the properties pane, right click on the the actionbarsherlock.zip file and change the Build Action to "LibraryProjectZip". Next, right click on the android-support-v4.jar file and change the Build Action to "ReferenceJar".
- Open the Metadata.xml file located under the the Transforms folder and replace all of its contents with the XML code below. Save and close the file when finished.
<metadata> <!-- Don't bind internal packages/classes --> <remove-node path="/api/package[starts-with(@name, 'com.actionbarsherlock.internal')]" /> <!-- Normalize the API, forced to use underscore to avoid name conflicts --> <attr path="/api/package[@name='android.support.v4.app']" name="managedName">Android.Support.V4.App</attr> <attr path="/api/package[@name='com.actionbarsherlock']" name="managedName">ActionBar_Sherlock</attr> <attr path="/api/package[@name='com.actionbarsherlock.app']" name="managedName">ActionBar_Sherlock.App</attr> <attr path="/api/package[@name='com.actionbarsherlock.view']" name="managedName">ActionBar_Sherlock.View</attr> <attr path="/api/package[@name='com.actionbarsherlock.widget']" name="managedName">ActionBar_Sherlock.Widget</attr> </metadata>
Note: Additional documentation regarding this step can be found here. Lines 6-11 are trivial but line 4 is important.
- Build the solution and verify that there are no errors. There will probably be some warnings but it should still build successfully.
Reference the Binding Library
- In Visual Studio, add a new Android Application project to the existing solution (click File -> Add -> New Project -> Mono for Android -> Android Application). Name the project ActionBarSherlockDemo and click OK.
- Click Project -> ActionBarSherlockDemo Properties and change the Target API level to 14+.
- Add a reference to the binding library by clicking Project -> Add Reference and switching to the Projects tab. Select the ActionBarSherlockBinding project and click OK.
- Also add a reference to the Mono.Android.Support.v4 binding library from the .NET tab of the Add Reference dialog.
- Rebuild the solution and verify that there are no errors.
Extend the SherlockActivity Class
- Open Activity1.cs and change it so that it inherits from the ActionBar_Sherlock.App.SherlockActivity class. Documentation for the ActionBarSherlock library is more or less equivalent to the native ActionBar API.
- Items can be added to the ActionBar by creating a menu resource and overriding the OnCreateOptionsMenu method.
- Generate the AndroidManifest.xml and then edit it and set the SDK and theme like this:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly"> <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14" /> <application android:theme="@style/Theme.Sherlock" /> </manifest>
- Rebuild the solution, deploy to the emulator or device, and congratulations, you're finished!
By Request - An ActionBar Tab Example
This is a quick and dirty example of ActionBar tabs with Mono for Android using ActionBarSherlock. This code is only intended as a demonstration of basic concepts. Please refer to the official Android ActionBar documentation for best practices and for a more complete example.
using System; using Android.OS; using Android.Views; using ActivityAttribute = Android.App.ActivityAttribute; using ActionBarNavigationMode = Android.App.ActionBarNavigationMode; using Android.Support.V4.App; using ActionBar_Sherlock.App; using Tab = ActionBar_Sherlock.App.ActionBar.Tab; namespace ActionBarSherlockDemo { [Activity(Label = "Tab Activity", MainLauncher = true)] public class TabActivity : SherlockFragmentActivity, ActionBar_Sherlock.App.ActionBar.ITabListener { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); SupportActionBar.NavigationMode = (int)ActionBarNavigationMode.Tabs; SupportActionBar.SetDisplayShowTitleEnabled(true); Tab tab = SupportActionBar.NewTab(); tab.SetTag("TAB1"); tab.SetText("TAB 1"); tab.SetTabListener(this); SupportActionBar.AddTab(tab); tab = SupportActionBar.NewTab(); tab.SetTag("TAB2"); tab.SetText("TAB 2"); tab.SetTabListener(this); SupportActionBar.AddTab(tab); } public void OnTabSelected(Tab tab, Android.Support.V4.App.FragmentTransaction ft) { string tag = tab.Tag.ToString(); Fragment f = SupportFragmentManager.FindFragmentByTag(tag); if (f != null) { ft.Show(f); return; } if (tag == "TAB1") f = new TestFragment1(); else if (tag == "TAB2") f = new TestFragment2(); ft.Add(Resource.Id.fragmentPlaceholder, f, tag); } public void OnTabUnselected(Tab tab, Android.Support.V4.App.FragmentTransaction ft) { string tag = tab.Tag.ToString(); Fragment f = SupportFragmentManager.FindFragmentByTag(tag); if (f != null) { ft.Hide(f); return; } } public void OnTabReselected(Tab tab, Android.Support.V4.App.FragmentTransaction ft) { //Do nothing } } public class TestFragment1 : Fragment { public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { return inflater.Inflate(Resource.Layout.test1, container, false); } } public class TestFragment2 : Fragment { public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { return inflater.Inflate(Resource.Layout.test2, container, false); } } }
Thank you. I've tried to do this a while back but unfortunately didn't get far and have much time. Can't wait to try this now.
ReplyDeleteI hope it helps!
ReplyDeleteCraig, Were you able to get Tabs working using this implementation? Was able to get the action bar up and running thanks to your blog, but having some trouble with Tabs.
ReplyDeleteThanks
Matt
Oh I didn't try the tabs. I'll have to check into that.
ReplyDeleteI briefly looked into ActionBar Tabs. It looks like the Xamarin's JAR Binding project has a bug in it - is not creating some required classes/methods such as the ActionBar_Sherlock.App.ActionBar.Tab.setTabListener method and the ActionBar_Sherlock.App.ActionBar.ITabListener interface. Sigh... This makes me nervous... I'll file a bug with Xamarin, and will look for a potential work around.
ReplyDeleteThanks Craig for looking into that...I was running into the same issues. I appreciate your work and I will also look for a workaround.
DeleteCraig, saw this in the binding documentation. http://docs.xamarin.com/android/tutorials/Binding_a_Java_Library_%28.jar%29#Limitations
DeleteI don't really understand why this works yet, but try deleting this line from metadata.xml in the binding project:
Delete<remove-node path="/api/package[@name='android.support.v4.app']"/>
Also add a reference to Mono.Android.Support.v4 (in the .NET tab of the Add Reference dialog) for the JAR binding project.
Credit to DFX / Dan for discovering this solution!
I will update the blog in the next few days along with updated source code. I haven't fully tested a tabs sample yet so I can't guarantee it will work, but at first glance it appears that the missing classes are present now.
Craig, That seemed to get me access to ITabListener until I try to compile then I get the error "The type name 'ITabListener' does not exist in the type 'ActionBar_Sherlock.App.ActionBar' " But it does now appear in intellisence.
DeleteJust had to remove the reference to the binding project and re-add it. Thanks!!!
DeleteJust wanted to thank you for this wonderful work, its making my life a lot easier! Please do keep us posted on the bugs.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi,
ReplyDeletethanks to your help I was able to implement SherlockActionBar & Holo theme in my app, I have only one problem, visual studio and Resharper not recognize classes of the java binding project, so I can't use the intellisense & always see red highlighted code in that activities.
http://www.image-share.com/ijpg-1680-30.html
Any idea for solve this problem?
Hmmm... That's strange. Intellisense is working for me with the classes from the Java binding project with Visual Studio 2010. I am not using ReSharper though so I'm not sure how that might impact things.
Deletemate, this is bloody awesome. i never would have worked this out by myself.
ReplyDeleteThanks.
DeleteHey Craig, good work on figuring this out. Not easy stuff.
ReplyDeleteHave you had any luck getting ABS + maps plugin going in monodroid 4.2.5?
We managed to get it going in 4.2.4 following this technique, just recompile the actionbarsherlock jar with the extra map activity baked in.
However with the fixes in 4.2.5, this method of getting ABS in doesnt work anymore.
The Xamarin examples (https://github.com/xamarin/monodroid-samples) have a working demo using LibraryProjectZip, however trying to recompile the zip with maps support hasn't worked for us so far.
Mono seems to have a problem once the maps component is added, however it's pretty silent as to what that problem is.
Got it :D Turns out the library zip file doesn't actually have a folder at the root level (zip file -> assets, bin, res), it was just the way it was being extracted. Fixing that up, now have a working binding with maps support :D
ReplyDeleteChris, Would it be possible to walk me through how you managed to include the ABS maps plugin. I have tried several time to include the maps plugin with no luck.
DeleteThanks
It would be nice if you could share how you managed to get maps working.
DeleteGlad you got it working. I'll have to check out the 4.2.5 sample project you pointed me to.
ReplyDelete(Thanks for pointing that out to me)
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHey Dan, honestly I'm not sure whether tabs are working or not. There was an issue before where some classes were not being generated (see earlier comments) but we were able to find a workaround. After the missing classes starting generating I just assumed it was fixed and didn't actually test it. My fault...
ReplyDeleteSo it may very well be that it is still broken. I think I read in the Mono forums that someone else was also having trouble with tabs even though they were able to generate the missing classes. I haven't had a project that required tabs yet. Unfortunately I currently don't have time to look further into this problem but will keep it in the back of my mind. Thanks.
I'm still a bit confused. The Xamarin guys have said that the ActionBarSherlock sample should generate the required classes (i.e. the Fragment stuff) but unfortunately things still seem to be awry. I wonder if they will fix it sometime this week.
ReplyDeleteYea I noticed that the Xamarin guy said it was fixed too, but when I tried the Xamarin method the classes were still not being generated. Maybe I did something wrong? I know if you fall back to the method in this post that the classes will being generated I'm unsure whether they actually work when the code is ran. Hope that clarifies a little.
ReplyDeleteAh it just seems that you have to add the actual v4 support dll to the binding project. Then you should be able to reference all classes (although MonoDevelop won't actually provide completion/IntelliSense).
DeleteI just tried a rather in-depth example and it seems to have worked out quite well!
Had some time to check into this. I can also confirm that the newest version of the Xamarin ActionBarSherlock sample project is working correctly now. As Taylor mentioned, it looks like a reference was added to the V4 Support library in both the binding project and the Android app project. Also the V4 Support Jar file was added to the Android app project with Build Action = "AndroidJavaLibrary". If a reference to V4 Support library is not added to both projects it will cause an error.
ReplyDeleteHi Craig,
ReplyDeleteI'm running into a problem that the sample doesn't run on Android 2.2 devices. It can't find the com.actionbarsherlock.R$stylable class. I think this is due to a problem in the extra generation pass you specified for the .csproj file.
I'm going to try to fix this myself, but if you have a good idea of what is causing the failure, please let me know :-)
Try running this sample on 2.2 and see if it works. https://github.com/xamarin/monodroid-samples/tree/master/ActionBarSherlock.
ReplyDeleteThat is the officially supported way to use Mono for Android now and doesn't require modify the .csproj file. I still haven't had a chance to update my blog with the new information.
Not sure if Xamarin has any actual documentation on this either. Last I checked the documentation was still missing. The most important part is that there is a ZIP file containing all the resources and java code, and the build action for the ZIP file must be LibraryProjectZip. You can steal the ZIP file from the sample project and copy it into your own project once you figure things out.
You also need android-support-v4.jar and references to Mono.Android.Support.V4 in both projects.
Let me know if that helps any.
i meant to say "that is the offically supported way to use ActionBar Sherlock." Brain is tired.
ReplyDeleteanyone ever get tabs working? I'm just now trying this for the first time and having some issues.
ReplyDeletenevermind i got tabs working
ReplyDeletePlease can you post up information on how you got tabs working on the latest MonoDroid 4.2.5+ ?
ReplyDeleteIntellisense seems to be missing for Com.Actionbarsherlock.* too in MonoDevelop :(
I added some over simplified ActionBar tab code to the bottom of the post. Let me know if that helps. You just need to add in your own layout files.
ReplyDeleteI got this working for 50%. I want to know how your main layout looks like. Because when I press on the other tab nothing changes.
DeleteThanks in advance.
I meant the ActionBar Tab Example.
DeleteI have problems with ActionShareProvider, i cant add a menu with share action.
ReplyDeleteAnybody help me
I spent the last couple of hours trying to build a JAR binding library for ActionbarSherlock. Ran into problems and found this page. Maybe someone could tell me what I'm doing wrong. Whenever I build it I get type or namespace does not exist for FloatKeyframeSet and IntKeyframeSet. I went into the library, made those classes both public and that fixed that problem. Now I had a whole bunch of other errors. No one else seems to have encountered this. Any ideas?
ReplyDeleteI have the same problem :(
DeleteI should add that I am using Visual Studio 2012 for my project.
ReplyDeleteOK, fixed it. Forgot to add the remove-node to Metadata.xml.
ReplyDeletei tested now mono for android and i have used your source code. But on Android 2.2 i have this error message: Java.Lang.NoClassDefFoundError: com.actionbarsherlock.R$styleable
ReplyDeleteI have used your example for Android 2.2, but it doesn't work, too.
@Craig can you help me, please?
I have updated the blog so that the information is current/correct as of today. Please see if that helps any. Thanks.
Deletethanke you for updating your block. Now it works at Android 2.2!
DeleteThanks Craig - top man. I don;t suppose you know what we need to do in order to get ABS working with MapActivitys? @Christopher Fraser above alluded to it, but doesn't spell out what needs to be done.
ReplyDeleteMany thanks
I've never actually tried this myself. Sorry I'm very busy with a project deadline and don't have enough time to look into this in depth at the moment. I think though that you will need to somehow bind the SherlockMapActivity.java file which is included in an extra plugin that can be found here:
Deletehttps://github.com/JakeWharton/ActionBarSherlock-Plugin-Maps/
It may be that you can just toss the SherlockMapActivity.java file into the com.actionbarsherlock.app package in the ActionBarSherlock java project prior to building and creating your ZIP file.
Then of course you will need to inherit from the SherlockMapActivity class in your C# code.
Let me know if that works. Thanks.
Actually, what I said above may work, but upon reading the documentation it looks like a MapFragment class was released in V2 of the Google Maps Android API. So it looks like it might be wiser to use the MapFragment class and implement the map in a fragment vs an activity. If you implement the map in a fragment then I don't think any extra, special steps would be required. That is what I would recommend. Use the support library so that the fragments are backwards compatible.
DeleteOh nevermind, MapFragment is not implemented yet by Xamarin. Hopefully this will be a feature included in a future release.
DeleteThanks for your help Craig - I'll look at implementing a map in a fragment and avoid the mess. Cheers
ReplyDeleteThese links may be helpful:
Deletehttps://github.com/xamarin/monodroid-samples/blob/master/MapsAndLocationDemo_v2/README.md
http://blog.neteril.org/blog/2012/12/10/using-the-new-google-maps-with-mono-for-android/
Yep great - got it working by munging the two monodroid Gmap v2 and actionbarsherlock samples - using MapFragment and SherlockFragmentActivity. Nice one fella
ReplyDeleteFollowing the example on this post, I'd like to use ActionBarNavigationMode.List instead of ActionBarNavigationMode.Tabs. When I do this, I see the small triangle next to the title, but clicking it doesn't bring down the list. Is there anything else I need to do?
ReplyDeleteI've never tried ActoinBarNavigationMode.List before so I'm not completely sure. In theory it should work; I've done a lot of other stuff with ActionBarSherlock and so far everything has worked for me.
Deletecraig
ReplyDeleteHere is another database that is compatible with Mono:
http://www.kellermansoftware.com/p-43-ninja-net-database-pro.aspx
Thank you for the great post but it doesn't work with latest tools.
ReplyDeleteI am using latest Xamarin Android 4.6.06000 and ABS 4.3.1
While I do not get any errors when compiling the binding library,I am getting these errors:
Error 34 The type name 'ITabListener' does not exist in the type 'ActionBar_Sherlock.App.ActionBar' F:\Work\Projects\Xamarin\ActionBarSherlock\Build\TestApp\TestApp\Activity1.cs 15 91 TestApp
Error 33 The type or namespace name 'SherlockFragmentActivity' could not be found (are you missing a using directive or an assembly reference?) F:\Work\Projects\Xamarin\ActionBarSherlock\Build\TestApp\TestApp\Activity1.cs 15 32 TestApp
Using the latest tools, it doesn't work
DeleteI created the binding library successfully with no error.
After adding it as reference to the test app, trying to change the Activity1 base class to ActionBar_Sherlock.App.SherlockActivity gives a compilation error:
Error 2 The type or namespace name 'ActionBar_Sherlock' could not be found (are you missing a using directive or an assembly reference?) F:\Work\Projects\Xamarin\ActionBarSherlock\Build\ActionBarSherlockBindings\TestApp\Activity1.cs 13 30 TestApp
If I'm able to I'll try to look into this later today. It should be working - I'm using this technique pretty frequently and haven't run into any issues, and I usually upgrade Xamarin Android as soon as new stable versions are available.
DeleteSorry Craig, this is so weird.
DeleteI just got back to trying this after few hours and now everything works.
I opened it in Xamarin Studio and it compiled OK. Same with Visual Studio, works OK.
Not sure what happened initially in Visual Studio, but it was very weird.
It's the same project.
Many thanks again for this post!
I must say that I am also having problems using Xamarin 4.6.0600 and ABS 4.3.1. Everything works fine but namespaces and classes cannot be found in Visual Studio 2012, but the build itself does not fail and I can also deploy the app.
DeleteI must say that I have the same problem with Xamarin 4.6.0600 and ABS 4.3.1 using Visual Studio 2012. I tried your instructions as well as the monodroid sample and everything builds without problems but when I try to integrate e.g. SherlockFragmentActivity or the ActionBar_Sherlock namespace neither can be found. Also when I use the object browser on the reference no namespaces are shown.
DeleteThe strange thing is that I can build and deploy the app without problems but all the sherlock namespaces and classes are marked red, thus developing is not really possible.
I just noticed that referencing the built dll instead of the project seems to work now =)
Deletehave you used ABS with MvvmCross?
ReplyDeleteno i haven't sorry
DeleteYou are creating a Xamarin Android project with Level 14.
ReplyDeleteHow to use ABS binding when targeting Android 2?
It depends on what you mean by target. There is a minVersion and a targetVersion that you can declare in your AndroidManifest File:
ReplyDelete<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" />
There is also property in the build settings called "Minimum Android to target" which is different. "Minimum Android to target" must be at least Android 4.0 (it's a requirement of the ABS library).
However this doesn't prevent you from running on older devices, you just need to change the minSdkVersion to "2" in your AndroidManifest.xml file. I usually leave my targetSdkVersion="17" since I'm always testing everything with Jellybean.
oh and you just have to be careful, since you are compiling with android 4.0 code you have to be sure that you don't rely on 4.0 features when supporting older devices. You can still use those newer features but only conditionally - you have to have an IF statement that checks the user's Android version to determine whether or not you can use the newer features
DeleteHi,
ReplyDeletewhen I try to compile the VS solution, the build fail with the following error:
Error 1 The "CreateLibraryResourceArchive" task failed unexpectedly.
Ionic.Zip.ZipException: Jars\actionbarsherlock.zip is not a valid zip file ---> System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at Ionic.Zip.ZipFile.ReadCentralDirectory(ZipFile zf)
at Ionic.Zip.ZipFile.ReadIntoInstance(ZipFile zf)
at Ionic.Zip.ZipFile._InitInstance(String zipFileName, TextWriter statusMessageWriter)
at Ionic.Zip.ZipFile..ctor(String fileName)
--- End of inner exception stack trace ---
at Ionic.Zip.ZipFile..ctor(String fileName)
at Xamarin.Android.Tasks.CreateLibraryResourceArchive.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.d__20.MoveNext() ActionBarSherlockBinding
It seems something about the zip, but I have followed your instruction. Can you help me please?
Hi.
ReplyDeleteThanks for the nice walkthrough.
But i get the following error:
This project does not contain any activities marked MainLauncher. It has been deployed to the device, but no activity will be launched.
I have MainLauncher = true in the top of one of my Activities. HAve tried with the samples from github with the same result.
Something you now anything about?
Hi Casper, I haven't seen that error before. Sorry.
ReplyDeleteHi Craig, Is Xamarin actionbarsherlock for custom tabhost is working. if u are having source can u send to me .sriram1237@gmail.com
ReplyDeleteHi Craig, Thank you for the post!
ReplyDeleteWhen I try to compile I am getting these errors:
Error 4 Invalid resource directory name: "crunch". C:\Projects\ActionBarSherlockBinding\ActionBarSherlockDemo\aapt.exe ActionBarSherlockDemo
Can you help me please?
Also, encountered the above error. Can you please help me? :-( Thank you.
ReplyDelete