Androidでパスワード付きzipを生成する

Java Zipユーティリティークラス (Hishidama's Java Zip class)のhmzip16.jarをdarty hackする必要がある。

hmzip16.jarはAndroidで使うことができない

ダウンロードしてきたjarをそのまま使おうとすると java.lang.VerifyErrorが発生する。このExceptionは実行しようとしているクラスファイル(バイトコード)がおかしい時に発生するらしい。
仕方ないので、jarを展開してEclipse/ADTにソースをインポートしてみると、InfoZIP_Native.javaでシンタックスエラーが出ていた。Androidでは用意されていないメソッド(java.io.File#canExecute())が使われているのが原因ということか。

仕方ないのでdarty hackする

  1. 前述のjarをダウンロードしてきて、アーカイブを展開。
  2. *.classを削除
  3. InfoZIP_Native.javaを開き、120行目あたりの if (f.canExecute()) とやっているブロックをコメントアウトし、コンパイル

修正済みのソースとjarの配布

修正済みのソースとjarをAndroid用Zipユーティリティクラス - terurou memoに置いておきました。前述の修正と共に、ソースのエンコーディングをCP932からUTF-8に変えておきました。
ライセンスはオリジナルのhmzip16.jarに従います。

サンプルコード

オンメモリでzipを生成するサンプルをやっつけで書いた。

byte[] bytes;

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
ZipOutputStream zipStream = new ZipOutputStream(byteStream, "UTF-8");
try {
    zipStream.setPassword("password".getBytes("UTF-8"));
    zipStream.putNextEntry(new ZipEntry("foo.txt"));
    zipStream.write("ほげほげ".getBytes("UTF-8"));
    zipStream.finish();
    bytes = byteStream.toByteArray();
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
    throw new RuntimeException(e); //FIXME
} catch (IOException e) {
    e.printStackTrace();
    throw new RuntimeException(e); //FIXME
} finally {
    try {
        zipStream.close();
    } catch (IOException e) {
    }
}

// 以下、bytesをごにょごにょ