Question

I have files in res/raw that I would like to open like this:

AssetFileDescriptor afd = getResources().openRawResourcesFd();

This allows for, e.g., getting the definitive file size via afd.getLength(), which InputStream.available() does not promise, even if it seems to generally work.

However, when I try this it fails:

java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed

These are just small text files. What's the problem?

Was it helpful?

Solution

aapt compress most resources as part of the build process. According to this article which quotes the aapt source, the exceptions are:

/* these formats are already compressed, or don't compress well */
static const char* kNoCompressExt[] = {
    ".jpg", ".jpeg", ".png", ".gif",
    ".wav", ".mp2", ".mp3", ".ogg", ".aac",
    ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
    ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
    ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
    ".amr", ".awb", ".wma", ".wmv"
};

So one way to get around this problem is to spoof aapt by renaming your files with one of those extensions.

That may not seem very satisfactory. If instead you want to add an extension to the list of exceptions, you can edit [sdk]/tools/ant/build.xml. Search the file for nocompress:

        <aapt executable="${aapt}"
                command="package"
                versioncode="${version.code}"
                versionname="${version.name}"
                debug="${build.is.packaging.debug}"
                manifest="${out.manifest.abs.file}"
                assets="${asset.absolute.dir}"
                androidjar="${project.target.android.jar}"
                apkfolder="${out.absolute.dir}"
                nocrunch="${build.packaging.nocrunch}"
                resourcefilename="${resource.package.file.name}"
                resourcefilter="${aapt.resource.filter}"
                libraryResFolderPathRefid="project.library.res.folder.path"
                libraryPackagesRefid="project.library.packages"
                libraryRFileRefid="project.library.bin.r.file.path"
                previousBuildType="${build.last.target}"
                buildType="${build.target}"
                ignoreAssets="${aapt.ignore.assets}">
            <res path="${out.res.absolute.dir}" />
            <res path="${resource.absolute.dir}" />
            <nocompress extension="txt"/>
            <!-- <nocompress /> forces no compression on any files in assets or res/raw -->
            <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
        </aapt>   

The comments at the bottom are self-explanatory. I inserted the exception for txt. Notice you can also turn off compression all together.

Alternately, create a special extension:

<nocompress extension="nocomp"> 

And rename your files, e.g., whatever.txt.nocomp. This way you can leave the compression on for everything except particular files.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top