“Unable to access asset data: -1” and compressed assets(Android)

I am developing a game called Heroes Of Honesty, a 3D RPG for the Android. Naturally the game is using assets such as geometry files and image\texture files.

One of the image file formats was my own custom file format with the suffix IC(Image Container). I had no problem loading my own custom format files until one day a certain file just wouldn’t load.

To be more specific I was able to open the file from the asset manager but I was unable to read it.
Reading would throw an IOException and print in the LogCat that “Unable to access asset data: -1”.

I used the following java function to read the file:

public byte[] LoadFile (String s)
{
String Free = GetFreeMemory();
int l = FileLength(s);
byte[] c = new byte[l];
int Count = 0;
try {
InputStream s2 = assetManager.open(s);
int tmp = 0;
while ((tmp=s2.read(Buf))>0)
{
for (int i=0; i
c[Count+i] = Buf[i];
Count+=tmp;
}
s2.close();
}
catch (IOException e) {
String Message = e.getMessage();
}
return c;
}

Specifically s2.read would throw the exception.

It turns out that ADT(an eclipse plugin) or the Android SDK packaging function it use would compress some of the files in the assets. When a file is compressed you cannot read it the way I did in ‘LoadFile’.

One solution is to change the suffix of the file from my own custom suffix to a known suffix that doesn’t get compressed, for instance, .jpg. But this isn’t optimal and opens a room for all sort of confusing bugs.

The command that is used to pack the assets is called “aapt.exe” and is found under the Android SDK inside the platform-tools folder.
It turns out there is a flag you can use with this command that would specify not to compress files with a specific file extension.

This flag is ‘-0’ and it should be used as ‘-0 IC’ in my case.
All you need to do is make sure ADT calls aapt with this flag…

However, this is not very simple. Eclipse doesn’t provide you a way to add flags for the packaging.

You can edit XML build files from within the Android SDK to add this flag, or you can do the slightly ugly thing I did which is to replace aapt.exe with your own program which calls the original aapt.exe but adds the -0 flag if necessary.

Assuming you rename aapt.exe into aapt2.exe and you specify the correct absolute path, the following C# program does exactly that:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
namespace aaptSharp
{
class Program
{
static void Main(string[] args)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "D:\\DevelopTools\\Android\\android-sdk\\platform-tools\\aapt2.exe";
if (args.Length>0)
{
startInfo.Arguments = args[0]+" ";
for (uint i = 1; i < args.Length; i++)
{
if (args[i]=="-I")
if (args[0] == "p" || args[0] == "package")
startInfo.Arguments += "-0 IC -0 tmx ";
startInfo.Arguments += args[i] + " ";
}
TextWriter tw = new StreamWriter("tmp.txt", true);
tw.WriteLine(startInfo.Arguments);
tw.Close();
}
Process.Start(startInfo).WaitForExit();
}
}
}

Edit: You need to add ‘WaitForExit’ in the C# application otherwise when ADT use aapt it will sometime fail(and sometime not).