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 10
The 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 |