3

ホームオートメーションアプリを作成しています。プラグインシステムを追加しようとしています。テストとして、テストクラス(Buttonをサブクラス化する)をAPKファイルとしてエクスポートし、アプリのファイルディレクトリに配置しました。このクラスの新しいインスタンスを作成し、とを使用してビューに配置することができましDexClassLoader.loadClass

次のステップは、このディレクトリ内のすべてのAPKをスキャンし、それらのクラスの名前を取得することです。

私はまさにそれを行うDexFileクラスを見つけましたが、それは次の例外をスローします:

04-18 17:26:15.697: E/dalvikvm(726): Can't open dex cache '/data/dalvik-cache/data@data@com.strutton.android.testplugin@files@testloadclass.apk@classes.dex': No such file or directory

04-18 17:26:15.705: I/dalvikvm(726): Unable to open or create cache for /data/data/com.strutton.android.testplugin/files/testloadclass.apk (/data/dalvik-cache/data@data@com.strutton.android.testplugin@files@testloadclass.apk@classes.dex)

システムキャッシュで最適化されたDexFileを見つけようとしているように見えますが、キャッシュディレクトリへのアクセス許可がありません。私が見ることができることから、これはおそらく設計によるものであり、私はそれで問題はありません。DEXファイルを解析してそこからクラス名を取得する別の方法はありますか?

いくつかのdex逆コンパイラプロジェクトのソースを見てきました。独自のソリューションを展開する必要がありますか?

何かを見逃した場合に備えて、(Activity OnCreateからの)テストアプリコードを次に示します。

    try {
        ArrayList<String> UIPlugins = new ArrayList<String>();
        final File filesDir = this.getFilesDir();
        final File tmpDir = getDir("dex", 0);
        final DexClassLoader classloader = new DexClassLoader( filesDir.getAbsolutePath()+"/testloadclass.apk",
                tmpDir.getAbsolutePath(),
                null, this.getClass().getClassLoader());
        final Class<Button> classToLoad = 
                (Class<Button>) classloader.loadClass("com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn");
        Button mybutton = classToLoad.getDeclaredConstructor(Context.class).newInstance(this);
        mybutton.setId(2);
        mybutton.setOnClickListener(this);
        main.addView(mybutton);
        // Up to here everything works as expected
        // This line throws the exceptions
        DexFile mDexFile = new DexFile(filesDir.getAbsolutePath()+"/testloadclass.apk";);
        Enumeration<String> classNames = mDexFile.entries();
        while (classNames.hasMoreElements()){
            String className = classNames.nextElement();
            if (className.endsWith("IRDroidUIPlugIn")){
                UIPlugins.add(className);
            }
        }
        final Class<Button> classToLoad = 
                (Class<Button>) classloader.loadClass("com.strutton.android.testloadclass.MyTestClass_IRDroidUIPlugIn");
        Button mybutton = classToLoad.getDeclaredConstructor(Context.class).newInstance(this);
        mybutton.setId(2);
        mybutton.setOnClickListener(this);
        main.addView(mybutton);
        btn.setText(tmpDir.getAbsolutePath());
      } catch (Exception e) {
        e.printStackTrace();
    }
4

2 に答える 2

4

それ以外の:

DexFile mDexFile = new DexFile(filesDir.getAbsolutePath()+"/testloadclass.apk";);

試す:

DexFile mDexFile = DexFile.loadDex(filesDir.getAbsolutePath()+"/testloadclass.apk", tmpDir.getAbsolutePath()+"/testloadclass.odex", 0);
于 2012-04-18T17:50:32.040 に答える
0

別の方法として、プラグインを個別のアプリケーションとしてインストールすることも考えられます。定義した特定のインテントを使用して、プラグイン アプリケーションにサービスを公開させることができます。また、サービスが実装する定義済みの aidl インターフェイスも必要です。メイン アプリケーションでは、そのサービス インテントを解決して、プラグイン サービスを見つけることができます。

于 2012-04-18T18:51:45.053 に答える