Mono for Android: “aapt.exe” exited with code 1

TL;DR

Also available in TL;SO (too long; Stack Overflow) flavor.

Getting this error: "aapt.exe" exited with code 1?

Do you have any files in your Mono for Android solution that are being packaged together with the app (e.g., “AndroidResource” build action)?

If so, make sure they don’t have anything but letters, numbers, periods, and underscores ([a-z0-9_.]) in their names.

Details

I am still getting my feet wet with Mono for Android (MfA) development. One of my first projects was a flashlight app for my Galaxy Nexus that introduced me to a couple Android/MfA development quirks. One concept in app development that I would like to explore is long-running tasks. How do I keep something going after the user has switched off to something else?

Greg Shackles has a new Visual Studio Magazine article on Background Services in MfA on just that topic. He creates a background service for playing an MP3 file using a standard Android service.

In his sample project, he sets up the service to play some Creative Commons Nine Inch Nails music.

I happen to have a good collection of my own Nine Inch Nails music. As I put the code together in my own project, I grabbed one such MP3 file, named “02 1,000,000.mp3”, and added it with the “AndroidResource” Build Action. Unfortunately, hitting Ctrl+Shift+B resulted in a lovely error: "aapt.exe" exited with code 1.

If you go to the Visual Studio output window, you don’t find much else of value.

Fortunately, you can get more verbose output from MSBuild if you ask for it. In the Visual Studio Options, go to “Projects and Solutions” then “Build and Run”. Switch the “MSBuild project build output verbosity” from “Minimal” to “Normal”. After I built the project again, I got a little clearer message: res\raw\02 1,000,000.mp3: Invalid file name: must contain only [a-z0-9_.].

A quick name change to something within the [a-z0-9_.] range and the project built beautifully. While this new sample project is just a horrible version of the baked-in music application, that definitely isn’t the point. It is definitely nice to have some code written about a concept before you find yourself needing it the first time.

Where did that JSON field go? Serializing IHtmlString to JSON.

TL;DR

If your brain consumes Stack Overflow questions better than blog posts, go see “How do I serialize IHtmlString to JSON with Json.NET?” over there.

IHtmlString doesn’t play nicely with JSON serialization

If you have an IHtmlString in your JSON (regardless of arguments against putting raw HTML in JSON), you will probably need to customize the serialization to get the HTML out of that variable. In fact, the serialization will probably be invalid compared to what you expect; it does make sense if you think about how the serialization process works.

Fortunately, putting together a quick Json.NET JsonConverter will make the issue go away.

What you might expect from some object containing an IHtmlString variable named x:

{ x = "some <span>text</span>" }

What default .NET JavaScript serialization and default Json.NET serialization will give you for said object:

{ x = { } }

How to fix it with Json.NET:

public class IHtmlStringConverter : Newtonsoft.Json.JsonConverter {
    public override bool CanConvert(Type objectType) {
        return typeof(IHtmlString).IsAssignableFrom(objectType);
    }
    ...
    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
        IHtmlString source = value as IHtmlString;
        if (source == null) {
            return;
        }
        writer.WriteValue(source.ToString());
    }
}

Background

While working on some random API, we noticed one of our JSON fields went from being a long string containing raw HTML (legacy baggage) to an empty object: SomeFieldWithHtml: {}.

While the API JSON-generating code hadn’t changed, that field was pulled from code shared by our MVC website. It seems that field was converted directly to an IHtmlString to avoid doubly-encoding it in an MVC view. If you ever have the same issue, you can avoid this issue entirely by leaving the source as a string and doing a quick MvcHtmlString.Create(x) on it before sending it to your view/view-model.

Code

For the full source used in this post, including an example MVC project where a controller has action methods to test all the variations here, head over to this post’s GitHub repository.

Performance Stub: getting all subtype items from a list

Performance Stubs

These blog posts are simply times I wanted to identify the fastest method for accomplishing a particular goal. As I write the code, I like to make some light notes of alternatives while driving forward with the first implementation that makes it from my brain to my fingers.

When I get the chance, I can go back and flesh out the two versions and drop them into some basic Stopwatch timing to determine which is better in terms of raw speed. Factoring those results with clarity of code, I have a method I will likely choose the next time I need the same feature.

Goal

Given a particular IEnumerable, find all the elements that are of a particular type (subclass, in this case).

Method 1: Select As, Where Not Null

The as operator with convert between two types with one nice tweak. If the cast cannot happen, it results in null.

In this version, we massage the list by hitting all items with an as cast and then filter out the ones that didn’t cast successfully.

public static IEnumerable<SubSomething> SelectAsWhereNotNull(IEnumerable<Something> source) {
    return source.Select(item => item as SubSomething).Where(item => item != null);
}

Method 2: Where Is, Cast

There is also the is operator. Instead of returning a cast result, it simply returns a boolean for whether the instance can be cast as a given type. From there, we use another Linq extension method: Cast<TResult>.

In this version, we filter the original list to just those that can make the cast successfully, then Cast those items to the final desired type.

public static IEnumerable<SubSomething> WhereIsCast(IEnumerable<Something> source) {
    return source.Where(item => item is SubSomething).Cast<SubSomething>();
}

Test

I built up a list (n=1,000,000) of parent type Something but make every other item a SubSomething (which is a subclass of Something). Then, I run that list through both methods 1000 iterations each.

Results

Clarity

Neither method is particularly difficult to decipher. The Select/Where method takes a few more characters, but not enough to hurt.

Speed

It takes quite a list for these tests to even register with average ticks. That said, there is little gain to be had here over small lists. Once list lengths are sufficiently large, method 1 took the lead.

For n=1,000,000 and 1000 iterations (run on 2.4GHz AMD Phenom 9750 with 8GB RAM)
Average Method
1.0 ticks {IEnumerable<Something>}.Select(item => item as SubSomething).Where(item => item != null)
1.7 ticks {IEnumerable<Something>}.Where(item => item is SubSomething).Cast<SubSomething>()

Performance Testing Framework

The original source for the test framework code evolved from a StackOverflow answer about converting byte arrays to hexadecimal strings. –That code is available in a bitbucket repo. I have adapted it here for these two methods.– That code is available in the framework repo.

Rather than post another repo for each test, I am going to abstract out a testing framework for these posts. That repo will show up soon and I will update this post accordingly.

Update 2013-01-22

I finally refined the testing framework code I was using. While I won’t pretend this code couldn’t use some improvements, feel free to hack away with it. The code is available on GitHub.

To add a new case to an existing test:

  1. Add the new static method (Func<byte[], string>) to /Tests/ConvertByteArrayToHexString/Test.cs.
  2. Add that method’s name to the TestCandidates return value in that same class.
  3. Make sure you are running the input version you want, sentence or text, by toggling the comments in GenerateTestInput in that same class.
  4. Hit F5 and wait for the output (an HTML dump is also generated in the /bin folder).

To add a new test fixture entirely, just write up something that implements IPerformanceTest in that project’s namespace.