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.ActivityType
yang 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
, Service
BroadcastReceiver
, dan ContentProvider
:
- ActivityAttribute.Name
- ApplicationAttribute.Name
- ServiceAttribute.Name
- BroadcastReceiverAttribute.Name
- ContentProviderAttribute.Name
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.