3

だから私は、開発者が 'CustomDevice' クラスを追加でき、メインプログラムが既存のコードを編集せずにそれらを自動的に実行する拡張可能な Android アプリケーションを構築したいと考えています。

Service Provider インターフェイスについて読んだことがありますが、それは良い方法だと思いました。

そこで私はそれをテストし、カスタム デバイス クラスが実装することが期待される「ICustomDevice」というインターフェイスを作成しました。

ICustomDevice を実装する「DummyDevice」というクラスを作成しました。

DummyDevice と ICustomDevice はどちらも同じパッケージ "CustomDevicePackage" にあります。

したがって、私のメインプログラムでは、次を実行します。

    ServiceLoader<ICustomDevice> loader = ServiceLoader.load(ICustomDevice.class);
    Iterator<ICustomDevice> devices = loader.iterator();
    System.out.println("Does it have devices? " + devices.hasNext());

常に false を返します。これは、「DummyDevice」が見つからないことを意味します。

私のEclipseプロジェクトでは、「src」にMETA-INFというフォルダーを作成し、その下に「services」というサブフォルダーを作成しました。

「Services」には「CustomDevicePackage.ICustomDevice」という名前のファイルがあり、コンテンツ行は「CustomDevicePackage.DummyDevice」です。

私はそれを正しくやっていますか?SPI について私が目にするすべての例は、JARS のロードに関するものです。JAR をロードしていません。同じプロジェクトでクラスを実行しようとしています。この方法は JAR をロードする場合にのみ機能しますか? プログラムで、ローカル サブクラスと外部 JAR のロードを同様にサポートしたいと考えています。

4

3 に答える 3

0

これを回答として追加していますが、この回避策の拡張コードの詳細を提供するために、以前の「回答」を残しています。以前の回答結果をバグとして Google に報告する作業を行っています。

java.util.ServiceLoader の Android 実装が壊れているため (System.getSecurityManager() == null の場合でも、常に内部の java.security.AccessControlContext フィールドに AccessController.getContext() を入力する)、回避策は、独自の ServiceLoader クラスを作成することです。 OpenJDK for Java 8 にあるコードをクラスにコピーし、import java.util.*; を使用せずに java.util から必要な特定のインポートを追加し、その ServiceLoader をコードで呼び出します (作成した ServiceLoader を完全に参照する必要がありますあいまいさ以上)。

これはエレガントではありませんが、機能する機能的な回避策です! また、ServiceLoader.load() 呼び出しで ClassLoader を使用する必要があります。その ClassLoader は、YourClass.class.getClassLoader() またはクラスの ClassLoader の子 ClassLoader である必要があります。

于 2019-01-28T12:46:08.910 に答える