しらいとブログ

ネットで検索してもなかなか出てこないIT情報を独自にまとめています

Android2.2(API8)以前で1MB以上のファイルを埋め込む

Android 2.2 (API 8)以前では一部のファイルを除いてresフォルダ、rawフォルダ、assetsフォルダ全てで1ファイルあたり1MBまでという制限があります。そのため、フォントの埋め込みなどで困ることがあります。

厳密には1MB以上のファイルを埋め込めないのではなく、1MB以上のファイルを圧縮して埋め込むと解凍できなくなるようです。つまり、圧縮せずに埋め込めば1MB以上でも問題ないわけです。

圧縮しないで埋め込む方法を2つ紹介します。

1MB以上でも埋め込めるファイル

まず、以下の拡張子のファイルはデフォルトで圧縮されないようになっています。

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

そのため上記拡張子のファイルは1MBを超えていても何もする必要はありません。

上記拡張子以外のファイルを埋め込む方法を書きます。

方法1.拡張子の偽装

拡張子を上記の圧縮されない拡張子に変えて偽装するだけで圧縮されなくなります。拡張子を変えても問題なく動くのであればこのやり方が一番簡単です。

ただし、読み込み時に拡張子でファイルタイプを判別している場合、拡張子を偽装したせいで正しく読み込めなくなることがあります。この場合はもう一つの方法を使う必要があります。

方法2.build.xmlを修正

AndroidSDKフォルダの"android-sdk\tools\ant\build.xml"を開いて、以下の行を検索します。

<!-- <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 -->

その次の行に

<nocompress extension="xml" />

と書けばxmlファイルが圧縮されなくなります。xmlの部分を他の拡張子に置き換えればその拡張子のファイルが圧縮されなくなります。複数の拡張子を列挙したい場合は次のように書いてください。

<nocompress extension="ttf" />
<nocompress extension="xml" />

このやり方で1MB以上のファイルの拡張子を全部書けば1MB以上のファイルを問題なく埋め込めます。

ちなみに、<nocompress />と書けば全てのファイルが圧縮されなくなると英語で書いてありますが、それをやるとバグでコンパイル出来なくなります。面倒でも拡張子を列挙するしかないです。

それと、このやり方だとbuild.xmlの変更が全てのプロジェクトに反映されてしまいます。その点に注意してください。

プロジェクト毎に設定する方法は一応ありますが、antを使わない人には面倒です。一応やり方を書くと、すでにプロジェクトをantプロジェクトにしているなら、上記build.xmlから必要な部分をコピペして以下のようなcustom_rules.xmlを作り、プロジェクトフォルダに置くだけです。

<?xml version="1.0" encoding="UTF-8"?>
<project name="android_rules" default="debug">
    <target name="-package-resources" depends="-crunch">
        <!-- only package resources if *not* a library project -->
        <do-only-if-not-library elseText="Library project: do not package resources..." >
            <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 /> 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>
        </do-only-if-not-library>
    </target>
</project>

まだantプロジェクトでない場合はantプロジェクトにする必要があります。ただしantプロジェクトにするということは、コンパイルから署名付きapkファイルの作成まで全てantでやる必要があります。IDEが対応していないとかなり面倒なことになります。