Todos os produtos
Search
Central de documentação

Alibaba Cloud DNS:Android SDK development guide

Última atualização: Aug 26, 2026

Integre o Android SDK do HTTPDNS ao seu aplicativo para obter resolução de domínios confiável com cache integrado.

Visão geral

O Android SDK é um wrapper Java para a DoH JSON API do HTTPDNS. Ele fornece interfaces Java para que aplicativos Android resolvam nomes de domínio e inclui um cache local eficiente que utiliza políticas de Time-to-Live (TTL) e Least Recently Used (LRU). Ao integrar o HTTPDNS ao seu aplicativo Android, você corrige erros de resolução de domínios e habilita um agendamento preciso e de baixo custo.

Principais vantagens:

  • Simplicidade de uso

    Pouco código é necessário para acessar o service do HTTPDNS.

  • Latência zero

    O cache LRU armazena os IPs resolvidos localmente e atualiza proativamente as entradas antes da expiração do TTL, permitindo resolução com latência zero.

Baixe o alidns_android_demo sample project para consultar uma implementação funcional de referência.

Integração do SDK

Adicionar o SDK

Gradle e Maven

Adicione o seguinte código ao seu arquivo build.gradle:

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

Adicione as informações de dependência:

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

Arquivo AAR

Baixe o SDK na página Download SDK e adicione o pacote alidns_android_sdk.aar ao diretório libs do seu projeto.

Inicialização do SDK

Importante

Inicialize o SDK o mais cedo possível no ciclo de vida do seu aplicativo para evitar falhas de resolução.

Obtenha seu Account ID no console e crie uma chave para obter seu AccessKey ID e sua AccessKey Secret. Em seguida, inicialize o SDK conforme mostrado neste exemplo de classe Application:

public class DnsCacheApplication extends Application{

    private String accountId = "Your Account ID"; // Set your Account ID from the console.
    private String accessKeyId = "Your AccessKey ID"; // Set your AccessKey ID from the console.
    private String accessKeySecret = "Your AccessKey Secret"; // Set your AccessKey Secret from the console.

    @Override
    public void onCreate() {
       super.onCreate();
       // Set the Account ID, AccessKey ID, and AccessKey Secret for SDK access.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       // Note: If you configure domains for keep-alive, resolution is automatically triggered when 75% of the TTL elapses. 
       // This ensures that resolution for these domains always hits the cache. However, if you use a CDN, 
       // the TTL can be short, leading to frequent requests and increased costs. Use this method with caution.
       DNSResolver.setKeepAliveDomains(new String[]{"your-domain-to-keep-alive-1","your-domain-to-keep-alive-2",...});       
       // Perform pre-resolution for specified domains to get IPv4 addresses. Replace the placeholder domains with the ones you want to resolve.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}
Nota

A classe DNSResolver é a classe principal do SDK do HTTPDNS. Ela encapsula a API JSON DoH do HTTPDNS para resolver nomes de domínio em endereços IP. Inicialize o SDK do HTTPDNS na sua subclasse Application.

Declare as seguintes permissões no arquivo AndroidManifest.xml:

<!--Required permissions-->
   <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"/>

Autenticação do SDK

A partir da versão 2,0, o SDK exige autenticação para evitar uso não autorizado. Para ativar o HTTPDNS, crie uma chave no console para obter um AccessKey ID e uma AccessKey Secret. **Defina os parâmetros de autenticação durante a inicialização do SDK. O HTTPDNS rejeita solicitações não autenticadas, o que causa falha na resolução e impacta seus services.**

Defina os parâmetros de autenticação da seguinte forma:

DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret);
Aviso
  • Para evitar que seu Account ID, AccessKey ID, AccessKey Secret ou outros dados de runtime sejam expostos em logs, desative o log de depuração do SDK na sua versão de produção.

  • A integração do SDK requer a definição do Account ID, AccessKey ID e AccessKey Secret no seu código. Esses parâmetros estão vinculados à medição e ao faturamento. Para evitar que a descompilação maliciosa exponha suas credenciais, ative a ofuscação de código e o reforço do aplicativo antes de lançar sua aplicação.

Problemas de integração do SDK

Erro "Cleartext HTTP traffic not permitted"

Causa: A partir do Android 9.0 (API level 28), o Android bloqueia tráfego de rede em texto simples por padrão e permite apenas URLs HTTPS.

Solução

No seu arquivo AndroidManifest.xml, adicione o seguinte código ao elemento <application>:

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">

Erro "Didn't find class BasicHttpParams"

Causa: O cliente HTTP Apache foi descontinuado.

No Android 6.0, o Google removeu o suporte ao cliente HTTP Apache. A partir do Android 9.0, a biblioteca org.apache.http.legacy foi removida do bootclasspath.

Essa alteração não afeta a maioria dos aplicativos direcionados a um API level inferior a 28. Para aplicativos direcionados ao API level 28 ou superior, se você continuar usando a interface HTTP Apache ou uma biblioteca que a utilize, ocorrerá uma exceção porque a interface HTTP Apache não será encontrada.

Solução

No seu arquivo AndroidManifest.xml, adicione o seguinte código ao elemento <application>:

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

Configuração do NDK

  • No diretório raiz do projeto do seu aplicativo, adicione o caminho de instalação do NDK ao arquivo local.properties.

ndk.dir=...\\ndk\\21.4.7075529; // Replace ... with the local NDK installation path.
  • No diretório raiz do projeto do seu aplicativo, adicione a seguinte configuração ao arquivo gradle.properties.

android.useDeprecatedNdk = true;

Para obter desempenho ideal, recomendamos o JDK 1.8 e o NDK 21.4.7075529 para compilar seu aplicativo.

Referência da API

Configurações comuns

1. Inicializar usando o método Init

Chame o método Init ao inicializar o SDK na sua classe Application.

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

2. Definir domínios para pré-resolução

Registre domínios no SDK do HTTPDNS durante a inicialização para ativar a pré-resolução e reduzir a latência subsequente:

  • Especifique a pré-resolução para domínios IPv4 ou IPv6

// Specify the record type for pre-resolution. Replace the placeholder domains with the ones you want to resolve.
DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{...});

// DNSResolver.QTYPE_IPV4: Pre-fetches the IPv4 record type for the domain.
// DNSResolver.QTYPE_IPV6: Pre-fetches the IPv6 record type for the domain.
// DNSResolver.QTYPE_IPV4_IPV6: Pre-fetches both IPv4 and IPv6 record types for the domain.
  • Selecione automaticamente IPv4 ou IPv6 para pré-resolução com base na rede atual. Em um ambiente dual-stack, tanto os endereços IPv4 quanto os IPv6 são pré-carregados.

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

A API de pré-resolução aciona solicitações de rede assíncronas em tempo real. Certifique-se de que toda a inicialização necessária esteja concluída antes de chamar esta API.

3. Definir domínios para keep-alive de cache

O SDK resolve novamente os domínios configurados quando 75% do TTL expira para manter o cache atualizado. Recomendamos limitar isso a 10 domínios. Esta função é independente da pré-resolução.

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

Vantagens

  • Os registros são atualizados em tempo hábil (antes da expiração do TTL).

  • Quando usado com pré-resolução, a latência inicial de resolução pode ser reduzida a 0 ms.

Desvantagens

  • Solicitar novamente a 75% do TTL gera custos adicionais.

4. Especificar se deve usar um endereço de servidor IPv6

O service do HTTPDNS suporta acesso via IPv4 e IPv6. Use DNSResolver.setEnableIPv6(boolean enable) para alternar o acesso ao servidor IPv6. Padrão: IPv4. Se o IPv6 estiver ativado e a conexão com o service do HTTPDNS falhar, o SDK tentará automaticamente uma nova vez via IPv4.

5. Definir o número máximo de entradas de cache

DNSResolver.getInstance().setMaxCacheSize(CACHE_MAX_NUMBER); // Sets the maximum number of cache entries. The default is 100.

Personalize o valor máximo de count conforme necessário.

6. Definir o protocolo para acesso ao servidor

O SDK suporta HTTP e HTTPS para solicitações de resolução. Padrão: HTTPS (recomendado por segurança). Observe que as solicitações HTTPS são cobradas a cinco vezes a taxa do HTTP. Escolha com base nos requisitos do seu negócio.HTTPDNS

DNSResolver.setSchemaType(DNSResolver.HTTPS); // The default access mode is HTTPS.

DNSResolver.HTTP: Acessa interfaces do lado do servidor via HTTP.

DNSResolver.HTTPS: Acessa interfaces do lado do servidor via HTTPS.

Configurações avançadas

1. Ativar ou desativar o log de depuração do SDK

DNSResolver.setEnableLogger(true); // SDK debug logs are disabled by default.

Ative ou desative o log de depuração do SDK. Padrão: desativado.

**2. Especificar se deve ativar o fallback automático do HTTPDNS para o DNS local quando a resolução do HTTPDNS falhar**

DNSResolver.setEnableLocalDns(true); // By default, automatic fallback to local DNS is enabled when HTTPDNS resolution fails.

3. Ativar ou desativar o modo curto

A API JSON DoH do HTTPDNS retorna dados em dois formatos: JSON completo e um array compacto de IPs. Chame DNSResolver.setEnableShort(boolean enable) para ativar ou desativar o modo curto. Por padrão, o modo curto está desativado.

DNSResolver.setEnableShort(true); // The default value is false. You do not need to set this parameter.
Importante

No modo curto, o SDK do HTTPDNS retorna um array compacto de IPs em vez de JSON completo, reduzindo o tamanho da resposta. Ideal para cenários sensíveis a tráfego.

4. Especificar se deve ativar um cache sem expiração

DNSResolver.setImmutableCacheEnable(false); // By default, the non-expiring cache is disabled.
Importante

O SDK fornece três mecanismos de atualização de cache:

  • Cache nunca expira: Quando ativado, este recurso trata o cache como sempre válido durante a execução do aplicativo, ignorando verificações de expiração e operações de atualização. Não é necessário definir setKeepAliveDomains para atualizar ativamente o cache, o que minimiza o número de resoluções do usuário.

    Método: DNSResolver.setImmutableCacheEnable(boolean var0)

    Quando o parâmetro var0 é true, o recurso de cache sem expiração é ativado. Quando var0 é false, este recurso é desativado.

  • Atualização ativa de cache: Este recurso garante que as resoluções utilizem os registros em cache mais atualizados. Quando a zona autoritativa de um domínio muda, esse mecanismo assegura que as solicitações de resolução não apenas acessem o cache para reduzir a latência do DNS, mas também recuperem os registros mais recentes. Quando 75% do TTL de um domínio expira, o SDK aciona automaticamente uma consulta de resolução para atualizar o cache. Recomendamos limitar a 10 o número de domínios com atualizações ativas.

    Método: DNSResolver.setKeepAliveDomains(String[] var1)

    Descrição: var1 é um array de strings contendo os nomes de domínio que precisam ser atualizados proativamente.

  • Atualização passiva de cache:

    Ao chamar os dois métodos abaixo para obter resultados de resolução, o cache é atualizado passivamente:

    • O método getIPsV4ByHost(String hostName) recupera um array de registros IPv4 para o hostName especificado. Se o cache não estiver vazio e estiver dentro do TTL, o método retorna o resultado em cache diretamente. Caso contrário, ele primeiro recupera o resultado de resolução mais recente por meio de uma solicitação de rede e, em seguida, retorna esse resultado e atualiza o cache. Este método é frequentemente usado em cenários que exigem resultados de resolução altamente precisos.

    • O método getIpv4ByHostFromCache(String hostName, boolean isAllowExp) recupera um array de registros IPv4 para um hostName do cache. Com base no valor do parâmetro isAllowExp, este método determina se deve retornar resultados de resolução expirados do cache. Recomendamos usar este método com um método de pré-carregamento na inicialização do aplicativo para garantir que os resultados de resolução mais recentes estejam em cache.

      Se isAllowExp estiver definido como true, dados obsoletos serão retornados mesmo se o cache tiver expirado (null é retornado se o cache estiver vazio), e o cache é atualizado usando uma solicitação assíncrona. Se este parâmetro estiver definido como false, null é retornado quando o cache está expirado ou vazio, e o cache é atualizado usando uma solicitação assíncrona.

    Padrão recomendado:

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

5. Ativar ou desativar o cache

DNSResolver.setEnableCache(true); // The cache is enabled by default.

Ative ou desative o cache de resolução. Padrão: ativado.

6. Ativar ou desativar o teste de velocidade de IP. Este recurso está desativado por padrão nas versões 2.3.0 e anteriores, e ativado por padrão nas versões 2.3.1 e posteriores.

DNSResolver.setEnableSpeedTest(false); // Disabled by default in v2.3.0 and earlier; enabled by default in v2.3.1 and later.

Ative ou desative o teste de velocidade de IP. Padrão: desativado na v2.3.0 e anteriores, ativado na v2.3.1+.

7. Definir o número da porta para teste de velocidade de IP via monitoramento de socket

DNSResolver.setSpeedPort(DNSResolver.PORT_80);

Defina a porta para teste de velocidade de IP baseado em socket. Padrão: 80.

8. Definir a margem de preferência IPv6 para teste de velocidade de IP (suportado na v2.3.3 e posteriores)

DNSResolver.setSpeedTestIpv6PreferMs(0);

Defina a margem de preferência IPv6, em milissegundos, para o teste de velocidade de IP. Quando o teste de velocidade está ativado e os endereços IPv4 e IPv6 são classificados juntos, o SDK subtrai essa margem do tempo medido do IPv6 antes de comparar esse resultado com o tempo medido do IPv4. Portanto, um endereço IPv6 ainda é preferido quando o IPv6 é mais lento que o IPv4 por menos que a margem definida. Padrão: 0, que desativa a margem. Intervalo válido: [0, 1000]. Esta configuração só tem efeito quando o teste de velocidade está ativado.

9. Especificar se deve particionar o cache de domínios por rede ISP

DNSResolver.setIspEnable(true); // By default, the domain cache is partitioned by ISP network.

Quando ativado, os dados do cache de domínios são armazenados separadamente por ambiente de rede. Quando desativado, um único cache é compartilhado entre todas as redes.

10. Definir o TTL máximo para o cache negativo

DNSResolver.setMaxNegativeCache(MAX_NEGATIVE_CACHE); // Sets the maximum TTL for the negative cache. The default is 30 seconds.

Defina o TTL máximo para o cache negativo. Uma entrada de cache negativo é criada quando nenhum IP é retornado para um domínio. Padrão: 30 segundos.

11. Definir o TTL máximo para o cache

DNSResolver.setMaxTtlCache(MAX_TTL_CACHE); // Sets the maximum TTL for the cache. The default value is 3,600 seconds.

Defina um limite máximo de TTL para as entradas de cache. Padrão: 3.600 segundos.

12. Definir informações de sub-rede do cliente

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

O método setEdnsSubnet suporta EDNS Client Subnet (ECS, RFC 7871), passando informações da sub-rede do usuário para o DNS autoritativo para um agendamento de tráfego preciso. Uma máscara mais longa fornece resultados mais precisos; uma máscara mais curta melhora a privacidade. Recomenda-se uma máscara /24.

Nota

Este parâmetro foi projetado para cenários onde um proxy DNS usa a API JSON DoH. Nesses cenários, um usuário envia uma consulta DNS ao proxy DNS, e o proxy usa este parâmetro para passar as informações da sub-rede do usuário para o HTTPDNS e, em seguida, para o servidor DNS autoritativo.

Por exemplo, se você chamar DNSResolver.setEdnsSubnet("1.2.XX.XX/24"), o servidor autoritativo receberá informações de prefixo baseadas no endereço 1.2.XX.XX/24 para ajudar na seleção de um link DNS.

13. Definir o tempo limite para resolução de nome de domínio

Defina o timeout para a resolução de domínios. Padrão: 3 segundos. Intervalo recomendado: 2–5 segundos.

DNSResolver.setTimeout(3);

14. Definir o número máximo de resoluções simultâneas (suportado na v2.3.2 e posteriores)

Defina o número máximo de resoluções DNS assíncronas simultâneas (pré-resolução, atualização de cache). Intervalo válido: [1, 50]. Padrão: 10.

DNSResolver.setMaxConcurrentResolveCount(10);

15. Obter SessionId para solução de problemas

Um sessionId é gerado na inicialização do aplicativo e permanece constante durante todo o ciclo de vida. Todas as solicitações de resolução do HTTPDNS carregam este ID. Use-o para rastrear solicitações no servidor para fins de solução de problemas.

public static String getSessionId()

16. Callback de saída de log

Este callback recebe os logs gerados pelo SDK.

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

Configuração do ProGuard

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

API de Service

  /**
   * Pre-loads domain name resolution based on the automatically detected network environment (IPv4-only, IPv6-only, or dual-stack).
   * In a dual-stack network environment, both IPv4 and IPv6 resolution results are pre-loaded. You can call this method during SDK initialization at app startup.
   * This method pre-stores the resolution results in the cache to reduce the latency of subsequent domain name resolutions.
   *
   * @param domains The domain names to be pre-loaded.
   */
   public void preLoadDomains(final String[] domains)

    /**
     * Pre-loads domain resolution for a specified record type (IPv4 or IPv6). 
     * You can call this method during SDK initialization at app startup. This method pre-stores the resolution results in the cache to reduce latency for later resolutions.
     *
     * @param qType The record type to pre-load, such as IPv4 or IPv6.
     * @param domains The domain names to be pre-loaded.
     */
    public void preLoadDomains(String qType, final String[] domains)
   /**
   * Obtains the resolution data for the domain name based on the automatically detected network environment (IPv4-only, IPv6-only, or dual-stack).
   * If a non-expired resolution result exists in the cache, the result from the cache is returned.
   * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
   *
   * @param host The domain name that you want to resolve.
   * @return The optimal IP address array based on the current network environment.
   */
    public String[] getIpsByHost(String host)

/**
    * Obtains the array of IPv4 records that correspond to the hostname.
    * If a non-expired resolution result exists in the cache, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
    *
    * @param hostName The hostname, such as www.example.com.
    * @return The array of IPv4 addresses that correspond to the hostname.
    */
  public  String[] getIPsV4ByHost(String hostName) 

   /**
    * Obtains the array of IPv6 records that correspond to the hostname.
    * @param hostName The hostname, such as www.example.com.
    * @return The array of IPv6 addresses that correspond to the hostname.
    */
  public String[] getIPsV6ByHost(String hostName) 

  

  /**
   * Obtains the IP address array for the resolved domain name from the cache based on the automatically detected network environment (IPv4-only, IPv6-only, or dual-stack).
   * If the cache is empty, this method returns null and initiates an asynchronous query. The query result is then stored in the cache.
   * If a resolution result exists in the cache and you allow returning expired results, the expired IP addresses are returned, and the cache is updated asynchronously.
   * If you do not allow returning expired results and the cached result has expired, this method returns null and then asynchronously updates the cache.
   *
   * @param host The host to query, such as www.example.com.
   * @param isAllowExp Specifies whether to return the resolution data of an expired domain.
   * @return The cached IP address array for the resolved host.
   */
   public String[] getIpsByHostFromCache(String host, boolean isAllowExp)
   
    /**
     * Obtains the IP address array of the IPv4 record type for the resolved domain name from the cache.
     * If the cache is empty, this method returns null and initiates an asynchronous query. The query result is then stored in the cache.
     * If a resolution result exists in the cache and you allow returning expired results, the expired IP addresses are returned, and the cache is updated asynchronously.
     * If you do not allow returning expired results and the cached result has expired, this method returns null and then asynchronously updates the cache.
     *
     * @param host The host to query, such as www.example.com.
     * @param isAllowExp Specifies whether to return the resolution data of an expired domain.
     * @return The IP address array of the IPv4 record type from the cache after the host is resolved.
     */
    public String[] getIpv4ByHostFromCache(String host , boolean isAllowExp)

    /**
     * Obtains the IP address array of the IPv6 record type for the resolved domain name from the cache.
     * If the cache is empty, this method returns null and initiates an asynchronous query. The query result is then stored in the cache.
     * If a resolution result exists in the cache and you allow returning expired results, the expired IP addresses are returned, and the cache is updated asynchronously.
     * If you do not allow returning expired results and the cached result has expired, this method returns null and then asynchronously updates the cache.
     *
     * @param host The host to query, such as www.example.com.
     * @param isAllowExp Specifies whether to return the resolution data of an expired domain.
     * @return The IP address array of the IPv6 record type from the cache after the host is resolved.
     */
    public String[] getIpv6ByHostFromCache(String host , boolean isAllowExp)

  /**
  * Obtains the array of DomainInfo objects for IPv4 records that correspond to the URL.
  * If a non-expired resolution result exists in the cache, the result from the cache is returned.
  * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
  *
  * @param url The URL, such as http://www.example.com.
  * @return The array of DomainInfo objects of the IPv4 type that correspond to the URL.
  */
  public DomainInfo[] getIPsV4DInfoByUrl(String url) 

  Note: The URL in the DomainInfo object is the URL in which the host is automatically replaced with an IP address. You do not need to manually replace the host in the URL.

  /**
   * Obtains the array of DomainInfo objects for IPv6 records that correspond to the URL.
   * If a non-expired resolution result exists in the cache, the result from the cache is returned.
   * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
   * 
   * @param url The URL, such as http://m.example.com.
   * @return The array of DomainInfo objects of the IPv6 type that correspond to the URL.
   */
   public DomainInfo[] getIPsV6DInfoByUrl(String url) 

  /**
    * Obtains a DomainInfo object for the IPv4 records that correspond to a specific URL.
    * If a non-expired resolution result exists in the cache, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
    *
    * @param url The URL, such as http://m.example.com.
    * @return A random DomainInfo object from the collection of IPv4-type DomainInfo objects that correspond to the URL.
    */
    public DomainInfo getIPV4DInfoByUrl(String url) 

  /**
    * Obtains a DomainInfo object for the IPv6 records that correspond to a specific URL.
    * If a non-expired resolution result exists in the cache, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
    *
    * @param url The URL, such as http://www.example.com.
    * @return A random DomainInfo object from the collection of IPv6-type DomainInfo objects that correspond to the URL.
    */
   public DomainInfo getIPV6DInfoByUrl(String url) 

   Note: The returned DomainInfo object encapsulates the following properties.

  /**
   * The auto-incrementing ID for the access domain.
    */
    public String id = null;

   /**
    * The URL that can be directly used. The host in the URL is replaced with an IP address.
    */
     public String url = null;

    /**
    * The name of the destination service to be set in the HTTP header.
    */
    public String host = "";

   /**
    * The returned content body.
    */
   public String data = null;

   /**
    * The time when the request starts.
    */
   public String startTime = null;

   /**
    * The time when the request ends. If the request times out, this value is null.
    */
   public String stopTime = null; 

   /**
   * The status code returned by the server, such as 200, 404, or 500. 
   */
   public String code = null;

  /**
    * Obtains the IPv4 record that corresponds to the hostname.
    * If a non-expired resolution result exists in the cache, the result from the cache is returned.
     * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
  
    * @param hostName The hostname, such as www.example.com.
    * @return A random IPv4 address from the set of IPv4 addresses that correspond to the hostname. If IP speed testing is enabled, the optimal IPv4 address is returned.
    */
  public String getIPV4ByHost(String hostName) 

   /**
    * Obtains the IPv6 record that corresponds to the hostname.
    * If a non-expired resolution result exists in the cache, the result from the cache is returned.
    * If the cache is empty or the cached result has expired, a synchronous network request is sent to the server to obtain the recursive resolution result. The result is then returned and stored in the cache.
  
    * @param hostName The hostname, such as www.example.com.
    * @return A random IPv6 address from the set of IPv6 addresses that correspond to the hostname. If IP speed testing is enabled, the optimal IPv6 address is returned.
    */
   public String getIPV6ByHost(String hostName) 
      

    /**
     * Obtains the statistics about successful and failed HTTPDNS requests.
     *
     * @return A JSON array string of the resolution statistics for all domain names.
     */
    public String getRequestReportInfo()
    
     /**
     * Sets domain names for cache keep-alive. The resolution of a configured domain name is automatically initiated when 75% of the TTL elapses. This ensures that resolution requests for the configured domain name always hit the cache and improves the resolution efficiency of the SDK.
     * We recommend that you do not configure an excessive number of domain names for this feature. The current limit is 10 domain names. This feature is configured independently of the pre-resolution feature.
     *
     * @param persistentCacheDomains
     */
    public synchronized static void setKeepAliveDomains(String[] persistentCacheDomains) {
    
     /**
     * Clears the cache for specified domain names. If the hostname is null, the cache for all domain names is cleared.
     *
     * @param domains The array of domain names whose cache you want to clear.
     */
    public void clearHostCache(String[] domains){

Exemplos de API

URL: O endereço de acesso passado, por exemplo, http://www.example.com.

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

1. Obter os dados de IP ideais para o ambiente de rede atual

String[] ip = DNSResolver.getInstance().getIpsByHost(hostname); // Gets the optimal domain resolution IP for the current network.

2. Pré-carregar a resolução de domínios com base no ambiente de rede atual

DNSResolver.getInstance().preLoadDomains(domains); // Sets domain names for pre-resolution. Replace the placeholder domains with the ones you want HTTPDNS to resolve.

3. Ler dados de resolução de domínios do cache com base no ambiente de rede atual

String[] ip = DNSResolver.getInstance().getIpsByHostFromCache(hostname,true); // Gets domain resolution data from the cache for the current network environment.

4. Obter um endereço IPv4

String IPV4 = DNSResolver.getInstance().getIPV4ByHost(hostname); // Gets the resolved IPv4 address.

5. Obter um endereço IPv6

String IPV6 =  DNSResolver.getInstance().getIPV6ByHost(hostname); // Gets the resolved IPv6 address.

6. Obter um endereço IPv4 resolvido do cache

String[] IPV4 =  DNSResolver.getInstance().getIpv4ByHostFromCache(hostname , true); // Gets the resolved IPv4 address from the cache.

7. Obter um endereço IPv6 resolvido do cache

String[] IPV6 =  DNSResolver.getInstance().getIpv6ByHostFromCache(hostname , true); // Gets the resolved IPv6 address from the cache.

8. Obter o objeto DomainInfo correspondente a uma URL

DomainInfo dinfo = DNSResolver.getInstance().getIPV4DInfoByUrl(url); // Gets the replaced URL.

9. Limpar o resultado de resolução de um domínio específico do cache

DNSResolver.getInstance().clearHostCache(hostName); // Clears the cache for a specified domain. If hostName is set to null, the cache for all domains is cleared.

10. Obter estatísticas sobre solicitações HTTPDNS bem-sucedidas e com falha

String reportInfo = DNSResolver.getInstance().getRequestReportInfo(); // Gets statistics about successful and failed requests.

A tabela a seguir descreve os campos no array de strings JSON de estatísticas de resolução de domínios.

 [
      {
         "avgRtt":"1",                         // Average domain resolution time, in milliseconds (ms).
         "degradeLocalDnsCount": 0,            // Number of fallbacks to local DNS.                       
         "domainName":"www.example.com",       // The resolved domain name.
         "hitDnsCacheCount": 1,                // Number of cache hits.
         "httpabnormalCount": 0,               // Number of failed recursive requests.
         "isp": "China Mobile",                // ISP name.
         "localDnsResolveErrCount": 0,         // Number of local DNS resolution failures.
         "maxRtt": 8.0,                        // Maximum domain resolution time, in milliseconds (ms).          
         "nonetworkCount": 0,                  // Number of times the network is unavailable.
         "permissionErrCount": 0,              // Number of user authentication failures.
         "queryType": 1,                       // IP type. 1 indicates IPv4, and 28 indicates IPv6.
         "recursiveReqCount": 1,               // Number of recursive queries.
         "reqParameterErrCount": 0,            // Number of request parameter format errors.
         "reqPathErrCount": 0,                 // Number of URL errors.
         "reqServerErrCount": 0,               // Number of DNS server-side errors.
         "reqTimeoutCount": 0,                 // Number of DNS service timeout errors.
         "resolveSuccessCount": 1,             // Number of successful resolutions.
         "timeoutCount": 0,                    // Number of network timeout errors.
         "utfNetWorkErroNum": 0                // Number of data reporting timeout errors.
      }
         ......
 ]
Importante

As estatísticas das solicitações de resolução de domínios do HTTPDNS são agregadas por ambiente de rede, nome de domínio e tipo de solicitação.

Exemplo

public class MainActivity extends AppCompatActivity {
   private Button button;
   private TextView tvInfo;
   private TextView tvResult;
   private String hostUrl = "http://www.taobao.com"; // Replace this with the hostUrl that you want to resolve.
   private String hostName = "www.taobao.com"; // Replace this with the hostName that you want to resolve.
   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() {
                      // Call the getIPV4ByHost method in the HTTPDNS SDK to obtain the resolved IP address of the target domain name.
                      String ip = DNSResolver.getInstance().getIPV4ByHost(hostName);
                      if(ip != null){
                         tvInfo.setText("The resolved IP for the domain is: "+ ip);
                      }
                      // Call the getIPV4DInfoByUrl method in the HTTPDNS SDK to get the URL from the resolved DomainInfo object. 
                      // The host in this URL is replaced with the IP address.
                      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) {
                // Sends a network request.
               String requestUrl = dinfo.url;
               HttpURLConnection conn = null;
               try {
                   URL url = new URL(requestUrl);
                   conn = (HttpURLConnection) url.openConnection();
                   // When you use an IP address for access, you must set the Host field of the HTTP request header to the original domain name.
                   conn.setRequestProperty("Host", url.getHost()); // Sets the Host field of the HTTP request header.
                   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, "Response: " + 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"; // Set your Account ID from the console.
    private String accessKeyId = "Your AccessKey ID"; // Set your AccessKey ID from the console.
    private String accessKeySecret = "Your AccessKey Secret"; // Set your AccessKey Secret from the console.

    @Override
    public void onCreate() {
       super.onCreate();
       // Set the Account ID, AccessKey ID, and AccessKey Secret for SDK access.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       // Sets domain names for cache keep-alive. The resolution of a configured domain name is automatically initiated at 75% of its TTL to ensure that resolution requests for the domain name always hit the cache.
       DNSResolver.setKeepAliveDomains(new String[]{"your-domain-1","your-domain-2",...}); 
       // Pre-loads specified domains to IPv4 addresses. Replace the placeholder domains with the ones that you want to resolve.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}

Melhores práticas

Combine a pré-resolução com o cache de respostas expiradas para obter desempenho ideal.

A pré-resolução armazena resultados em cache na inicialização. Permitir respostas expiradas retorna IPs em cache imediatamente, mesmo após a expiração do TTL, alcançando resolução com latência quase zero.

Domínios pré-carregados acessam o cache local em solicitações subsequentes, eliminando idas e vindas na rede.

1. Pré-resolução

Ative o cache e pré-resolva domínios essenciais na inicialização do aplicativo.

No método onCreate() da classe Application, pré-resolva seus domínios e armazene os resultados em cache localmente.

1. Cenários somente IPv4

//********For IPv4-only scenarios*******
public class DnsCacheApplication extends Application{
    private String accountId = "Your Account ID"; // Set your Account ID from the console.
    private String accessKeyId = "Your AccessKey ID"; // Set your AccessKey ID from the console.
    private String accessKeySecret = "Your AccessKey Secret"; // Set your AccessKey Secret from the console.

    @Override
    public void onCreate() {
       super.onCreate();
       // Set the Account ID, AccessKey ID, and AccessKey Secret for SDK access.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       DNSResolver.setEnableCache(true); // Enable caching. Default value: true. 
       // The IPv4 record type for pre-resolution.    
       // Pre-loads specified domains to IPv4 addresses. Replace the placeholder domains with the ones that you want HTTPDNS to resolve.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}

2. Suporte a IPv6

//********For scenarios that require IPv6 support*******
public class DnsCacheApplication extends Application{
    private String accountId = "Your Account ID"; // Set your Account ID from the console.
    private String accessKeyId = "Your AccessKey ID"; // Set your AccessKey ID from the console.
    private String accessKeySecret = "Your AccessKey Secret"; // Set your AccessKey Secret from the console.

    @Override
    public void onCreate() {
       super.onCreate();
       // Set the Account ID, AccessKey ID, and AccessKey Secret for SDK access.
       DNSResolver.Init(this, accountId, accessKeyId, accessKeySecret); 
       DNSResolver.setEnableCache(true); // Enable caching. Default value: true.
       DNSResolver.setEnableIPv6(true); // Specifies whether to resolve domain names over an IPv6 network. Default value: false.  
       DNSResolver.setEnableSpeedTest(true); // Specifies whether to enable IP speed testing. Default value: false.
       // The IPv4 and IPv6 record types for pre-resolution.  
       // Pre-loads specified domains to IPv4 and IPv6 addresses. Replace the placeholder domains with the ones that you want HTTPDNS to resolve.
       DNSResolver.getInstance().preLoadDomains(DNSResolver.QTYPE_IPV4_IPV6,new String[]{"your-domain-to-preload-1","your-domain-to-preload-2",...}); 
    }
}

2. Permitir respostas expiradas

Leia IPs do cache antes das solicitações de rede, permitindo que entradas expiradas sejam retornadas imediatamente. O cache é atualizado de forma assíncrona em segundo plano.

1. Cenários somente IPv4

    //********For IPv4-only scenarios*******
    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        // Prioritize getting the IP address from the cache. The second parameter, if true, allows returning expired but usable records.
        String[] IPArray = mDNSResolver.getIpv4ByHostFromCache(hostname,true);
        if (IPArray == null || IPArray.length == 0){
            // If the cache is not hit, initiate an asynchronous resolution.
            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. Suporte a IPv6

    //********For scenarios that require IPv6 support*******
    @Override
    public List<InetAddress> lookup(@NonNull String hostname) throws UnknownHostException {
        // Prioritize getting the IP address from the cache. The second parameter, if true, allows returning expired but usable records.
        String[] IPArray = mDNSResolver.getIpsByHostFromCache(hostname,true);
        if (IPArray == null || IPArray.length == 0){
            // If the cache is not hit, initiate an asynchronous resolution.
            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);
    }

Notas de uso

  1. Ao usar um endereço IP obtido do HTTPDNS para enviar solicitações, defina o cabeçalho HTTP Host como o nome de domínio original.

  2. Se o SDK do HTTPDNS retornar um IP vazio, faça fallback para a URL do nome de domínio original:

    String ip = DNSResolver.getInstance().getIPV4ByHost("your-domain");
    if (ip != null) {
    	// Replace the host in the URL with the IP address to make an API request.
    }else {
    	// Use the request URL of the original domain name to make a fallback request. 
        // In this case, use the original URL that contains the domain name to make a network request.
    }
  3. Use o Download the demo program como referência para integrar o SDK do HTTPDNS.

  4. Após a integração, verifique o sucesso na página Traffic Analysis no console. Se nenhum tráfego aparecer, verifique se o Account ID, o AccessKey ID e a AccessKey Secret estão definidos corretamente.

DNS On-premises

A partir da v2.3.0, o HTTPDNS Android SDK adiciona suporte para implantação de DNS on-premises.

O DNS on-premises é adequado para cenários que exigem conformidade de dados e políticas de resolução personalizadas (finanças, governo, grandes empresas). O SDK suporta quatro modos de implantação: apenas cloud pública, apenas on-premises e dois híbridos primário-standby.

Capacidades principais

  • Suporte a implantação on-premises: Permite configurar endpoints de service DNS on-premises usando endereços IPv4/IPv6 ou nomes de domínio de host.

  • Autenticação bidirecional: Este mecanismo assina solicitações com um accessKeyId e uma accessKeySecret específicos do cliente para garantir comunicação segura.

  • Circuit breaking e health checks: Se um nó DNS on-premises falhar 3 ou mais vezes consecutivas, o circuit breaking é acionado automaticamente. Depois disso, sua disponibilidade é verificada a cada minuto usando o healthCheckDomain especificado. O nó é reativado automaticamente após se recuperar.

  • Controle de validação de certificado: A partir da versão 2.3.1.beta, você pode desativar a validação de certificado TLS para testar o DNS on-premises. Versões beta destinam-se apenas a testes e não devem ser usadas em produção. Android SDK release note

  • Fallback inteligente: Se o DNS primário (DNS da cloud pública ou DNS on-premises) falhar ao resolver um nome de domínio e a contagem de falhas atingir o limiar especificado, o sistema mudará automaticamente para o DNS standby para garantir alta disponibilidade de resolução.

  • Compatibilidade perfeita de API: Independentemente de usar DNS da cloud pública ou DNS on-premises, a maneira de chamar a API de resolução permanece a mesma. Não é necessário modificar sua lógica de negócios.

Configuração

1. Apenas DNS da cloud pública

Este modo destina-se a usuários SaaS padrão que não implantaram um DNS on-premises.

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

2. Apenas DNS on-premises

Este modo destina-se a clientes que dependem inteiramente de seu 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");
// Optional: Disable certificate validation (for test environments only, requires a beta SDK version, e.g., 2.3.1.beta).
// DNSResolver.setEnableCertificateValidation(false);

3. Primário: Cloud pública, Standby: On-premises

Se o HTTPDNS público da Alibaba Cloud primário falhar ao resolver um nome de domínio, o sistema fará fallback automaticamente para o DNS on-premises.

// Primary: public cloud DNS
DNSResolver.Init(this, accountID, accessKeyId, accessKeySecret);
    
// Standby: on-premises DNS
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");
// Optional: Disable certificate validation (for test environments only, requires a beta SDK version, e.g., 2.3.1.beta).
// DNSResolver.setEnableCertificateValidation(false);

4. Primário: On-premises, Standby: Cloud pública

Use o DNS on-premises como DNS primário. Se o DNS on-premises falhar ao resolver um nome de domínio, o sistema fará fallback automaticamente para o DNS da cloud pública da Alibaba Cloud.

// Primary: on-premises DNS
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");
// Optional: Disable certificate validation (for test environments only, requires a beta SDK version, e.g., 2.3.1.beta).
// DNSResolver.setEnableCertificateValidation(false);

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

Novas APIs

O SDK adiciona três APIs principais para implantação on-premises e recuperação de desastres de alta disponibilidade:

1. Configurar endpoints e autenticação

    /** For on-premises DNS used in on-premises deployments. You do not need to call this method if you use only public DNS.
     *
     * Sets the address and authentication information for the on-premises DNS server.
     * Customers use this interface to pass the address and authentication credentials of the private DNS server.
     * The SDK uses this information to initiate requests.
     * @param ctx The context.
     * @param serverIpv4Arr The array of IPv4 addresses (can be nil).
     * @param serverIpv6Arr The array of IPv6 addresses (can be nil).
     * @param serverHostArr The array of host domain names (can be nil).
     * @param port The service port, such as "443". If nil, the default port "443" is used.
     * @param healthCheckDomain The domain name that is used for health checks after circuit breaking is triggered. When a resolution service consecutively fails more than three times, circuit breaking is triggered, and the IP address of that service enters the healthCheck state. Subsequent requests will not be sent to this service. 
     *                          A timer runs every minute to call the resolution API by using this healthCheckDomain to probe whether the resolution service is available. If the probe is successful, the service returns to the alive state, and subsequent requests can be sent to this service.
     * @param accessKeyId The customer's private accessKeyId, which is used for authentication.
     * @param accessKeySecret The customer's private accessKeySecret, which is used for authentication.
     */
    public static void InitFusionDNS(Context ctx,String[] serverIpv4Arr, String[] serverIpv6Arr, String[] serverHostArr, String port, String healthCheckDomain, String accessKeyId, String accessKeySecret)

2. Controlar a validação de certificado TLS

Controle a validação de certificado TLS para DNS on-premises. Builds beta do Android SDK são publicadas a partir da versão 2.3.1, e a build beta correspondente a 2.3.1 é chamada 2.3.1.beta. Uma build beta permite desativar a validação de certificado TLS para DNS on-premises para que você possa executar testes. Builds beta existem apenas para conveniência de testes. Nunca use uma build beta em um ambiente de produção.

    /** For on-premises DNS used in on-premises deployments. You do not need to call this method if you use only public DNS.
     *
     * Specifies whether to enable certificate validation for on-premises DNS. Default value: true. If the server is not configured with a domain certificate or an IP certificate, you can set this parameter to false for testing. In production environments, we strongly recommend that you set this parameter to true. Otherwise, security risks may arise.
     * @param enable Set this parameter to true to enable certificate validation (default), or false to disable it.
     */
    public static void setEnableCertificateValidation(boolean enable)

3. Definir o limiar de fallback

    /** If you configure both public cloud DNS and on-premises DNS, you can specify the number of times that DNS resolution on the primary DNS must fail before the system automatically falls back to the standby DNS. If you configure only one type of DNS, you do not need to call this method.
     *
     * Specifies the number of times that DNS resolution on the primary DNS must fail before the system automatically falls back to the standby DNS. If you configure only one type of DNS, you do not need to call this method.
     * @param fallbackThreshold The failure threshold. Default: 4 if the primary DNS is public cloud DNS, or 2 if the primary DNS is on-premises DNS.
     * Valid range: [0, 4]. A value of 0 indicates an immediate fallback.
     */
     public static void setFallbackThreshold(int fallbackThreshold)