2

私はオープンソースのエミュレータ プロジェクトを開発しています。このプロジェクトには、カスタマイズ可能な複数のネイティブ プラグインがあります。これらのプラグインは、ネイティブの共有オブジェクト ライブラリ (.so ファイル) として構築され、JNI を介してネイティブと Java の間のさまざまなインターフェイスを備えています。これまでに作成されたプラグインごとに APK を配布するのではなく、ユーザーが独自のカスタム プラグインを作成できるようにするために、アプリのインストール後にいつでもこれらの .so ファイルをインポートする方法が必要です。

ファイルをフォルダー /data/data/[package_name] にコピーできることがわかりましたが、lib/ サブフォルダーにはコピーできません (「システム」グループが所有しているため)。Java で JNI インターフェースを利用するには、System.loadLibrary( libname ); を呼び出す必要があります。ただし、これには .so ファイルを lib/ サブフォルダーに配置する必要があるようです。これを回避する唯一の方法は、ユーザーにルート化されたデバイスを要求することです。これを達成する別の方法はありますか?

4

3 に答える 3

2

代わりに System.load() を使用してください。

static
{
    final String[] libs = {
        "/data/data/com.foo.test/lib/liba.so",
        "/data/data/com.foo.test/lib/libb.so"
    };

    for (int i=0; i<libs.length; ++i)
    {
        Log.d(TAG, "Loading " + libs[i] + "...");
        System.load(libs[i]);
    }
}

$ adb logcat

D/LibTest (1022): /data/data/com.foo.test/lib/liba.so を読み込んでいます...
D/dalvikvm(1022): lib /data/data/com.foo.test/lib を読み込もうとしています/liba.so 0x40512640
D/dalvikvm( 1022): 共有ライブラリを追加しました /data/data/com.foo.test/lib/liba.so 0x40512640
D/dalvikvm( 1022): /data/data/com に JNI_OnLoad が見つかりません。 foo.test/lib/liba.so 0x40512640、init
D/LibTest (1022) をスキップ: /data/data/com.foo.test/lib/libb.so を読み込んでいます...
D/dalvikvm(1022): 読み込もうとしていますlib /data/data/com.foo.test/lib/libb.so 0x40512640
D/dalvikvm( 1022): 共有ライブラリを追加しました /data/data/com.foo.test/lib/libb.so 0x40512640
D/dalvikvm( 1022 ): /data/data/com.foo.test/lib/libb.so 0x40512640 に JNI_OnLoad が見つかりません。init をスキップします

于 2012-04-26T14:30:12.370 に答える
1

プラグインを APK として配布し、IPC メカニズムを介してホストからプラグインに通信します。

  • ブロードキャストIntents
  • サービス (コマンドまたはバインディング パターン)
  • ContentProvider

副次的なボーナスとして、プラグインがホストよりも多くの/異なる権限を必要とする場合、これはサポートされています。

確かに、これには IPC が必要です。これにより、重要なオーバーヘッドが追加され、粗粒度のプラグイン通信プロトコルの方向に進みます。また、より多くの RAM を消費します (そして、オーバーヘッドのための余分な CPU 時間は、より多くのバッテリー寿命を消費します)。

于 2012-04-25T23:20:37.593 に答える
1

c++ で so ファイルをロードするには、dlopen を使用できます。このコードを C++ で使用して、任意のフォルダーにファイルをロードします。

// KGEmain function pointer
typedef void (*KGEmain) ();

std::string strPluginName = "/data/data/com.kge.android/lib/lib";
strPluginName += appname;
strPluginName += ".so";

void* handle = dlopen(strPluginName.c_str(), RTLD_LAZY);

const char* error;

if (!handle)
{
    LOGE("can't load the %s plugin. (%s)", strPluginName.c_str(), dlerror());
    return;
}
// Clear any exiting error
dlerror();

// Load the KGEmain function
pFn = (KGEmain)dlsym(handle, "KGEmain");
if ((error = dlerror()) != NULL || !pFn)
{
    LOGE("KGEmain function dose not find in %s plugin.\n%s", strPluginName.c_str(), error);
    return;
}

pFn();
于 2012-04-29T15:24:39.133 に答える