All Products
Search
Document Center

Alibaba Cloud DNS:Android SDK

Last Updated:May 31, 2026

Dokumen ini menjelaskan cara mengintegrasikan HTTPDNS Android SDK.

Ikhtisar

Android SDK merupakan wrapper Java untuk HTTPDNS DoH JSON API. SDK ini menyediakan antarmuka Java bagi aplikasi Android untuk melakukan resolusi nama domain dan mencakup cache lokal yang efisien menggunakan kebijakan Time-to-Live (TTL) dan Least Recently Used (LRU). Anda dapat dengan mudah mengintegrasikan HTTPDNS ke dalam aplikasi Android guna memperbaiki error resolusi domain serta mengaktifkan penjadwalan yang akurat dan berbiaya rendah.

SDK ini menawarkan keunggulan berikut:

  • Mudah digunakan

    Integrasikan SDK yang disediakan untuk mengakses layanan HTTPDNS. Metode integrasinya sederhana dan memberikan pengalaman resolusi yang simpel dan nyaman.

  • Latensi nol

    SDK menerapkan cache LRU yang menyimpan alamat IP hasil resolusi secara lokal. SDK ini secara proaktif merefresh entri cache berbasis TTL yang telah kedaluwarsa agar data cache tetap mutakhir dan efektif, sehingga memungkinkan resolusi dengan latensi nol.

Untuk panduan implementasi, lihat kode sumber proyek contoh alidns_android_demo.

Integrasi SDK

Tambahkan SDK

Gradle dan Maven

Tambahkan kode berikut ke file build.gradle Anda:

allprojects {
  repositories {
    maven {
      url 'https://maven.aliyun.com/repository/public/'
    }
    mavenLocal()
    mavenCentral()
  }
}

Tambahkan informasi dependensi:

dependencies {
     implementation 'com.alibaba.pdns:alidns-android-sdk:2.3.2'
     implementation 'com.google.code.gson:gson:2.8.5'
}

File AAR

Lihat Download SDK untuk mendapatkan SDK, lalu integrasikan paket AAR alidns_android_sdk.aar yang disertakan ke direktori libs proyek Anda.

Inisialisasi SDK

Penting

Untuk memastikan kinerja yang andal dan menghindari kegagalan resolusi alamat IP, inisialisasi SDK sedini mungkin dalam siklus hidup aplikasi Anda.

Pertama, temukan Account ID Anda di Konsol dan buat kunci untuk mendapatkan AccessKey ID dan AccessKey Secret Anda. Setelah mengintegrasikan SDK, lakukan inisialisasi. Untuk detailnya, lihat contoh kelas Application berikut.

public class DnsCacheApplication extends Application{

    private String accountId = "Your Account ID"; // Setel Account ID Anda dari Konsol.
    private String accessKeyId = "Your AccessKey ID"; // Setel AccessKey ID Anda dari Konsol.
    private String accessKeySecret = "Your AccessKey Secret"; // Setel AccessKey Secret Anda dari Konsol.

    @Override
    public void onCreate() {
       super.onCreate();
       // Setel Account ID, AccessKey ID, dan AccessKey Secret untuk akses SDK.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       // Catatan: Jika Anda mengonfigurasi domain untuk keep-alive, resolusi akan dipicu secara otomatis saat 75% TTL berlalu. 
       // Hal ini memastikan bahwa resolusi untuk domain tersebut selalu mengenai cache. Namun, jika Anda menggunakan CDN, 
       // TTL bisa sangat singkat, sehingga menyebabkan permintaan yang sering dan meningkatkan biaya. Gunakan metode ini dengan hati-hati.
       DNSResolver.setKeepAliveDomains(new String[]{"your-domain-to-keep-alive-1","your-domain-to-keep-alive-2",...});       
       // Lakukan pre-resolusi untuk domain tertentu guna mendapatkan alamat IPv4. Ganti placeholder domain dengan domain yang ingin Anda resolusi.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}
Catatan

DNSResolver adalah kelas inti dari SDK HTTPDNS. Kelas ini membungkus DoH JSON API HTTPDNS untuk meresolusi nama domain target Anda menjadi alamat IP. Kami menyarankan Anda mengintegrasikan SDK HTTPDNS di subclass Application Anda.

Selain itu, proyek Android Anda harus mendeklarasikan izin akses berikut di AndroidManifest.xml:

<!--Izin yang diperlukan-->
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

Otentikasi SDK

Mulai versi 2.0, SDK mendukung fitur otentikasi untuk mengamankan identitas Anda dan mencegah penggunaan tidak sah. Untuk mengaktifkan HTTPDNS, buat kunci di Konsol untuk mendapatkan AccessKey ID dan AccessKey Secret. Anda harus menyetel parameter otentikasi selama inisialisasi SDK. HTTPDNS menolak permintaan tanpa otentikasi, yang menyebabkan kegagalan resolusi dan berdampak pada layanan Anda.HTTPDNS

Anda dapat menyetel parameter otentikasi sebagai berikut:

DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret);
Peringatan
  • Untuk mencegah Account ID, AccessKey ID, AccessKey Secret, atau data waktu proses lainnya terekspos di log, nonaktifkan logging debug SDK pada rilis produksi Anda.

  • Integrasi SDK memerlukan penyetelan Account ID, AccessKey ID, dan AccessKey Secret dalam kode Anda. Parameter-parameter ini terkait dengan metering dan penagihan. Untuk mencegah dekompilasi jahat yang mengekspos kredensial Anda, aktifkan obfuscasi kode dan penguatan aplikasi sebelum merilis aplikasi Anda.

Permasalahan integrasi SDK

Error "Cleartext HTTP traffic not permitted"

Penyebab: Mulai Android 9.0 (API level 28), Android secara default memblokir lalu lintas jaringan cleartext dan hanya mengizinkan URL HTTPS.

Solusi

Dalam file AndroidManifest.xml Anda, tambahkan kode berikut ke elemen :

android:usesCleartextTraffic="true"

<application
        android:name=".DnsCacheApplication"
        android:icon="@mipmap/ic_launcher"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:usesCleartextTraffic="true">

Error "Didn't find class BasicHttpParams"

Penyebab: Klien HTTP Apache sudah tidak didukung lagi.

Di Android 6.0, Google menghapus dukungan untuk klien HTTP Apache. Mulai Android 9.0, org.apache.http.legacy dihapus dari bootclasspath.

Perubahan ini tidak memengaruhi sebagian besar aplikasi yang menargetkan API level di bawah 28. Untuk aplikasi yang menargetkan API level 28 atau lebih tinggi, jika Anda terus menggunakan antarmuka HTTP Apache atau library yang menggunakannya, akan terjadi exception karena antarmuka HTTP Apache tidak ditemukan.

Solusi

Dalam file AndroidManifest.xml Anda, tambahkan kode berikut ke elemen :

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

Konfigurasi NDK

  • Di direktori root proyek aplikasi Anda, tambahkan path instalasi NDK ke file local.properties.

ndk.dir=...\\ndk\\21.4.7075529; // Ganti ... dengan path instalasi NDK lokal.
  • Di direktori root proyek aplikasi Anda, tambahkan konfigurasi berikut ke file gradle.properties.

android.useDeprecatedNdk = true;

Untuk kinerja optimal, kami merekomendasikan menggunakan JDK 1.8 dan NDK 21.4.7075529 saat mengompilasi aplikasi Anda.

Referensi API

Pengaturan umum

1. Inisialisasi menggunakan metode Init

Panggil metode Init saat Anda menginisialisasi SDK di kelas Application Anda.

DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret);

2. Setel domain untuk pre-resolusi

Saat menginisialisasi aplikasi Anda, kami sangat menyarankan agar Anda mendaftarkan domain yang akan digunakan ke SDK HTTPDNS. Hal ini memungkinkan SDK melakukan pre-resolusi, yang mengurangi latensi permintaan resolusi berikutnya. Panggil metode berikut untuk menyetel domain yang akan di-pre-load:

  • Tentukan pre-resolusi untuk domain IPv4 atau IPv6

// Tentukan tipe catatan untuk pre-resolusi. Ganti placeholder domain dengan domain yang ingin Anda resolusi.
DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{...});

// DNSResolver.QTYPE_IPV4: Pre-fetch tipe catatan IPv4 untuk domain.
// DNSResolver.QTYPE_IPV6: Pre-fetch tipe catatan IPv6 untuk domain.
// DNSResolver.QTYPE_IPV4_IPV6: Pre-fetch tipe catatan IPv4 dan IPv6 untuk domain.
  • Pilih secara otomatis IPv4 atau IPv6 untuk pre-resolusi berdasarkan jaringan saat ini. Di lingkungan dual-stack, alamat IPv4 dan IPv6 keduanya di-pre-load.

DNSResolver.getInstance().preLoadDomains(domains);
Penting

API pre-resolusi memicu permintaan jaringan asinkron secara real-time. Pastikan semua inisialisasi yang diperlukan telah selesai sebelum memanggil API ini.

3. Setel domain untuk cache keep-alive

SDK secara otomatis meresolusi domain yang dikonfigurasi saat 75% TTL-nya berlalu. Hal ini memastikan bahwa permintaan resolusi selalu mengenai cache, meningkatkan efisiensi resolusi. Kami menyarankan agar Anda membatasi jumlah domain untuk fitur ini hingga 10. Pengaturan ini independen dari pre-resolusi.

DNSResolver.setKeepAliveDomains(new String[]{"your-domain-1", "your-domain-2"});
Catatan

Kelebihan

1. Catatan diperbarui secara tepat waktu (sebelum TTL berakhir).

2. Saat digunakan bersama pre-resolusi, latensi resolusi awal dapat dikurangi menjadi 0 ms.

Kekurangan

1. Permintaan ulang pada 75% TTL menimbulkan biaya tambahan.

4. Tentukan apakah akan menggunakan alamat server IPv6

Layanan HTTPDNS mendukung akses melalui IPv4 dan IPv6. Gunakan metode DNSResolver.setEnableIPv6(boolean enable) untuk menentukan apakah akan menggunakan alamat server IPv6. Jika Anda menyetel enable ke true, SDK menggunakan alamat IPv6 untuk mengakses antarmuka sisi server. Jika Anda menyetel enable ke false, SDK menggunakan alamat IPv4. Secara default, alamat IPv4 digunakan. Jika Anda mengaktifkan IPv6 dan koneksi ke layanan HTTPDNS gagal, SDK secara otomatis beralih ke alamat IPv4 dan mencoba koneksi sekali lagi.

5. Setel jumlah maksimum entri cache

DNSResolver.getInstance().setMaxCacheSize(CACHE_MAX_NUMBER); // Menyetel jumlah maksimum entri cache. Default-nya adalah 100.

Anda dapat menyesuaikan nilai count maksimum.

6. Setel protokol untuk akses server

SDK memungkinkan Anda memilih protokol (HTTP atau HTTPS) untuk permintaan resolusi DNS. Kami merekomendasikan protokol HTTPS default untuk keamanan yang lebih baik. Perhatikan bahwa HTTPDNS menagih berdasarkan permintaan resolusi, dan permintaan HTTPS ditagih lima kali lipat dari permintaan HTTP. Pilih protokol sesuai kebutuhan bisnis Anda.HTTPDNS

DNSResolver.setSchemaType(DNSResolver.HTTPS); // Mode akses default adalah HTTPS.

DNSResolver.HTTP: Mengakses antarmuka sisi server melalui HTTP.

DNSResolver.HTTPS: Mengakses antarmuka sisi server melalui HTTPS.

Pengaturan lanjutan

1. Aktifkan atau nonaktifkan logging debug SDK

DNSResolver.setEnableLogger(true); // Log debug SDK dinonaktifkan secara default.

Anda dapat mengaktifkan atau menonaktifkan log debug SDK. true mengaktifkan logging debug, dan false menonaktifkannya.

2. Tentukan apakah akan mengaktifkan HTTPDNS ke DNS lokal secara otomatis saat resolusi HTTPDNS gagal

DNSResolver.setEnableLocalDns(true); // Secara default, fallback otomatis ke DNS lokal diaktifkan ketika resolusi HTTPDNS gagal.

3. Aktifkan atau nonaktifkan Short Mode

DoH JSON API HTTPDNS mengembalikan data dalam dua format: JSON lengkap dan array IP ringkas. Anda dapat memanggil DNSResolver.setEnableShort(boolean enable) untuk mengaktifkan atau menonaktifkan mode short. Secara default, mode short dinonaktifkan.

DNSResolver.setEnableShort(true); // Nilai default-nya adalah false. Anda tidak perlu menyetel parameter ini.
Penting

Dalam mode short, SDK memanggil layanan HTTPDNS dan mengembalikan array IP yang lebih sederhana. Hal ini mengurangi jumlah data respons dan cocok untuk skenario yang sensitif terhadap trafik jaringan.

4. Tentukan apakah akan mengaktifkan cache yang tidak kedaluwarsa

DNSResolver.setImmutableCacheEnable(false); // Secara default, cache yang tidak kedaluwarsa dinonaktifkan.
Penting

SDK menyediakan tiga mekanisme pembaruan cache:

  • Cache tidak pernah kedaluwarsa: Saat diaktifkan, fitur ini memperlakukan cache sebagai selalu valid selama waktu proses aplikasi dengan melewati pemeriksaan kedaluwarsa dan operasi pembaruan. Anda tidak perlu menyetel setKeepAliveDomains untuk memperbarui cache secara aktif, yang meminimalkan jumlah resolusi pengguna.

    Metode: DNSResolver.setImmutableCacheEnable(boolean var0)

    Saat parameter var0 bernilai true, fitur cache tidak pernah kedaluwarsa diaktifkan. Saat var0 bernilai false, fitur ini dinonaktifkan.

  • Pembaruan cache aktif: Fitur ini memastikan bahwa resolusi mengenai catatan cache terbaru. Saat resolusi otoritatif untuk suatu domain berubah, mekanisme ini memastikan bahwa permintaan resolusi tidak hanya mengenai cache untuk mengurangi latensi DNS tetapi juga mengambil catatan terbaru. Saat 75% TTL domain berlalu, SDK secara otomatis memicu kueri resolusi untuk memperbarui cache. Kami menyarankan agar Anda membatasi jumlah domain yang diaktifkan pembaruan aktifnya hingga 10.

    Metode: DNSResolver.setKeepAliveDomains(String[] var1)

    Deskripsi: var1 adalah array string nama domain yang perlu diperbarui secara proaktif.

  • Pembaruan cache pasif:

    Saat Anda memanggil dua metode berikut untuk mendapatkan hasil resolusi, cache diperbarui secara pasif:

    • Metode getIPsV4ByHost(String hostName) mengambil array catatan IPv4 untuk hostName yang ditentukan. Jika cache tidak kosong dan masih dalam TTL-nya, metode ini langsung mengembalikan hasil cache. Jika tidak, metode ini terlebih dahulu mengambil hasil resolusi terbaru melalui permintaan jaringan, lalu mengembalikan hasil tersebut dan memperbarui cache. Metode ini sering digunakan dalam skenario yang memerlukan hasil resolusi sangat akurat.

    • Metode getIpv4ByHostFromCache(String hostName, boolean isAllowExp) mengambil array catatan IPv4 untuk hostName dari cache. Berdasarkan nilai parameter isAllowExp, metode ini menentukan apakah akan mengembalikan hasil resolusi kedaluwarsa dari cache. Kami menyarankan Anda menggunakan metode ini bersama metode preload saat startup aplikasi untuk memastikan hasil resolusi terbaru dicache.

      Jika isAllowExp disetel ke true, data lama dikembalikan meskipun cache telah kedaluwarsa (null dikembalikan jika cache kosong), dan cache diperbarui menggunakan permintaan asinkron. Jika parameter ini disetel ke false, null dikembalikan saat cache kedaluwarsa atau kosong, dan cache diperbarui menggunakan permintaan asinkron.

    Pola yang direkomendasikan:

    String[] IPArray = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
            if (IPArray == null || IPArray.length == 0){
                IPArray = mDNSResolver.getIPsV4ByHost(hostname);
            }

5. Aktifkan atau nonaktifkan cache

DNSResolver.setEnableCache(true); // Cache diaktifkan secara default.

Anda dapat mengaktifkan atau menonaktifkan fitur cache. true mengaktifkan fitur, dan false menonaktifkannya.

6. Aktifkan atau nonaktifkan pengujian kecepatan IP. Fitur ini dinonaktifkan secara default di versi 2.3.0 dan sebelumnya, serta diaktifkan secara default di versi 2.3.1 dan seterusnya.

DNSResolver.setEnableSpeedTest(false); // Dinonaktifkan secara default di v2.3.0 dan sebelumnya; diaktifkan secara default di v2.3.1 dan seterusnya.

Anda dapat mengaktifkan atau menonaktifkan pengujian kecepatan IP. true mengaktifkan fitur, dan false menonaktifkannya.

7. Setel nomor port untuk pengujian kecepatan IP melalui pemantauan socket

DNSResolver.setSpeedPort(DNSResolver.PORT_80);

Anda dapat menyetel nomor port untuk pengujian kecepatan IP berbasis socket. Default-nya adalah 80.

8. Tentukan apakah akan mempartisi cache domain berdasarkan jaringan ISP

DNSResolver.setIspEnable(true); // Secara default, cache domain dipartisi berdasarkan jaringan ISP.

Menentukan apakah akan mempartisi cache domain berdasarkan jaringan ISP. Jika diaktifkan, data cache domain disimpan secara terpisah untuk lingkungan jaringan berbeda dan tidak memengaruhi lingkungan lainnya. Jika dinonaktifkan, satu cache domain digunakan untuk semua lingkungan jaringan.

9. Setel TTL maksimum untuk cache negatif

DNSResolver.setMaxNegativeCache(MAX_NEGATIVE_CACHE); // Menyetel TTL maksimum untuk cache negatif. Default-nya adalah 30 detik.

Anda dapat menyetel TTL maksimum untuk cache negatif sesuai kebutuhan bisnis Anda. Cache negatif adalah entri cache tidak valid yang dihasilkan ketika tidak ada alamat IP yang dikonfigurasi untuk suatu domain dan tidak ada alamat IP yang dikembalikan sebagai hasil resolusi.

10. Setel TTL maksimum untuk cache

DNSResolver.setMaxTtlCache(MAX_TTL_CACHE); // Menyetel TTL maksimum untuk cache. Nilai default-nya adalah 3.600 detik.

SDK memungkinkan Anda menyetel TTL maksimum untuk cache. Jika waktu ini disetel, TTL maksimum cache tidak akan melebihi nilai ini. Default-nya adalah 3.600 detik.

11. Setel informasi subnet klien

DNSResolver.setEdnsSubnet("1.2.XX.XX/24");

setEdnsSubnet digunakan untuk mendukung fitur EDNS Client Subnet (ECS) (RFC 7871), yang meneruskan informasi subnet pengguna ke DNS otoritatif untuk resolusi DNS dan penjadwalan trafik yang lebih tepat. Mask yang lebih panjang memberikan informasi alamat yang lebih akurat, sedangkan mask yang lebih pendek meningkatkan privasi pengguna. Kami menyarankan Anda menggunakan panjang mask /24.

Catatan

Parameter ini dirancang untuk skenario di mana proxy DNS menggunakan DoH JSON API. Dalam skenario ini, pengguna mengirim kueri DNS ke proxy DNS, dan proxy menggunakan parameter ini untuk meneruskan informasi subnet pengguna ke HTTPDNS lalu ke server DNS otoritatif.

Sebagai contoh, jika Anda memanggil DNSResolver.setEdnsSubnet("1.2.XX.XX/24"), server otoritatif menerima informasi awalan berdasarkan alamat 1.2.XX.XX/24 untuk membantu Anda memilih tautan DNS.

12. Setel periode timeout untuk resolusi nama domain

Atribut timeout menentukan timeout untuk resolusi nama domain. Timeout default-nya adalah 3 detik. Anda dapat menyetel timeout kustom. Nilai antara 2 detik hingga 5 detik direkomendasikan.

DNSResolver.setTimeout(3);

13. Setel jumlah maksimum resolusi konkuren (didukung di v2.3.2 dan seterusnya)

Menyetel jumlah maksimum permintaan konkuren untuk resolusi DNS asinkron, seperti pre-resolusi dan refresh cache asinkron. Rentang valid: [1, 50]. Nilai default: 10.

DNSResolver.setMaxConcurrentResolveCount(10);

14. Dapatkan SessionId untuk troubleshooting

Parameter sessionId dihasilkan saat aplikasi dimulai dan tetap tidak berubah sepanjang siklus hidupnya. Semua permintaan resolusi HTTPDNS dalam siklus hidup aplikasi yang sama membawa sessionId yang sama. Server mencatat parameter ini dan menghasilkan indeks. Gunakan sessionId untuk melacak siklus hidup aplikasi dan memecahkan masalah spesifik aplikasi.

public static String getSessionId()

15. Log Output Callback

Callback ini menerima log yang dikeluarkan oleh SDK.

HttpDnsLog.setLogger(new ILogger() {
  @Override
  public void log(String msg) {
      Log.d("HttpDnsLogger:", msg);
  }
});

Konfigurasi ProGuard

   -keep class com.alibaba.pdns.** {*;}

API Layanan

  /**
   * Pre-load resolusi nama domain berdasarkan lingkungan jaringan yang terdeteksi secara otomatis (IPv4-only, IPv6-only, atau dual-stack).
   * Di lingkungan jaringan dual-stack, hasil resolusi IPv4 dan IPv6 keduanya di-pre-load. Anda dapat memanggil metode ini selama inisialisasi SDK saat startup aplikasi.
   * Metode ini menyimpan hasil resolusi di cache untuk mengurangi latensi resolusi nama domain berikutnya.
   *
   * @param domains Nama domain yang akan di-pre-load.
   */
   public void preLoadDomains(final String[] domains)

    /**
     * Pre-load resolusi domain untuk tipe catatan tertentu (IPv4 atau IPv6). 
     * Anda dapat memanggil metode ini selama inisialisasi SDK saat startup aplikasi. Metode ini menyimpan hasil resolusi di cache untuk mengurangi latensi resolusi berikutnya.
     *
     * @param qType Tipe catatan yang akan di-pre-load, seperti IPv4 atau IPv6.
     * @param domains Nama domain yang akan di-pre-load.
     */
    public void preLoadDomains(String qType, final String[] domains)
   /**
   * Mendapatkan data resolusi untuk nama domain berdasarkan lingkungan jaringan yang terdeteksi secara otomatis (IPv4-only, IPv6-only, atau dual-stack).
   * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
   * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
   *
   * @param host Nama domain yang ingin Anda resolusi.
   * @return Array alamat IP optimal berdasarkan lingkungan jaringan saat ini.
   */
    public String[] getIpsByHost(String host)

/**
    * Mendapatkan array catatan IPv4 yang sesuai dengan hostname.
    * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
    * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
    *
    * @param hostName Hostname, seperti www.example.com.
    * @return Array alamat IPv4 yang sesuai dengan hostname.
    */
  public  String[] getIPsV4ByHost(String hostName) 

   /**
    * Mendapatkan array catatan IPv6 yang sesuai dengan hostname.
    * @param hostName Hostname, seperti www.example.com.
    * @return Array alamat IPv6 yang sesuai dengan hostname.
    */
  public String[] getIPsV6ByHost(String hostName) 

  

  /**
   * Mendapatkan array alamat IP untuk nama domain yang telah diresolusi dari cache berdasarkan lingkungan jaringan yang terdeteksi secara otomatis (IPv4-only, IPv6-only, atau dual-stack).
   * Jika cache kosong, metode ini mengembalikan null dan memulai kueri asinkron. Hasil kueri kemudian disimpan di cache.
   * Jika hasil resolusi ada di cache dan Anda mengizinkan pengembalian hasil kedaluwarsa, alamat IP kedaluwarsa dikembalikan, dan cache diperbarui secara asinkron.
   * Jika Anda tidak mengizinkan pengembalian hasil kedaluwarsa dan hasil cache telah kedaluwarsa, metode ini mengembalikan null lalu memperbarui cache secara asinkron.
   *
   * @param host Host yang akan dikueri, seperti www.example.com.
   * @param isAllowExp Menentukan apakah akan mengembalikan data resolusi domain yang kedaluwarsa.
   * @return Array alamat IP yang di-cache untuk host yang telah diresolusi.
   */
   public String[] getIpsByHostFromCache(String host, boolean isAllowExp)
   
    /**
     * Mendapatkan array alamat IP tipe catatan IPv4 untuk nama domain yang telah diresolusi dari cache.
     * Jika cache kosong, metode ini mengembalikan null dan memulai kueri asinkron. Hasil kueri kemudian disimpan di cache.
     * Jika hasil resolusi ada di cache dan Anda mengizinkan pengembalian hasil kedaluwarsa, alamat IP kedaluwarsa dikembalikan, dan cache diperbarui secara asinkron.
     * Jika Anda tidak mengizinkan pengembalian hasil kedaluwarsa dan hasil cache telah kedaluwarsa, metode ini mengembalikan null lalu memperbarui cache secara asinkron.
     *
     * @param host Host yang akan dikueri, seperti www.example.com.
     * @param isAllowExp Menentukan apakah akan mengembalikan data resolusi domain yang kedaluwarsa.
     * @return Array alamat IP tipe catatan IPv4 dari cache setelah host diresolusi.
     */
    public String[] getIpv4ByHostFromCache(String host , boolean isAllowExp)

    /**
     * Mendapatkan array alamat IP tipe catatan IPv6 untuk nama domain yang telah diresolusi dari cache.
     * Jika cache kosong, metode ini mengembalikan null dan memulai kueri asinkron. Hasil kueri kemudian disimpan di cache.
     * Jika hasil resolusi ada di cache dan Anda mengizinkan pengembalian hasil kedaluwarsa, alamat IP kedaluwarsa dikembalikan, dan cache diperbarui secara asinkron.
     * Jika Anda tidak mengizinkan pengembalian hasil kedaluwarsa dan hasil cache telah kedaluwarsa, metode ini mengembalikan null lalu memperbarui cache secara asinkron.
     *
     * @param host Host yang akan dikueri, seperti www.example.com.
     * @param isAllowExp Menentukan apakah akan mengembalikan data resolusi domain yang kedaluwarsa.
     * @return Array alamat IP tipe catatan IPv6 dari cache setelah host diresolusi.
     */
    public String[] getIpv6ByHostFromCache(String host , boolean isAllowExp)

  /**
  * Mendapatkan array objek DomainInfo untuk catatan IPv4 yang sesuai dengan URL.
  * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
  * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
  *
  * @param url URL, seperti http://www.example.com.
  * @return Array objek DomainInfo tipe IPv4 yang sesuai dengan URL.
  */
  public DomainInfo[] getIPsV4DInfoByUrl(String url) 

  Catatan: URL dalam objek DomainInfo adalah URL yang host-nya secara otomatis diganti dengan alamat IP. Anda tidak perlu mengganti host di URL secara manual.

  /**
   * Mendapatkan array objek DomainInfo untuk catatan IPv6 yang sesuai dengan URL.
   * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
   * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
   * 
   * @param url URL, seperti http://m.example.com.
   * @return Array objek DomainInfo tipe IPv6 yang sesuai dengan URL.
   */
   public DomainInfo[] getIPsV6DInfoByUrl(String url) 

  /**
    * Mendapatkan objek DomainInfo untuk catatan IPv4 yang sesuai dengan URL tertentu.
    * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
    * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
    *
    * @param url URL, seperti http://m.example.com.
    * @return Objek DomainInfo acak dari kumpulan objek DomainInfo tipe IPv4 yang sesuai dengan URL.
    */
    public DomainInfo getIPV4DInfoByUrl(String url) 


  /**
    * Mendapatkan objek DomainInfo untuk catatan IPv6 yang sesuai dengan URL tertentu.
    * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
    * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
    *
    * @param url URL, seperti http://www.example.com.
    * @return Objek DomainInfo acak dari kumpulan objek DomainInfo tipe IPv6 yang sesuai dengan URL.
    */
   public DomainInfo getIPV6DInfoByUrl(String url) 

   Catatan: Objek DomainInfo yang dikembalikan membungkus properti berikut.

  /**
   * ID auto-increment untuk domain akses.
    */
    public String id = null;

   /**
    * URL yang dapat digunakan langsung. Host di URL diganti dengan alamat IP.
    */
     public String url = null;

    /**
    * Nama layanan tujuan yang akan disetel di Header HTTP.
    */
    public String host = "";

   /**
    * Body konten yang dikembalikan.
    */
   public String data = null;

   /**
    * Waktu permintaan dimulai.
    */
   public String startTime = null;

   /**
    * Waktu permintaan berakhir. Jika permintaan timeout, nilai ini null.
    */
   public String stopTime = null; 

   /**
   * Kode status yang dikembalikan oleh server, seperti 200, 404, atau 500. 
   */
   public String code = null;

  /**
    * Mendapatkan catatan IPv4 yang sesuai dengan hostname.
    * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
     * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
  
    * @param hostName Hostname, seperti www.example.com.
    * @return Alamat IPv4 acak dari kumpulan alamat IPv4 yang sesuai dengan hostname. Jika pengujian kecepatan IP diaktifkan, alamat IPv4 optimal dikembalikan.
    */
  public String getIPV4ByHost(String hostName) 

   /**
    * Mendapatkan catatan IPv6 yang sesuai dengan hostname.
    * Jika hasil resolusi yang belum kedaluwarsa ada di cache, hasil dari cache dikembalikan.
    * Jika cache kosong atau hasil cache telah kedaluwarsa, permintaan jaringan sinkron dikirim ke server untuk mendapatkan hasil resolusi rekursif. Hasil tersebut kemudian dikembalikan dan disimpan di cache.
  
    * @param hostName Hostname, seperti www.example.com.
    * @return Alamat IPv6 acak dari kumpulan alamat IPv6 yang sesuai dengan hostname. Jika pengujian kecepatan IP diaktifkan, alamat IPv6 optimal dikembalikan.
    */
   public String getIPV6ByHost(String hostName) 
      

    /**
     * Mendapatkan statistik tentang permintaan HTTPDNS yang berhasil dan gagal.
     *
     * @return String array JSON dari statistik resolusi untuk semua nama domain.
     */
    public String getRequestReportInfo()
    
     /**
     * Menyetel nama domain untuk cache keep-alive. Resolusi nama domain yang dikonfigurasi secara otomatis dipicu saat 75% TTL berlalu. Hal ini memastikan bahwa permintaan resolusi untuk nama domain yang dikonfigurasi selalu mengenai cache dan meningkatkan efisiensi resolusi SDK.
     * Kami menyarankan agar Anda tidak mengonfigurasi terlalu banyak nama domain untuk fitur ini. Batas saat ini adalah 10 nama domain. Fitur ini dikonfigurasi secara independen dari fitur pre-resolusi.
     *
     * @param persistentCacheDomains
     */
    public synchronized static void setKeepAliveDomains(String[] persistentCacheDomains) {
    
     /**
     * Menghapus cache untuk nama domain tertentu. Jika hostname null, cache untuk semua nama domain dihapus.
     *
     * @param domains Array nama domain yang cachenya ingin Anda hapus.
     */
    public void clearHostCache(String[] domains){

Contoh API

URL: Alamat akses yang diteruskan, misalnya, http://www.example.com.

 String hostname = "www.taobao.com";
 String url = "http://www.taobao.com";

1. Dapatkan data IP optimal untuk lingkungan jaringan saat ini

String[] ip = DNSResolver.getInstance().getIpsByHost(hostname); // Mendapatkan IP resolusi domain optimal untuk jaringan saat ini.

2. Pre-load resolusi domain berdasarkan lingkungan jaringan saat ini

DNSResolver.getInstance().preLoadDomains(domains); // Menyetel nama domain untuk pre-resolusi. Ganti placeholder domain dengan domain yang ingin Anda resolusi oleh HTTPDNS.

3. Baca data resolusi domain dari cache berdasarkan lingkungan jaringan saat ini

String[] ip = DNSResolver.getInstance().getIpsByHostFromCache(hostname,true); // Mendapatkan data resolusi domain dari cache untuk lingkungan jaringan saat ini.

4. Dapatkan alamat IPv4

String IPV4 = DNSResolver.getInstance().getIPV4ByHost(hostname); // Mendapatkan alamat IPv4 yang telah diresolusi.

5. Dapatkan alamat IPv6

String IPV6 =  DNSResolver.getInstance().getIPV6ByHost(hostname); // Mendapatkan alamat IPv6 yang telah diresolusi.

6. Dapatkan alamat IPv4 yang telah diresolusi dari cache

String[] IPV4 =  DNSResolver.getInstance().getIpv4ByHostFromCache(hostname , true); // Mendapatkan alamat IPv4 yang telah diresolusi dari cache.

7. Dapatkan alamat IPv6 yang telah diresolusi dari cache

String[] IPV6 =  DNSResolver.getInstance().getIpv6ByHostFromCache(hostname , true); // Mendapatkan alamat IPv6 yang telah diresolusi dari cache.

8. Dapatkan objek DomainInfo yang sesuai dengan URL

DomainInfo dinfo = DNSResolver.getInstance().getIPV4DInfoByUrl(url); // Mendapatkan URL yang telah diganti.

9. Hapus hasil resolusi domain tertentu dari cache

DNSResolver.getInstance().clearHostCache(hostName); // Menghapus cache untuk domain tertentu. Jika hostName disetel ke null, cache untuk semua domain dihapus.

10. Dapatkan statistik tentang permintaan HTTPDNS yang berhasil dan gagal

String reportInfo = DNSResolver.getInstance().getRequestReportInfo(); // Mendapatkan statistik tentang permintaan yang berhasil dan gagal.

Tabel berikut menjelaskan bidang dalam array string JSON statistik resolusi domain.

 [
      {
         "avgRtt":"1",                         // Waktu resolusi domain rata-rata, dalam milidetik (ms).
         "degradeLocalDnsCount": 0,            // Jumlah fallback ke DNS lokal.                       
         "domainName":"www.example.com",       // Nama domain yang diresolusi.
         "hitDnsCacheCount": 1,                // Jumlah hit cache.
         "httpabnormalCount": 0,               // Jumlah permintaan rekursif yang gagal.
         "isp": "China Mobile",                // Nama ISP.
         "localDnsResolveErrCount": 0,         // Jumlah kegagalan resolusi DNS lokal.
         "maxRtt": 8.0,                        // Waktu resolusi domain maksimum, dalam milidetik (ms).          
         "nonetworkCount": 0,                  // Jumlah kali jaringan tidak tersedia.
         "permissionErrCount": 0,              // Jumlah kegagalan otentikasi pengguna.
         "queryType": 1,                       // Tipe IP. 1 menunjukkan IPv4, dan 28 menunjukkan IPv6.
         "recursiveReqCount": 1,               // Jumlah kueri rekursif.
         "reqParameterErrCount": 0,            // Jumlah kesalahan format parameter permintaan.
         "reqPathErrCount": 0,                 // Jumlah kesalahan URL.
         "reqServerErrCount": 0,               // Jumlah kesalahan sisi server DNS.
         "reqTimeoutCount": 0,                 // Jumlah kesalahan timeout layanan DNS.
         "resolveSuccessCount": 1,             // Jumlah resolusi yang berhasil.
         "timeoutCount": 0,                    // Jumlah kesalahan timeout jaringan.
         "utfNetWorkErroNum": 0                // Jumlah kesalahan timeout pelaporan data.
      }
         ......
 ]
Penting

Statistik untuk permintaan resolusi domain HTTPDNS diagregasi berdasarkan lingkungan jaringan, nama domain, dan tipe permintaan.

Contoh

public class MainActivity extends AppCompatActivity {
   private Button button;
   private TextView tvInfo;
   private TextView tvResult;
   private String hostUrl = "http://www.taobao.com"; // Ganti ini dengan hostUrl yang ingin Anda resolusi.
   private String hostName = "www.taobao.com"; // Ganti ini dengan hostName yang ingin Anda resolusi.
   private static final String TAG = "PDnsDemo";
   private static ExecutorService pool = Executors.newSingleThreadExecutor();
   private static final String PDNS_RESULT = "pdns_result";
   private static final int SHOW_CONSOLE_TEXT = 10000;
   private Handler mHandler;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.demo_activity_main);
       init();
       initHandler();
   }
 private void init() {
       tvInfo = findViewById(R.id.tv_respons_info);
       tvResult = findViewById(R.id.tv_respons);
       button = findViewById(R.id.btn_onclik);
       button.setOnClickListener(new View.OnClickListener() {
           public void onClick(View view) {
               new Thread(new Runnable() {
                      @Override
                      public void  run() {
                      // Panggil metode getIPV4ByHost di SDK HTTPDNS untuk mendapatkan alamat IP yang diresolusi dari nama domain target.
                      String ip = DNSResolver.getInstance().getIPV4ByHost(hostName);
                      if(ip != null){
                         tvInfo.setText("Alamat IP yang diresolusi untuk domain tersebut adalah: "+ ip);
                      }
                      // Panggil metode getIPV4DInfoByUrl di SDK HTTPDNS untuk mendapatkan URL dari objek DomainInfo yang diresolusi. 
                      // Host di URL ini diganti dengan alamat IP.
                      DomainInfo dinfo = DNSResolver.getInstance().getIPV4DInfoByUrl(hostUrl);
                      if (dinfo != null) {
                           showResponse(dinfo);
                      }
                   }
               }).start();
           }
       });
   }
   private void initHandler() {
       mHandler = new Handler() {
           @Override
           public void handleMessage(Message msg) {
               switch (msg.what)  {
                   case SHOW_CONSOLE_TEXT:
                       tvResult.setText(msg.getData().getString(PDNS_RESULT) + "\n");
                       break;
               }
           }
       };
   }
   private void showResponse(final DomainInfo dinfo) {
                // Mengirim permintaan jaringan.
               String requestUrl = dinfo.url;
               HttpURLConnection conn = null;
               try {
                   URL url = new URL(requestUrl);
                   conn = (HttpURLConnection) url.openConnection();
                   // Saat Anda menggunakan alamat IP untuk akses, Anda harus menyetel bidang Host di Header permintaan HTTP ke nama domain asli.
                   conn.setRequestProperty("Host", url.getHost()); // Menyetel bidang Host di Header permintaan HTTP.
                   DataInputStream dis = new DataInputStream(conn.getInputStream());
                   int len;
                   byte[] buff = new byte[4096];
                   StringBuilder response = new StringBuilder();
                   while ((len = dis.read(buff)) != -1) {
                       response.append(new String(buff, 0, len));
                   }
                   Log.d(TAG, "Respons: " + response.toString());
                   dis.close();
                   sendMessage(response.toString());
               } catch (IOException e) {
                   e.printStackTrace();
               }finally {
                   if (conn != null) {
                       conn.disconnect();
                   }
               }
           }
   private void sendMessage(String message) {
       if (mHandler != null) {
               Message msg = mHandler.obtainMessage();
               Bundle bundle = new Bundle();
               bundle.putString(PDNS_RESULT, message);
               msg.setData(bundle);
               msg.what = SHOW_CONSOLE_TEXT;
               mHandler.sendMessage(msg);
       }
   }
}

public class DnsCacheApplication extends Application {
    
    private String accountId = "Your Account ID"; // Setel Account ID Anda dari Konsol.
    private String accessKeyId = "Your AccessKey ID"; // Setel AccessKey ID Anda dari Konsol.
    private String accessKeySecret = "Your AccessKey Secret"; // Setel AccessKey Secret Anda dari Konsol.

    @Override
    public void onCreate() {
       super.onCreate();
       // Setel Account ID, AccessKey ID, dan AccessKey Secret untuk akses SDK.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       // Menyetel nama domain untuk cache keep-alive. Resolusi nama domain yang dikonfigurasi secara otomatis dipicu saat 75% TTL-nya berlalu untuk memastikan permintaan resolusi untuk nama domain tersebut selalu mengenai cache.
       DNSResolver.setKeepAliveDomains(new String[]{"your-domain-1","your-domain-2",...}); 
       // Pre-load domain tertentu ke alamat IPv4. Ganti placeholder domain dengan domain yang ingin Anda resolusi.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}

Praktik terbaik

Untuk kinerja optimal, gunakan pre-resolusi dan izinkan respons kedaluwarsa.

Dalam skenario dengan persyaratan tinggi terhadap kinerja jaringan, Anda dapat menggabungkan pre-resolusi dengan strategi mengizinkan respons kedaluwarsa untuk secara signifikan meningkatkan kecepatan resolusi DNS dan bahkan mencapai resolusi "latensi nol".

Berkat cache bawaan SDK, permintaan resolusi berikutnya untuk domain yang telah di-pre-load dapat langsung mengenai cache. Hal ini menghindari round-trip jaringan dan sangat meningkatkan pengalaman pengguna.

1. Pre-resolusi

Aktifkan caching dan pre-resolve domain kunci. Kami menyarankan Anda melakukan operasi ini saat aplikasi dimulai.

Pada metode onCreate() Application, lakukan pra-resolusi nama-nama domain yang digunakan oleh aplikasi Anda dan cache hasilnya di memori lokal.

1. Skenario IPv4-only

//********Untuk skenario IPv4-only*******
public class DnsCacheApplication extends Application{
    private String accountId = "Your Account ID"; // Setel Account ID Anda dari Konsol.
    private String accessKeyId = "Your AccessKey ID"; // Setel AccessKey ID Anda dari Konsol.
    private String accessKeySecret = "Your AccessKey Secret"; // Setel AccessKey Secret Anda dari Konsol.

    @Override
    public void onCreate() {
       super.onCreate();
       // Setel Account ID, AccessKey ID, dan AccessKey Secret untuk akses SDK.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       DNSResolver.setEnableCache(true); // Aktifkan caching. Nilai default: true. 
       // Tipe catatan IPv4 untuk pre-resolusi.    
       // Pre-load domain tertentu ke alamat IPv4. Ganti placeholder domain dengan domain yang ingin Anda resolusi oleh HTTPDNS.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}

2. Dukungan IPv6

//********Untuk skenario yang memerlukan dukungan IPv6*******
public class DnsCacheApplication extends Application{
    private String accountId = "Your Account ID"; // Setel Account ID Anda dari Konsol.
    private String accessKeyId = "Your AccessKey ID"; // Setel AccessKey ID Anda dari Konsol.
    private String accessKeySecret = "Your AccessKey Secret"; // Setel AccessKey Secret Anda dari Konsol.

    @Override
    public void onCreate() {
       super.onCreate();
       // Setel Account ID, AccessKey ID, dan AccessKey Secret untuk akses SDK.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       DNSResolver.setEnableCache(true); // Aktifkan caching. Nilai default: true.
       DNSResolver.setEnableIPv6(true); // Menentukan apakah akan meresolusi nama domain melalui jaringan IPv6. Nilai default: false.  
       DNSResolver.setEnableSpeedTest(true); // Menentukan apakah akan mengaktifkan pengujian kecepatan IP. Nilai default: false.
       // Tipe catatan IPv4 dan IPv6 untuk pre-resolusi.  
       // Pre-load domain tertentu ke alamat IPv4 dan IPv6. Ganti placeholder domain dengan domain yang ingin Anda resolusi oleh HTTPDNS.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4_IPV6,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}

2. Izinkan respons kedaluwarsa

Utamakan penggunaan cache untuk resolusi dan izinkan pengembalian alamat IP kedaluwarsa. Sebelum memulai permintaan jaringan, dapatkan alamat IP dari cache dan izinkan penggunaan catatan cache kedaluwarsa namun masih ada. Dengan cara ini, meskipun TTL telah berakhir, hasil tetap dapat dikembalikan segera selama cache belum dihapus. Hal ini membantu mencapai resolusi "tanpa tunggu".

1. Skenario IPv4-only

    //********Untuk skenario IPv4-only*******
    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        // Utamakan mendapatkan alamat IP dari cache. Parameter kedua, jika true, mengizinkan pengembalian catatan kedaluwarsa namun masih dapat digunakan.
        String[] IPArray = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
        if (IPArray == null || IPArray.length == 0){
            // Jika cache tidak terkena, mulai resolusi asinkron.
            IPArray = mDNSResolver.getIPsV4ByHost(hostname);
        }
        if (IPArray != null && IPArray.length > 0) {
            List<InetAddress> inetAddresses = new ArrayList<>();
            InetAddress address;
            for (String ip : IPArray) {
                address = InetAddress.getByName(ip);
                inetAddresses.add(address);
            }
            if (!inetAddresses.isEmpty()) {
                return inetAddresses;
            }
        }
        return okhttp3.Dns.SYSTEM.lookup(hostname);
    }

2. Dukungan IPv6

    //********Untuk skenario yang memerlukan dukungan IPv6*******
    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        // Utamakan mendapatkan alamat IP dari cache. Parameter kedua, jika true, mengizinkan pengembalian catatan kedaluwarsa namun masih dapat digunakan.
        String[] IPArray = mDNSResolver.getIpsByHostFromCache(hostname,true);
        if (IPArray == null || IPArray.length == 0){
            // Jika cache tidak terkena, mulai resolusi asinkron.
            IPArray = mDNSResolver.getIpsByHost(hostname);
        }
        if (IPArray != null && IPArray.length > 0) {
            List<InetAddress> inetAddresses = new ArrayList<>();
            InetAddress address;
            for (String ip : IPArray) {
                address = InetAddress.getByName(ip);
                inetAddresses.add(address);
            }
            if (!inetAddresses.isEmpty()) {
                return inetAddresses;
            }
        }
        return okhttp3.Dns.SYSTEM.lookup(hostname);
    }

Catatan

  1. Setelah mendapatkan alamat IP nama domain menggunakan HTTPDNS, klien dapat menggunakan alamat IP ini untuk mengirim permintaan layanan. Anda harus mengubah bidang Host di Header permintaan HTTP ke nama domain asli.

  2. Untuk memastikan layanan Anda berjalan sesuai harapan, jika alamat IP yang dikembalikan oleh SDK HTTPDNS untuk resolusi nama domain kosong, Anda harus menggunakan URL permintaan nama domain asli untuk melakukan permintaan fallback. Kode berikut memberikan contohnya:

    String ip = DNSResolver.getInstance().getIPV4ByHost("your-domain");
    if (ip != null) {
    	// Ganti host di URL dengan alamat IP untuk membuat permintaan API.
    }else {
    	// Gunakan URL permintaan nama domain asli untuk melakukan permintaan fallback. 
        // Dalam hal ini, gunakan URL asli yang berisi nama domain untuk membuat permintaan jaringan.
    }
  3. Untuk membantu Anda memulai dengan SDK HTTPDNS, kami menyediakan program demo yang dapat Anda unduh dan gunakan sebagai referensi. Klik di sini untuk mengunduh program demo.

  4. Setelah mengintegrasikan SDK, periksa halaman Analisis Trafik di Konsol untuk memverifikasi bahwa integrasi berhasil. Jika tidak ada trafik yang dihasilkan, periksa apakah parameter Account ID, AccessKey ID, dan AccessKey Secret telah disetel dengan benar.

DNS On-premises

Mulai v2.3.0, SDK Android HTTPDNS menambahkan dukungan untuk penyebaran DNS on-premises.

Mode DNS on-premises cocok untuk skenario dengan persyaratan tinggi terhadap kepatuhan data dan kebijakan resolusi kustom, seperti keuangan, pemerintahan, dan perusahaan Internet besar. SDK mendukung empat mode penyebaran khas: hanya DNS cloud publik, hanya DNS on-premises, dan hybrid primary-standby (DNS cloud publik dan DNS on-premises saling menjadi fallback). Hal ini memungkinkan adaptasi fleksibel terhadap arsitektur layanan yang berbeda.

Kemampuan inti

  • Dukungan penyebaran on-premises: Mendukung konfigurasi endpoint layanan DNS on-premises menggunakan alamat IPv4/IPv6 atau nama domain host.

  • Otentikasi dua arah: Mekanisme ini menandatangani permintaan dengan accessKeyId dan accessKeySecret khusus pelanggan untuk memastikan komunikasi aman.

  • Pemutusan sirkuit dan pemeriksaan kesehatan: Jika node DNS on-premises gagal 3 kali berturut-turut atau lebih, pemutusan sirkuit dipicu secara otomatis. Setelah itu, ketersediaannya diperiksa setiap menit menggunakan healthCheckDomain yang ditentukan. Node tersebut diaktifkan kembali secara otomatis setelah pulih.

  • Kontrol validasi sertifikat: Mulai versi 2.3.1.beta, Anda dapat menonaktifkan validasi sertifikat TLS untuk pengujian DNS on-premises. Versi beta hanya untuk pengujian dan tidak boleh digunakan di produksi. Unduh versi beta

  • Fallback cerdas: Jika DNS primer (DNS cloud publik atau DNS on-premises) gagal meresolusi nama domain dan jumlah kegagalannya mencapai ambang batas yang ditentukan, sistem secara otomatis beralih ke DNS standby untuk memastikan ketersediaan tinggi untuk resolusi.

  • Kompatibilitas API mulus: Baik Anda menggunakan DNS cloud publik maupun DNS on-premises, cara memanggil API resolusi tetap sama. Anda tidak perlu memodifikasi logika bisnis Anda.

Konfigurasi

1. Hanya DNS cloud publik

Mode ini untuk pengguna SaaS standar yang belum menyebar DNS on-premises.

DNSResolver.Init(this, accountID, accessKeyId, accessKeySecret);

2. Hanya DNS on-premises

Mode ini untuk pelanggan yang sepenuhnya bergantung pada DNS on-premises mereka.

DNSResolver.InitFusionDNS(this,new String[]{"1.1.X.X","2.2.X.X"},null,null,"443", "check.example.com", "your_fusion_ak", "your_fusion_sk");
// Opsional: Nonaktifkan validasi sertifikat (hanya untuk lingkungan pengujian, memerlukan versi SDK beta, misalnya 2.3.1.beta).
// DNSResolver.setEnableCertificateValidation(false);

3. Primer: Cloud publik, standby: On-premises

Jika HTTPDNS publik Alibaba Cloud primer gagal meresolusi nama domain, sistem secara otomatis fallback ke DNS on-premises.

// Primer: DNS cloud publik
DNSResolver.Init(this, accountID, accessKeyId, accessKeySecret);
    
// Standby: DNS on-premises
DNSResolver.InitFusionDNS(this,new String[]{"1.1.X.X","2.2.X.X"},null,null,"443", "check.example.com", "your_fusion_ak", "your_fusion_sk");
// Opsional: Nonaktifkan validasi sertifikat (hanya untuk lingkungan pengujian, memerlukan versi SDK beta, misalnya 2.3.1.beta).
// DNSResolver.setEnableCertificateValidation(false);

4. Primer: On-premises, standby: Cloud publik

Gunakan DNS on-premises sebagai DNS primer. Jika DNS on-premises gagal meresolusi nama domain, sistem secara otomatis fallback ke DNS cloud publik Alibaba Cloud.

// Primer: DNS on-premises
DNSResolver.InitFusionDNS(this,new String[]{"1.1.X.X","2.2.X.X"},null,null,"443", "check.example.com", "your_fusion_ak", "your_fusion_sk");
// Opsional: Nonaktifkan validasi sertifikat (hanya untuk lingkungan pengujian, memerlukan versi SDK beta, misalnya 2.3.1.beta).
// DNSResolver.setEnableCertificateValidation(false);

// Standby: DNS cloud publik
DNSResolver.Init(this, accountID, accessKeyId, accessKeySecret);

API Baru

Untuk mendukung penyebaran on-premises dan pemulihan bencana ketersediaan tinggi untuk DNS on-premises, SDK menambahkan tiga antarmuka inti berikut. Gunakan antarmuka ini untuk mengonfigurasi layanan DNS on-premises, mengontrol kebijakan keamanan, dan menerapkan fallback primer-standby otomatis.

1. Konfigurasi endpoint dan otentikasi

    /** Untuk DNS on-premises yang digunakan dalam penyebaran on-premises. Anda tidak perlu memanggil metode ini jika hanya menggunakan DNS publik.
     *
     * Menyetel alamat dan informasi otentikasi untuk server DNS on-premises.
     * Pelanggan menggunakan antarmuka ini untuk meneruskan alamat dan kredensial otentikasi server DNS privat.
     * SDK menggunakan informasi ini untuk memulai permintaan.
     * @param ctx Konteks.
     * @param serverIpv4Arr Array alamat IPv4 (bisa null).
     * @param serverIpv6Arr Array alamat IPv6 (bisa null).
     * @param serverHostArr Array nama domain host (bisa null).
     * @param port Port layanan, seperti "443". Jika null, port default "443" digunakan.
     * @param healthCheckDomain Nama domain yang digunakan untuk pemeriksaan kesehatan setelah pemutusan sirkuit dipicu. Saat layanan resolusi gagal berturut-turut lebih dari tiga kali, pemutusan sirkuit dipicu, dan alamat IP layanan tersebut memasuki status healthCheck. Permintaan berikutnya tidak akan dikirim ke layanan ini. 
     *                          Timer berjalan setiap menit untuk memanggil API resolusi menggunakan healthCheckDomain ini guna memeriksa apakah layanan resolusi tersedia. Jika probe berhasil, layanan kembali ke status alive, dan permintaan berikutnya dapat dikirim ke layanan ini.
     * @param accessKeyId accessKeyId privat pelanggan, yang digunakan untuk otentikasi.
     * @param accessKeySecret accessKeySecret privat pelanggan, yang digunakan untuk otentikasi.
     */
    public static void InitFusionDNS(Context ctx,String[] serverIpv4Arr, String[] serverIpv6Arr, String[] serverHostArr, String port, String healthCheckDomain, String accessKeyId, String accessKeySecret)

2. Kontrol validasi sertifikat TLS

Validasi TLS di versi beta

    /** Untuk DNS on-premises yang digunakan dalam penyebaran on-premises. Anda tidak perlu memanggil metode ini jika hanya menggunakan DNS publik.
     *
     * Menentukan apakah akan mengaktifkan validasi sertifikat untuk DNS on-premises. Nilai default: true. Jika server tidak dikonfigurasi dengan sertifikat domain atau sertifikat IP, Anda dapat menyetel parameter ini ke false untuk pengujian. Di lingkungan produksi, kami sangat menyarankan Anda menyetel parameter ini ke true. Jika tidak, risiko keamanan mungkin timbul.
     * @param enable Setel parameter ini ke true untuk mengaktifkan validasi sertifikat (default), atau false untuk menonaktifkannya.
     */
    public static void setEnableCertificateValidation(boolean enable)

3. Setel ambang batas fallback

    /** Jika Anda mengonfigurasi DNS cloud publik dan DNS on-premises, Anda dapat menentukan jumlah kali kegagalan resolusi DNS pada DNS primer sebelum sistem secara otomatis fallback ke DNS standby. Jika Anda hanya mengonfigurasi satu jenis DNS, Anda tidak perlu memanggil metode ini.
     *
     * Menentukan jumlah kali kegagalan resolusi DNS pada DNS primer sebelum sistem secara otomatis fallback ke DNS standby. Jika Anda hanya mengonfigurasi satu jenis DNS, Anda tidak perlu memanggil metode ini.
     * @param fallbackThreshold Ambang batas kegagalan. Default: 4 jika DNS primer adalah DNS cloud publik, atau 2 jika DNS primer adalah DNS on-premises.
     * Rentang valid: [0, 4]. Nilai 0 menunjukkan fallback segera.
     */
     public static void setFallbackThreshold(int fallbackThreshold)