Bagikan melalui


Pemecahan masalah pengikatan

Mengikat file pustaka Android ( .aar atau .jar) jarang merupakan urusan yang mudah; biasanya memerlukan upaya tambahan untuk mengurangi masalah yang dihasilkan dari perbedaan antara Java dan .NET. Masalah ini akan mencegah .NET Android menghubungkan pustaka Android dan akan terlihat sebagai pesan kesalahan di log build. Panduan ini akan memberikan beberapa tips untuk memecahkan masalah, mencantumkan beberapa masalah/skenario yang lebih umum, dan memberikan solusi yang mungkin agar berhasil mengikat pustaka Android.

Saat mengikat pustaka Android yang ada, perlu diingat poin-poin berikut:

  • Dependensi eksternal untuk pustaka – Dependensi Java apa pun yang diperlukan oleh pustaka Android harus disertakan dalam proyek .NET untuk Android melalui NuGet package atau sebagai AndroidLibrary.

  • Tingkat API Android yang ditargetkan pustaka Android - Tidak mungkin untuk "menurunkan tingkat API Android" ; pastikan bahwa proyek pengikatan .NET untuk Android menargetkan tingkat API yang sama (atau lebih tinggi) dengan pustaka Android.

Tips

Wiki repositori GitHub Binding Tooling adalah referensi yang bagus dan berisi informasi pemecahan masalah tambahan yang dapat membantu kasus-kasus spesifik.

Langkah pertama untuk memecahkan masalah dengan mengikat pustaka .NET untuk Android adalah mengaktifkan output diagnostik MSBuild. Setelah mengaktifkan output diagnostik, bangun kembali proyek pengikatan .NET untuk Android dan periksa log build untuk menemukan petunjuk tentang apa penyebab masalahnya.

Ini juga dapat terbukti membantu untuk mendekompilasi pustaka Android dan memeriksa jenis dan metode yang sedang dicoba untuk diikat oleh .NET untuk Android. Ini tercakup secara lebih rinci nanti dalam panduan ini.

Mendekompilasi pustaka Android

Memeriksa kelas dan metode kelas Java dapat memberikan informasi berharga yang akan membantu dalam mengikat pustaka. JD-GUI adalah utilitas grafis yang dapat menampilkan kode sumber Java dari file CLASS yang terkandung dalam JAR.

Untuk mendekompilasi pustaka Android, buka file .JAR dengan decompiler Java. Jika pustaka adalah file .AAR, kode sumber Java akan berada di entri classes.jar dari file arsip. Berikut ini adalah cuplikan layar sampel penggunaan JD-GUI untuk menganalisis Picasso JAR:

Menggunakan Java Decompiler untuk menganalisis picasso-2.5.2.jar

Setelah Anda mendekompilasi pustaka Android, periksa kode sumber. Secara umum, cari :

  • Kelas yang memiliki karakteristik pengaburan – Karakteristik kelas yang mengalami pengaburan meliputi:

    • Nama kelas mencakup $, yaitu $.class
    • Nama kelas sepenuhnya terdiri dari huruf kecil, yaitu a.class
  • import pernyataan untuk pustaka yang tidak direferensikan – Identifikasi pustaka yang tidak direferensikan dan tambahkan dependensi tersebut ke proyek pengikatan .NET untuk Android dengan pengikatan yang sesuai dari NuGet atau dengan Build Action dari AndroidLibrary.

Catatan

Mendekompresi pustaka Java mungkin dilarang atau tunduk pada pembatasan hukum berdasarkan undang-undang lokal atau lisensi tempat pustaka Java diterbitkan. Jika perlu, daftarkan layanan profesional hukum sebelum mencoba mendekompilasi pustaka Java dan memeriksa kode sumber.

Periksa api.xml

Sebagai bagian dari membangun proyek pengikatan, .NET untuk Android akan menghasilkan nama file XML obj/Debug/api.xml:

Api.xml yang dihasilkan di bawah obj/Debug

File ini menyediakan daftar semua API Java yang sedang berusaha diikat oleh .NET untuk Android. Isi file ini dapat membantu mengidentifikasi jenis atau metode yang hilang, pengikatan duplikat. Meskipun inspeksi file ini membosankan dan memakan waktu, itu dapat memberikan petunjuk tentang apa yang mungkin menyebabkan masalah pengikatan. Misalnya, api.xml mungkin mengungkapkan bahwa properti mengembalikan jenis yang tidak pantas, atau ada dua jenis yang memiliki nama terkelola yang sama.

Masalah umum

Bagian ini akan mencantumkan beberapa pesan kesalahan umum atau gejala yang mungkin terjadi saat mencoba menghubungkan pustaka Android.

Masalah: Jenis C# yang hilang dalam output yang dihasilkan.

Pengikatan .dll dibangun tetapi mengabaikan beberapa jenis Java, atau sumber C# yang dihasilkan gagal dibangun karena kesalahan yang menyatakan bahwa ada jenis yang hilang.

Kemungkinan penyebabnya:

Kesalahan ini dapat terjadi karena beberapa alasan seperti yang tercantum di bawah ini:

  • Pustaka yang sedang dibundel dapat menggunakan referensi pustaka Java kedua. Jika API publik untuk pustaka terikat menggunakan jenis dari pustaka kedua, Anda juga harus mereferensikan pengikatan terkelola untuk pustaka kedua.

  • Java memungkinkan turunan kelas publik dari kelas non-publik, tetapi ini tidak didukung di .NET. Karena generator pengikatan tidak menghasilkan pengikatan untuk kelas non-publik, kelas turunan seperti ini tidak dapat dihasilkan dengan benar. Untuk memperbaikinya, hapus entri metadata untuk kelas turunan tersebut menggunakan remove-node di Metadata.xml, atau perbaiki metadata yang membuat kelas non-publik menjadi publik. Meskipun solusi terakhir akan membuat pengikatan sehingga sumber C# akan dibangun, kelas non-publik tidak boleh digunakan.

    Contohnya:

    <attr path="/api/package[@name='com.some.package']/class[@name='SomeClass']"
        name="visibility">public</attr>
    
  • Alat yang mengaburkan pustaka Java dapat mengganggu Generator Pengikatan .NET untuk Android dan kemampuannya untuk menghasilkan kelas pembungkus C#. Cuplikan berikut menunjukkan cara memperbarui Metadata.xml untuk membatalkan pemadaman nama kelas.

    <attr path="/api/package[@name='{package_name}']/class[@name='{name}']"
        name="obfuscated">false</attr>
    

Masalah: Sumber C# yang dihasilkan tidak dibangun karena ketidakcocokan jenis parameter

Sumber C# yang dihasilkan tidak dapat dikompilasi. Jenis parameter metode yang di-override tidak cocok.

Kemungkinan penyebabnya:

.NET untuk Android mencakup berbagai bidang Java yang dipetakan ke enum dalam pengikatan C#. Ini dapat menyebabkan ketidaksesuaian jenis dalam pengikatan yang dihasilkan. Untuk mengatasi hal ini, tanda tangan metode yang dibuat dari generator pengikatan perlu dimodifikasi untuk menggunakan enum. Untuk informasi selengkapnya, silakan lihat Membuat enumerasi.

Masalah: Menduplikasi jenis EventArgs kustom

Proses kompilasi gagal karena adanya jenis duplikat dari EventArgs kustom. Kesalahan seperti ini terjadi:

error CS0102: The type `Com.Google.Ads.Mediation.DismissScreenEventArgs' already contains a definition for `p0'

Kemungkinan penyebabnya:

Ini karena ada beberapa konflik antara jenis peristiwa yang berasal dari lebih dari satu jenis "listener" antarmuka yang berbagi metode yang memiliki nama yang identik. Misalnya, jika ada dua antarmuka Java seperti yang terlihat dalam contoh di bawah ini, generator membuat DismissScreenEventArgs untuk MediationBannerListener dan MediationInterstitialListener, yang mengakibatkan kesalahan.

// Java:
public interface MediationBannerListener {
    void onDismissScreen(MediationBannerAdapter p0);
}
public interface MediationInterstitialListener {
    void onDismissScreen(MediationInterstitialAdapter p0);
}

Ini dirancang agar nama panjang pada jenis argumen peristiwa dihindari. Untuk menghindari konflik ini, diperlukan beberapa transformasi metadata. Edit Transformasi\Metadata.xml dan tambahkan argsType atribut di salah satu antarmuka (atau pada metode antarmuka):

<attr path="/api/package[@name='com.google.ads.mediation']/
        interface[@name='MediationBannerListener']/method[@name='onDismissScreen']"
        name="argsType">BannerDismissScreenEventArgs</attr>

<attr path="/api/package[@name='com.google.ads.mediation']/
        interface[@name='MediationInterstitialListener']/method[@name='onDismissScreen']"
        name="argsType">IntersitionalDismissScreenEventArgs</attr>

<attr path="/api/package[@name='android.content']/
        interface[@name='DialogInterface.OnClickListener']"
        name="argsType">DialogClickEventArgs</attr>

Masalah: Kelas tidak menerapkan metode antarmuka

Pesan kesalahan diproduksi yang menunjukkan bahwa kelas yang dihasilkan tidak menerapkan metode yang diperlukan untuk antarmuka yang diterapkan kelas yang dihasilkan. Namun, melihat kode yang dihasilkan, Anda dapat melihat bahwa metode diimplementasikan.

Berikut adalah contoh kesalahan:

obj\Debug\generated\src\Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.cs(8,23):
error CS0738: 'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter' does not
implement interface member 'Oauth.Signpost.Http.IHttpRequest.Unwrap()'.
'Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.Unwrap()' cannot implement
'Oauth.Signpost.Http.IHttpRequest.Unwrap()' because it does not have the matching
return type of 'Java.Lang.Object'

Kemungkinan penyebabnya:

Ini adalah masalah yang terjadi dengan mengikat metode Java dengan jenis pengembalian kovarian. Dalam contoh ini, metode Oauth.Signpost.Http.IHttpRequest.UnWrap() perlu mengembalikan Java.Lang.Object. Namun, metode Oauth.Signpost.Basic.HttpURLConnectionRequestAdapter.UnWrap() ini memiliki jenis pengembalian .HttpURLConnection Ada dua cara untuk memperbaiki masalah ini:

  • Tambahkan deklarasi kelas parsial untuk HttpURLConnectionRequestAdapter dan terapkan IHttpRequest.Unwrap()secara eksplisit :

    namespace Oauth.Signpost.Basic {
        partial class HttpURLConnectionRequestAdapter {
            Java.Lang.Object OauthSignpost.Http.IHttpRequest.Unwrap() {
                return Unwrap();
            }
        }
    }
    
  • Hapus kovarians dari kode C# yang dihasilkan. Ini melibatkan penambahan transformasi berikut ke Transforms\Metadata.xml yang akan menyebabkan kode C# yang dihasilkan memiliki jenis pengembalian :Java.Lang.Object

    <attr
        path="/api/package[@name='oauth.signpost.basic']/class[@name='HttpURLConnectionRequestAdapter']/method[@name='unwrap']"
        name="managedReturn">Java.Lang.Object
    </attr>
    

Masalah: Tabrakan nama pada kelas dalam atau properti

Visibilitas yang bertentangan pada objek yang diwariskan.

Di Java, tidak diharuskan bahwa kelas turunan memiliki visibilitas yang sama dengan induknya. Java hanya akan memperbaikinya untuk Anda. Di C#, itu harus eksplisit, jadi Anda perlu memastikan semua kelas dalam hierarki memiliki visibilitas yang sesuai. Contoh berikut menunjukkan cara mengubah nama paket Java dari com.evernote.android.job menjadi Evernote.AndroidJob:

<!-- Change the visibility of a class -->
<attr path="/api/package[@name='namespace']/class[@name='ClassName']" name="visibility">public</attr>

<!-- Change the visibility of a method -->
<attr path="/api/package[@name='namespace']/class[@name='ClassName']/method[@name='MethodName']" name="visibility">public</attr>

Masalah: Pustaka .so yang diperlukan oleh pengikatan tidak dimuat

Beberapa proyek pengikatan mungkin juga bergantung pada fungsionalitas dalam pustaka .so . Ada kemungkinan bahwa .NET untuk Android tidak akan secara otomatis memuat pustaka .so . Ketika kode Java yang dibungkus dijalankan, .NET untuk Android akan gagal melakukan panggilan JNI dan pesan kesalahan java.lang.UnsatisfiedLinkError: Metode native tidak ditemukan: akan muncul dalam output logcat aplikasi.

Perbaikan untuk ini adalah memuat pustaka .so secara manual dengan panggilan ke Java.Lang.JavaSystem.LoadLibrary. Misalnya dengan asumsi bahwa proyek .NET untuk Android memiliki pustaka bersama libpocketsphinx_jni.so yang disertakan dalam proyek pengikatan dengan tindakan build EmbeddedNativeLibrary, cuplikan berikut (dijalankan sebelum menggunakan pustaka bersama) akan memuat pustaka .so:

Java.Lang.JavaSystem.LoadLibrary("pocketsphinx_jni");