2012-04-25 15 views
2

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

私は、/ data/data/[package_name]フォルダにファイルをコピーできますが、lib /サブフォルダにはコピーできないことがわかりました。 JavaでJNIインタフェースを利用するには、System.loadLibrary(libname)を呼び出す必要があります。しかし、これは.soファイルがlib /サブフォルダに置かれている必要があります。私が考えることができるこの周りの唯一の方法は、ユーザーにルートされたデバイスを持つことを要求することです。これを達成する別の方法がありますか?

答えて

1

使用は、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):共有lib/data/data/com.foo.test/lib/liba.so 0x40512640
D/dalvikvm(1022):/data/data/com.foo.test/lib/liba.so 0x40512640にJNI_OnLoadが見つかりませんでした。 INITをスキップ
D/LibTest(1022):読み込ん/data/data/com.foo.test/lib/libb.so ...
D/dalvikvm(1022):libに/データ/データをロードしようとすると/ COM .foo.test/LIB/libb.so 0x40512640
D/dalvikvm(1022):0x40512640
D/dalvikvm(1022)/data/data/com.foo.test/lib/libb.so追加された共有ライブラリ:いいえJNI_OnLoadが/data/data/com.foo.test/lib/libb.so 0x40512640にあります。

+0

ああ、System.loadがこのために使われたのか分かりませんでした。私が質問を投稿する前に私は研究をすべきだと思います。助けてくれてありがとう! – paulscode

1

のAPKとしてあなたのプラグインを配布し、IPCメカニズムを経由してプラグインへのホストからの通信:

  • 放送Intents
  • サービス(コマンドまたは結合パターン)
  • ContentProvider

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

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

+0

これは別の方法ですが、最適な方法ではありません。しかし、良いオプションを持っている。ありがとう! – paulscode

1

dlopenを使用して、soファイルをC++で読み込むことができます。 私はこのコードを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(); 
+0

ありがとう!私は実際にこの部分を持っていましたが、Java側でもこのことが気付かれませんでした。しかし、完全な画像のために、ここでこの答えを得るのは良いことです。ありがとう! – paulscode

関連する問題