アプリケーションパッケージ(.apk)中のクラスを列挙してロードする
一つ前のエントリでclasses.dex中のクラス名を列挙できた訳だが、これですぐにクラスがロードできる訳ではない。
通常のJavaアプリケーションではよくある、以下のコードでは、クラスをロードしようとしても失敗するだろう。
- Activity中にて
//スレッドのコンテキストクラスローダを使う ClassLoader loader = Thread.currentThread().getContextClassLoader(); Enumerationenumeration = enumClassNames(this); while (enumeration.hasMoreElements()) { String className = enumeration.nextElement(); //クラスをロードする Class.forName(className, loader); //ClassNotFoundExceptionがスローされる }
ならばどうする?
Contextクラスに属したクラスローダ(Context#getClassLoader()で取得できる)階層には、DexClassLoaderというdex形式ファイル(classes.dex)からクラスをロードできるクラスローダがクラスローダチェインに挿入されているので、ロードにはそれを使う必要がある。
- Activity中にて
//アクティビティから取得できるコンテキストクラスローダを使う ClassLoader loader = this.getClassLoader(); Enumerationenumeration = enumClassNames(this); while (enumeration.hasMoreElements()) { String className = enumeration.nextElement(); Class.forName(className, loader); //OK }
これで、classes.dexからクラス名の一覧を列挙して、好きなクラスをロードしてインスタンスを生成することができるようになった。