Bagikan melalui


Android Callable Wrappers untuk Xamarin.Android

Android Callable Wrappers (ACW) diperlukan setiap kali runtime Android memanggil kode terkelola. Pembungkus ini diperlukan karena tidak ada cara untuk mendaftarkan kelas dengan ART (runtime Android) saat runtime. (Khususnya, Fungsi JNI DefineClass() tidak didukung oleh runtime Android.} Android Callable Wrappers sehingga menebus kurangnya dukungan pendaftaran jenis runtime.

Setiap kali kode Android perlu menjalankan virtual metode atau antarmuka yang overridden atau diimplementasikan dalam kode terkelola, Xamarin.Android harus menyediakan proksi Java sehingga metode ini dikirim ke jenis terkelola yang sesuai. Jenis proksi Java ini adalah kode Java yang memiliki kelas dasar "sama" dan daftar antarmuka Java sebagai jenis terkelola, menerapkan konstruktor yang sama dan mendeklarasikan kelas dasar dan metode antarmuka yang ditimpa.

Pembungkus yang dapat dipanggil Android dihasilkan oleh program monodroid.exe selama proses build: mereka dihasilkan untuk semua jenis yang (secara langsung atau tidak langsung) mewarisi Java.Lang.Object.

Penamaan Pembungkus yang Dapat Dipanggil Android

Nama paket untuk Android Callable Wrappers didasarkan pada MD5SUM dari nama jenis yang memenuhi syarat rakitan yang sedang diekspor. Teknik penamaan ini memungkinkan nama jenis yang sepenuhnya memenuhi syarat yang sama tersedia oleh rakitan yang berbeda tanpa memperkenalkan kesalahan pengemasan.

Karena skema penamaan MD5SUM ini, Anda tidak dapat langsung mengakses jenis berdasarkan nama Anda. Misalnya, perintah berikut adb tidak akan berfungsi karena nama my.ActivityType jenis tidak dihasilkan secara default:

adb shell am start -n My.Package.Name/my.ActivityType

Selain itu, Anda mungkin melihat kesalahan seperti berikut ini jika Anda mencoba mereferensikan jenis menurut nama:

java.lang.ClassNotFoundException: Didn't find class "com.company.app.MainActivity"
on path: DexPathList[[zip file "/data/app/com.company.App-1.apk"] ...

Jika Anda memerlukan akses ke jenis menurut nama, Anda dapat mendeklarasikan nama untuk jenis tersebut dalam deklarasi atribut. Misalnya, berikut adalah kode yang mendeklarasikan aktivitas dengan nama My.ActivityTypeyang sepenuhnya memenuhi syarat :

namespace My {
    [Activity]
    public partial class ActivityType : Activity {
        /* ... */
    }
}

ActivityAttribute.Name Properti dapat diatur untuk secara eksplisit menyatakan nama aktivitas ini:

namespace My {
    [Activity(Name="my.ActivityType")]
    public partial class ActivityType : Activity {
        /* ... */
    }
}

Setelah pengaturan properti ini ditambahkan, my.ActivityType dapat diakses berdasarkan nama dari kode eksternal dan dari adb skrip. Atribut Name dapat diatur untuk berbagai jenis termasuk Activity, , Application, ServiceBroadcastReceiver, dan ContentProvider:

Penamaan ACW berbasis MD5SUM diperkenalkan di Xamarin.Android 5.0. Untuk informasi selengkapnya tentang penamaan atribut, lihat RegisterAttribute.

Menerapkan Antarmuka

Ada kalanya Anda mungkin perlu menerapkan antarmuka Android, seperti Android.Content.IComponentCallbacks. Karena semua kelas dan antarmuka Android memperluas antarmuka Android.Runtime.IJavaObject , pertanyaan muncul: bagaimana kita menerapkan IJavaObject?

Pertanyaan tersebut dijawab di atas: alasan yang perlu diimplementasikan IJavaObject semua jenis Android adalah agar Xamarin.Android memiliki pembungkus yang dapat dipanggil Android untuk disediakan ke Android, yaitu proksi Java untuk jenis tertentu. Karena monodroid.exe hanya mencari Java.Lang.Object subkelas, dan Java.Lang.Object mengimplementasikan IJavaObject, jawabannya jelas: subkelas Java.Lang.Object :

class MyComponentCallbacks : Java.Lang.Object, Android.Content.IComponentCallbacks {

    public void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
    {
        // implementation goes here...
    } 

    public void OnLowMemory ()
    {
        // implementation goes here...
    }
}

Detail Implementasi

Sisa halaman ini menyediakan detail implementasi yang dapat berubah tanpa pemberitahuan (dan disajikan di sini hanya karena pengembang akan penasaran dengan apa yang terjadi).

Misalnya, mengingat sumber C# berikut:

using System;
using Android.App;
using Android.OS;

namespace Mono.Samples.HelloWorld
{
    public class HelloAndroid : Activity
    {
        protected override void OnCreate (Bundle savedInstanceState)
        {
            base.OnCreate (savedInstanceState);
            SetContentView (R.layout.main);
        }
    }
}

Program mandroid.exe akan menghasilkan Android Callable Wrapper berikut:

package mono.samples.helloWorld;

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

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

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

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

Perhatikan bahwa kelas dasar dipertahankan, dan native deklarasi metode disediakan untuk setiap metode yang ditimpa dalam kode terkelola.