2012年5月9日水曜日

ProGuard が勝手にコンストラクタを削除した件

難読化ツールと言うくらいなので、てっきり難読化だけするのかと思いきや、
ProGuard さんは不要(と判断した)メソッドやフィールドの削除も行います。

・・・ということを、本日知りました(汗

そもそも、なんで本日知ったかというと、
android.view.View を派生した ColorPickerView というクラスを作成していたのですが、
ProGuard を使うと、以下のような Exception が発生することに気づきました。

android.view.InflateException: Binary XML file line #110: Error inflating class jp.xxx.yyy.zzz..ColorPickerView

layout フォルダにあるレイアウトファイル (XMLファイル) に、
自作したColorPickerView を記述していたのですが、
こんなクラスはないよ、と言いがかりつけらています。

ProGuard を使わないと、言いがかりはつけられません。

なんで・・・?と調べていたところ、
ProGurad の削除機能でコンストラクタが削除されていることに気づいた、というわけです。


ProGuard をよく知らずに使っていた自分が悪いと言えば悪いんですが、
そんな危ない機能はデフォルトでオフにしておいたほうがいいんじゃないですかね。
(自分だけの非にはしたくない気分です)

ProGuard が生成するテキスト・ファイルのなかに、usage.txt というファイルがあるのですが、
このファイルには、ProGuard によって削除されたメソッドやフィールドが記録されます。

まあ、こんなテキスト・ファイルの意味なんかも分かってなかったんですが、
この中に、自作の ColorPickerView のコンストラクが含まれていて、

「おれのコンストラクタが削除されてるーーー」 

となったわけです。


で、回避策ですが、

元々、以下のような 3 つのコンストラクタがあったので、

package jp.xxx.yyy.zzz;

public class ColorPickerView extends View {

public ColorPickerView(Context c) {
super(c);
}

public ColorPickerView(Context c, AttributeSet attrs) {
super(c, attrs);
}

public ColorPickerView(Context c, AttributeSet attrs, int defStyle) {
super(c, attrs, defStyle);
}

(省略)

}


proguard.cfg に以下の記述を追加しました。

-keep public class  jp.xxx.yyy.zzz..ColorPickerView  {
    public <init>(android.content.Context);
    public <init>(android.content.Context,android.util.AttributeSet);
    public <init>(android.content.Context,android.util.AttributeSet,int);
}

これでコンストラクタは 3 つとも削除されなくなりました。

<init> はコンストラクタを指しています。

詳細は、本家の Usage でもご参照下さい。

本家の Usage - http://proguard.sourceforge.net/index.html#manual/usage.html