ほぼメモ的な内容。
ライブラリプロジェクトを分割し、かつライブラリAに対し、ライブラリBが
プラグイン的に機能を提供する手段の一つとして検討した際のメモ。
あんまりAndroid自体は関係ない。
インターフェースとかの定義
まずサービス(Androidのサービスではないです)を定義するためにインターフェースとかをきる。
Service.java
package com.hoge;
public interface Service {
void onLoaded();
}
実装クラスを用意
機能提供側で実装クラスを作成
ServiceImpl.java
package com.hoge.impl;
public class ServiceImpl implements Service {
@Override
public void onLoaded() {
Log.d("test", "loaded " + getClass().getName());
}
}
META-INFを用意
src/{buildType}/resources/META-INF/services 以下に
サービス(インターフェース側)のFQNでファイルを生成
例: src/main/resources/META-INF/services/com.hoge.Service
実装クラスを提供するものがライブラリプロジェクトの場合は
これでaarファイルを生成した際にMETA-INFがjarファイルに含まれる。
上記ファイルにロードするクラスを記述する
上で作った src/main/resources/META-INF/services/com.hoge.Service に
ロードするクラスをFQNで記述する
com.hoge.Service
com.hoge.impl.ServiceImpl
クラスのロード
ServiceLoaderを使用してロード。(APIレベル9以降。流石に2.2とか対応している人はいないと信じたい)
以下はとりあえず定義されているやつをぐるぐるロードする例。
ServiceLoader<Service> loader = ServiceLoader.load(Service.class);
for (Service service : loader) { // loaderからはロードされたクラスへのiteratorが取得できる。
service.onLoaded(); // この例ではServiceImplの実体がnewされ渡される
}