Create a new Android Application project.
Set the Compile, Minimum, and Target Android versions. For this example, use Gingerbread API Level 10 (v2.3) for both Compile
and Target
. Set the Minimum
to 10 or lower.
Reload the project, as requested by the prompt.
Add the Google Play Services (Gingerbread) component from the Xamarin component store.
The component will add four new references to the project:
If you build the project at this step, for example via Build -> Build $(MSBuildProjectName), the build will fail.
Example error text:
Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Holo.ActionBar'.
With diagnostic build output enabled, the Output -> Build window shows that these errors happen during the aapt packaging step:
aapt.exe package -f -m -M C:\Users\Brendan\AppData\Local\Temp\rkpjcydb.cqo\AndroidManifest.xml -J C:\Users\Brendan\AppData\Local\Temp\rkpjcydb.cqo --custom-package androidapplication1.androidapplication1 -F C:\Users\Brendan\AppData\Local\Temp\rkpjcydb.cqo\resources.apk.bk -S obj\Release\res -S C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.1\lib\android\15\content\google-play-services/libproject/google-play-services_lib\res -S C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.1\lib\android\19.0.1\content\support/v7/appcompat\res -S C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.1\lib\android\19.0.1\content\support/v7/mediarouter\res -I C:\Users\Brendan\AppData\Local\Android\android-sdk\platforms\android-10\android.jar --auto-add-overlay
The errors arise from the appcompat/res/values-v14 folder because that folder contains style definitions that depend on the Holo theme. The Holo theme was first introduced in Ice Cream Sandwich (Android v4.0, API 14), and is not available on Gingerbread (Android v2.3, API 10).
To stop the Holo theme problems, we can simply delete the appcompat/res/values-v14 folder located at:
$(MSBuildProjectDirectory)..\Components\googleplayservicesgingerbread-15.0.1\lib\android\19.0.1\content\support\v7\appcompat\res\values-v14
On the second build attempt, we get some new errors:
Example error text:
… googleplayservicesgingerbread-15.0.1\lib\android\19.0.1\content\support\v7\appcompat\res\values-v11\styles_base.xml(27): error : Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Holo.ProgressBar.Horizontal'.
These errors are essentially the same as the values-v14 errors, but this time they are caused by the values-v11 folder. So let's delete that folder, and try again.
Example error text:
… googleplayservicesgingerbread-15.0.1\lib\android\19.0.1\content\support\v7\mediarouter\res\layout\mr_media_route_controller_dialog.xml(18): error : No resource identifier found for attribute 'showDividers' in package 'android'
… googleplayservicesgingerbread-15.0.1\lib\android\19.0.1\content\support\v7\mediarouter\res\layout-v11\mr_media_route_controller_dialog.xml(18): error : No resource found that matches the given name (at 'divider' with value '?android:attr/dividerHorizontal').
… googleplayservicesgingerbread-15.0.1\lib\android\19.0.1\content\support\v7\mediarouter\res\layout-v17\mr_media_route_list_item.xml(23): error : No resource identifier found for attribute 'paddingStart' in package 'android'
Again the build fails due to resource errors during the aapt packaging step, but this time the problems are in the MediaRouter
library. The incompatible resources are:
dividerHorizontal (API 11)showDividers (API 11)paddingStart (API 17)We can again delete the unneeded layout-v11 and layout-v14 folders. That will leave just one error from the layout folder.
layout/mr_media_route_controller_dialog.xml: "No resource found for attribute 'showDividers'"Now we hit an interesting case. The mediarouter
developers included the same divider and showDividers attributes in the default mr_media_route_controller_dialog.xml layout as in the v11 version, but these attributes aren't available on API 10. As expected, this causes an error during aapt bundling. What is the correct way to fix this? Is it safe simply to delete these attributes from the layout? We can try a quick experiment: what happens if you include these attribtues in a layout, compile the app on Android 3.0 (API 11), and run it on a Gingerbread (API 10) device? The result is that the app ignores the attributes. So yes, deleting the attributes is a sensible fix:
--- a/mediarouter/res/layout/mr_media_route_controller_dialog.xml +++ b/mediarouter/res/layout/mr_media_route_controller_dialog.xml @@ -17,9 +17,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:orientation="vertical" - android:divider="?android:attr/dividerHorizontal" - android:showDividers="middle"> + android:orientation="vertical"> <!-- Optional volume slider section. --> <LinearLayout android:id="@+id/media_route_volume_layout" android:layout_width="fill_parent"
attr.xml errorError text:
AAPT : error : In MenuView, unable to find attribute android:preserveIconSpacing
Unfortunately, in this case aapt does not name the file where the problematic android:preserveIconSpacing attribute appears. But that's no problem. A quick grep, findstr, or gci -r | select-string easily finds the line:
appcompat\res\values\attrs.xml:309
<attr name="android:preserveIconSpacing"/>
Again, since this attribute only appears in Ice Cream Sandwich, we'll assume it would be ignored on Gingerbread, and delete the line:
--- a/appcompat/res/values/attrs.xml +++ b/appcompat/res/values/attrs.xml @@ -305,8 +305,6 @@ <attr name="android:windowAnimationStyle"/> <!-- Default disabled icon alpha for each menu item that shows an icon. --> <attr name="android:itemIconDisabledAlpha"/> - <!-- Whether space should be reserved in layout when an icon is missing. --> - <attr name="android:preserveIconSpacing"/> </declare-styleable> <declare-styleable name="ActionMenuView"> <!-- Size of padding on either end of a divider. -->
COMPILETODALVIK : UNEXPECTED TOP-LEVEL error :
java.lang.OutOfMemoryError: Java heap space (TaskId:158)
at com.android.dx.rop.code.RegisterSpecSet.<init>(RegisterSpecSet.java:49) (TaskId:158)
at com.android.dx.rop.code.RegisterSpecSet.mutableCopy(RegisterSpecSet.java:383) (TaskId:158)
As discussed in the Troubleshooting section of the component's Getting Started
page, the fix for this problem is to increase Java's heap size via the JavaMaximumHeapSize property. You can set this directly in the .csproj file, or by using the project property editor: Application -> Advanced Android Build Settings [section] -> Java Max Heap Size.
If 512M isn't enough, you can increase it to 1G or more.
After all of these changes, the project now successfully builds!
One remaining question you might have is: If the Google Play Services (Gingerbread) component is targeted for Gingerbread, why are these steps necessary?
The short answer is that all of the problems are with resources, and these are included directly from Google's original libraries. The Xamarin part of the component is just a thin layer of C# that allows access to the Java classes and methods. This C# binding treats the resources exactly like the original Java classes and methods. Specifically, it only looks at the contents of the .xml resource files at run time. In fact, compiling the appcompat
and mediarouter
libraries in a Java Eclipse Android project produces identical resource errors, and requires the same workarounds.
--max-res-version 10The Android Asset Packaging Tool
aapt includes a --max-res-version option that helps with many of the errors. This technique is quite difficult to use with Xamarin.Android at the moment because there is no MSBuild variable for additional aapt options. Additionally, running aapt by hand from the command line isn't sufficient because the Xamarin.Android MSBuild tasks will re-run aapt regardless of whether it has already been run. There are some plans to make it easier to use --max-res-version in future versions of Xamarin.Android.
To get an idea for how --max-res-version will help, we can return to build attempt 1,
copy the aapt command from the Output -> Build window, add the --max-res-version 10 option, and then run the command from the command line (for example using cmd.exe):
C:\Users\Brendan\AppData\Local\Android\android-sdk\build-tools\17.0.0\aapt.exe package -f -m -M C:\Users\Brendan\AppData\Local\Temp\4cppgmha.k1m\AndroidManifest.xml -J C:\Users\Brendan\AppData\Local\Temp\4cppgmha.k1m --custom-package androidapplication1.androidapplication1 -F C:\Users\Brendan\AppData\Local\Temp\4cppgmha.k1m\resources.apk.bk -S obj\Debug\res -S C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.2\lib\android\15\content\google-play-services/libproject/google-play-services_lib\res -S C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.2\lib\android\19.0.1\content\support/v7/appcompat\res -S C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.2\lib\android\19.0.1\content\support/v7/mediarouter\res -I C:\Users\Brendan\AppData\Local\Android\android-sdk\platforms\android-10\android.jar --auto-add-overlay --max-res-version 10
This produces some output to indicate that aapt is skipping the incompatible resource directories:
max res 10, skipping layout-v11
max res 10, skipping layout-v17
max res 10, skipping layout-v11
max res 10, skipping layout-v14
max res 10, skipping values-v11
max res 10, skipping values-v14
... but it also produces a couple errors:
C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.2\lib\android\19.0.1\content\support\v7\mediarouter\res\layout\mr_media_route_controller_dialog.xml:17: error: No resource identifier found for attribute 'showDividers' in package 'android'
C:\Users\Brendan\Desktop\AndroidApplication1\Components\googleplayservicesgingerbread-15.0.2\lib\android\19.0.1\content\support\v7\mediarouter\res\layout\mr_media_route_controller_dialog.xml:17: error: Error: No resource found that matches the given name (at 'divider' with value '?android:attr/dividerHorizontal').
These are the same showDividers and divider errors in the mediarouter library that we saw at the end of build attempt 3. To resolve these errors, we would again need to delete the problematic attributes from mr_media_route_controller_dialog.xml. After that, we would be back at build attempt 4.
We would again see the In MenuView, unable to find attribute android:preserveIconSpacing
error, and we would again need to fix the error by editing the attrs.xml file.
documentation
When run from the command line with no arguments, aapt outputs some short documentation for the various command line options. For --max-res-version, the corresponding output is:
--max-res-version
ignores versioned resource directories above the given value.
Submit a comment or correction
| 31 Mar 2014 | Add discussion of --max-res-version |
| 11 Mar 2014 | Posted |