6

私はAndroidプロジェクトのためにMonoでかなり単純なアクティビティを作成しました:

[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]
public class Activity1 : Activity
{
    private string value = "intitial";

    [Export]
    public string GetString()
    {
        return value;
    }

    [Export]
    public void SetString(string newValue)
    {
        value = newValue;
    }
}

このアクティビティは、概念実証としてのみ機能する必要があるため、その単純さです。ここで、「通常の」JavaベースのAndroidアプリケーションからGetString()メソッドを呼び出せるようにしたいと思います。

Xamarinのドキュメントで、JavaからManagedへの相互運用について読んだことがあります。これはまさに私が探しているもののようです。私が正しく理解していれば、Mono for Androidアプリがコンパイルされると、Android Callable Wrappers(ACW)と呼ばれるJavaクラスが生成されます。そうすれば、JavaベースのAndroidアプリケーションからこれらのACWのメソッドを呼び出すことができるはずです。

問題は、 JavaベースのAndroidアプリからコンパイルされたMono for Androidアプリケーション(apkファイル)をどのように正確に参照するかです。

これは私が今立ち往生していて、具体的な例を見つけることができなかった場所です。SO(これこれ)といくつかのブログ投稿についても同様の質問がありますが、要約すると「ACWを使用する」ということです。しかし、どのくらい正確に?たぶん私はここで明らかな何かを見逃しています。Androidの男ではありません。

私が試したのは、Mono forAndroidapkからヤンクしたdexファイルを動的にロードすることです。それをストレージカードに置いてDexClassLoaderから、JavaベースのAndroidアプリから使用してロードしようとしました(このブログ投稿をフォローしました)。ACWクラスが見つかりましたが、そのインスタンスを作成しようとすると、次のエラーが発生しました。

ネイティブLmno/android / Runtime; .register(Ljava / lang / String; Ljava / lang / Class; Ljava / lang / String;)の実装が見つかりません

どういうわけか、Androidランタイム用のMonoをJavaベースのアプリに含める必要があると思いますが、その方法がわかりません。

編集:これは私がdex をロードしようとしているコードです:

DexClassLoader cl = new DexClassLoader(dexInternalStoragePath.getAbsolutePath(),
    optimizedDexOutputPath.getAbsolutePath(),
    null,
    getClassLoader());

try {
    Class<?> classActivity1 = cl.loadClass("androidapplication1.Activity1");

    // the following line throws the exception
    Object a = classActivity1.newInstance();

    Method getStringMethod = classActivity1.getMethod("GetString");
    Object result = getStringMethod.invoke(angel);

    result = null;
} catch (Exception e) {
    e.printStackTrace();
}

EDIT2: 私は今ここで、JavaからAndroid用のMonoで書かれたアクティビティを直接開始できるはずだと読んいます。JavaからAndroid用のMonoを参照する方法はまだはっきりしていません。グーグルでは、関連するヒットは得られません。本当に今困惑しています。

4

1 に答える 1

5

あなたがやろうとしていることを私が正しく理解していれば、これは実際には不可能です。表示されるエラーメッセージが示すように、Mono for Androidアプリケーション内のアクティビティは、正しく機能するためにMonoランタイムに依存しています。この場合、呼び出し可能なラッパーは、Monoランタイムを呼び出す単なる薄いJavaラッパークラスであるため、それ自体では役に立ちません。プロジェクトのビルド後にobj/Debug / android / srcフォルダーを見ると、生成された呼び出し可能ラッパーを実際に確認できます。例えば:

package androidapplication9;


public class Activity1
    extends android.app.Activity
    implements
        mono.android.IGCUserPeer
{
    static final String __md_methods;
    static {
        __md_methods = 
            "n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n" +
            "";
        mono.android.Runtime.register ("AndroidApplication9.Activity1, AndroidApplication9, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", Activity1.class, __md_methods);
    }


    public Activity1 ()
    {
        super ();
        if (getClass () == Activity1.class)
            mono.android.TypeManager.Activate ("AndroidApplication9.Activity1, AndroidApplication9, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "", this, new java.lang.Object[] {  });
    }


    public void onCreate (android.os.Bundle p0)
    {
        n_onCreate (p0);
    }

    private native void n_onCreate (android.os.Bundle p0);

    java.util.ArrayList refList;
    public void monodroidAddReference (java.lang.Object obj)
    {
        if (refList == null)
            refList = new java.util.ArrayList ();
        refList.add (obj);
    }

    public void monodroidClearReferences ()
    {
        if (refList != null)
            refList.clear ();
    }
}

とはいえ、Androidの動作方法により、外部のJavaアクティビティを開始するのと同じ方法で、MonoforAndroidアプリケーションで定義されたアクティビティをJavaアプリケーションに開始させることができます。もちろん、これは両方のアプリケーションがインストールされていることに依存しますが、MonoforAndroidアプリケーションとMonoランタイムが実際にそのアクティビティを実行するように起動します。

編集

コメントで提起した質問に答えるために更新しています。基本的にはExportAttribute、ACWの生成方法をさらに制御できるため、特定のメソッドまたはフィールドがACWに存在する必要があり、その名前を指定できます。これは、レイアウトでandroid:onClick属性などを使用する場合に役立ちます。たとえば、デフォルトでは、ACWに参照するメソッドが含まれていません。

Monoランタイムが存在しないため、MonoforAndroidアプリケーションのコンテキスト外でACWを十分に活用することはできません。C#で記述されたコードは、Monoランタイム上で実行され、コンパイル中などのバックグラウンドでJavaに変換されません。実行時に、Dalvik(Androidのランタイム)とMonoの2つのランタイムが並んでいます。呼び出し可能なラッパーは、2つが相互に通信できるようにするためにあります。そのため、Mono for AndroidクラスライブラリでもMonoランタイムに依存するため、そのランタイムとは別に使用することはできません。

この図は、アーキテクチャがどのように見えるか、およびランタイムが互いにどのように関連しているかを示しています。

Androidアーキテクチャ用のMono

これが物事を片付けるのに役立つことを願っています!

于 2012-08-31T18:35:59.790 に答える