1. ホーム
  2. android

Androidアプリケーションから実行時にライブラリを動的にロードすることは可能ですか?

2023-11-12 02:21:53

質問

Androidアプリケーションで、実行時にJavaライブラリをダウンロードして使用する方法はありますか?

以下はその例です。

アプリケーションが入力値に応じていくつかの計算をする必要があるとします。アプリケーションはこれらの入力値を要求し、必要な Classe または Method が利用できます。

利用できない場合、サーバーに接続し、必要なライブラリをダウンロードし、実行時にロードしてリフレクション技術を使用して必要なメソッドを呼び出します。ライブラリをダウンロードするユーザーなど、様々な条件によって実装が変わる可能性があります。

どのように解決するのですか?

申し訳ありませんが、私は遅くなり、質問はすでに受け入れられている答えを持っていますが はい のように、外部ライブラリをダウンロードし、実行することができます。以下は私が行った方法です。

これが実現可能かどうかが気になったので、以下のようなクラスを書きました。

package org.shlublu.android.sandbox;

import android.util.Log;

public class MyClass {
    public MyClass() {
        Log.d(MyClass.class.getName(), "MyClass: constructor called.");
    }

    public void doSomething() {
        Log.d(MyClass.class.getName(), "MyClass: doSomething() called.");
    }
}

そして、それをDEXファイルにパッケージして、端末のSDカードに保存したものを /sdcard/shlublu.jar .

を削除した後、以下のようなプログラムを書きました。 MyClass を削除してきれいにした後、以下のようなプログラムを書きました。

public class Main extends Activity {

    @SuppressWarnings("unchecked")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        try {
            final String libPath = Environment.getExternalStorageDirectory() + "/shlublu.jar";
            final File tmpDir = getDir("dex", 0);

            final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader());
            final Class<Object> classToLoad = (Class<Object>) classloader.loadClass("org.shlublu.android.sandbox.MyClass");

            final Object myInstance  = classToLoad.newInstance();
            final Method doSomething = classToLoad.getMethod("doSomething");

            doSomething.invoke(myInstance);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

これは基本的にクラス MyClass をそのように読み込む。

  • を作成します。 DexClassLoader

  • クラスを抽出するために使用します。 MyClass から "/sdcard/shlublu.jar"

  • で、このクラスをアプリケーションの "dex" private directory (携帯電話の内部ストレージ) に格納します。

次に MyClass のインスタンスを作成し doSomething() を起動します。

そして、それは動作します... で定義されたトレースが表示されます。 MyClass で定義されたトレースがLogCatに表示されます。

エミュレータ 2.1 と物理的な HTC 携帯電話 (Android 2.2 を実行しており、ルート化されていない) の両方で試してみました。

これは、アプリケーションがダウンロードし、実行するための外部 DEX ファイルを作成できることを意味します。ここでは、ハードな方法で作成しました (醜い Object を鋳造します。 Method.invoke() 醜い呼び出し...) を使って遊ぶことは可能なはずです。 Interface を弄って、よりクリーンなものを作ることは可能なはずです。

うわー。最初に驚いたのは私です。私はてっきり SecurityException .

もっと調査するのに役立ついくつかの事実。

  • 私の DEX shlublu.jar は署名されましたが、私のアプリは署名されませんでした。
  • 私のアプリはEclipse/USB接続から実行されました。つまり、これはDEBUGモードでコンパイルされた署名されていないAPKです。