From a4e8deb45a20b87acb474291650f092aab7a8ce4 Mon Sep 17 00:00:00 2001 From: Renato Date: Thu, 12 Feb 2026 21:53:44 -0300 Subject: [PATCH] Fix DNS issues: Add 4 DoH servers with fallback, remove ineffective DNSSetter - Remove DNSSetter.java (System.setProperty doesn't affect Android DNS) - Update NetworkUtils with 4 DNS over HTTPS providers: * Google DNS (8.8.8.8) - Primary * Cloudflare (1.1.1.1) - Secondary * AdGuard (94.140.14.14) - Tertiary * Quad9 (9.9.9.9) - Quaternary - Update DeviceRegistry to use NetworkUtils client - Update UpdateManager to use NetworkUtils client - Remove DNSSetter call from PlayerActivity This ensures the app works even when ISPs block specific DNS servers. --- .../main/java/com/streamplayer/DNSSetter.java | 109 ------------------ .../java/com/streamplayer/DeviceRegistry.java | 8 +- .../java/com/streamplayer/NetworkUtils.java | 64 ++++++++-- .../java/com/streamplayer/PlayerActivity.java | 2 +- .../java/com/streamplayer/UpdateManager.java | 9 +- 5 files changed, 62 insertions(+), 130 deletions(-) delete mode 100644 app/src/main/java/com/streamplayer/DNSSetter.java diff --git a/app/src/main/java/com/streamplayer/DNSSetter.java b/app/src/main/java/com/streamplayer/DNSSetter.java deleted file mode 100644 index 3e25cf9..0000000 --- a/app/src/main/java/com/streamplayer/DNSSetter.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.streamplayer; - -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; -import android.os.Build; - -import java.net.InetAddress; - -public class DNSSetter { - - private static final String[] GOOGLE_DNS = {"8.8.8.8", "8.8.4.4"}; - - public static void configureDNSToGoogle(Context context) { - try { - // Configurar propiedades del sistema para usar DNS específicos - System.setProperty("networkaddress.cache.ttl", "60"); - System.setProperty("networkaddress.cache.negative.ttl", "10"); - - // Forzar resolución usando DNS de Google - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - configureModernDNS(context); - } else { - configureLegacyDNS(); - } - - // Pre-resolver dominio con DNS de Google - preResolveWithGoogleDNS(); - - } catch (Exception e) { - System.out.println("Error configurando DNS de Google: " + e.getMessage()); - } - } - - private static void configureModernDNS(Context context) { - try { - ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - - NetworkRequest networkRequest = new NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .build(); - - connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() { - @Override - public void onAvailable(Network network) { - super.onAvailable(network); - - // Configuración para priorizar DNS de Google - // Aunque no podemos cambiar DNS directamente sin permisos especiales, - // podemos optimizar la configuración de red - try { - NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(network); - if (caps != null) { - System.out.println("Red configurada con DNS optimizado para streaming"); - } - } catch (Exception e) { - System.out.println("Error en configuración de red: " + e.getMessage()); - } - } - }); - - } catch (Exception e) { - System.out.println("Error configurando DNS moderno: " + e.getMessage()); - } - } - - private static void configureLegacyDNS() { - try { - // Para versiones antiguas, configuramos propiedades del sistema - System.setProperty("sun.net.inetaddr.ttl", "60"); - System.setProperty("sun.net.inetaddr.negative.ttl", "10"); - - System.out.println("DNS legacy configurado para streaming"); - } catch (Exception e) { - System.out.println("Error configurando DNS legacy: " + e.getMessage()); - } - } - - private static void preResolveWithGoogleDNS() { - try { - // Pre-resolver algunos dominios comunes para caching - Thread thread = new Thread(() -> { - try { - String[] domains = {"streamtp10.com", "google.com", "dns.adguard-dns.com"}; - for (String domain : domains) { - try { - InetAddress.getByName(domain); - System.out.println("Pre-resuelto: " + domain); - } catch (Exception e) { - System.out.println("Error pre-resolviendo " + domain + ": " + e.getMessage()); - } - } - } catch (Exception e) { - System.out.println("Error en pre-resolución: " + e.getMessage()); - } - }); - thread.start(); - - } catch (Exception e) { - System.out.println("Error en pre-resolución DNS: " + e.getMessage()); - } - } - - public static String getGoogleDNSInfo() { - return "DNS de Google configurado: " + String.join(", ", GOOGLE_DNS); - } -} diff --git a/app/src/main/java/com/streamplayer/DeviceRegistry.java b/app/src/main/java/com/streamplayer/DeviceRegistry.java index f96a8f0..d9de21e 100644 --- a/app/src/main/java/com/streamplayer/DeviceRegistry.java +++ b/app/src/main/java/com/streamplayer/DeviceRegistry.java @@ -15,7 +15,6 @@ import java.io.IOException; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -46,11 +45,8 @@ public class DeviceRegistry { public DeviceRegistry(Context context) { this.appContext = context.getApplicationContext(); - this.httpClient = new OkHttpClient.Builder() - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(15, TimeUnit.SECONDS) - .callTimeout(20, TimeUnit.SECONDS) - .build(); + // Usar NetworkUtils para obtener cliente con DNS over HTTPS configurado + this.httpClient = NetworkUtils.getClient(); this.executorService = Executors.newSingleThreadExecutor(); } diff --git a/app/src/main/java/com/streamplayer/NetworkUtils.java b/app/src/main/java/com/streamplayer/NetworkUtils.java index d8aa095..cd8a994 100644 --- a/app/src/main/java/com/streamplayer/NetworkUtils.java +++ b/app/src/main/java/com/streamplayer/NetworkUtils.java @@ -3,7 +3,6 @@ package com.streamplayer; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; @@ -12,46 +11,78 @@ import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.dnsoverhttps.DnsOverHttps; +/** + * Utilidad centralizada para configuración de red con múltiples servidores DNS over HTTPS. + * Implementa fallback progresivo: Google -> Cloudflare -> AdGuard -> Quad9 -> Sistema + */ public class NetworkUtils { private static final OkHttpClient CLIENT; private static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"; + // URLs de servidores DNS over HTTPS + private static final String GOOGLE_DOH_URL = "https://dns.google/dns-query"; + private static final String CLOUDFLARE_DOH_URL = "https://cloudflare-dns.com/dns-query"; + private static final String ADGUARD_DOH_URL = "https://dns.adguard-dns.com/dns-query"; + private static final String QUAD9_DOH_URL = "https://dns.quad9.net/dns-query"; + static { OkHttpClient.Builder builder = new OkHttpClient.Builder() .connectTimeout(15, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .writeTimeout(15, TimeUnit.SECONDS) .followRedirects(true) - .followSslRedirects(true); + .followSslRedirects(true) + .retryOnConnectionFailure(true); try { // Cliente bootstrap para resolver los dominios de DNS OkHttpClient bootstrap = new OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) + .retryOnConnectionFailure(true) .build(); // 1. Google DNS over HTTPS (Primario) final DnsOverHttps googleDns = new DnsOverHttps.Builder() .client(bootstrap) - .url(HttpUrl.get("https://dns.google/dns-query")) + .url(HttpUrl.get(GOOGLE_DOH_URL)) .bootstrapDnsHosts( getByIp("8.8.8.8"), getByIp("8.8.4.4")) .includeIPv6(false) .build(); - // 2. AdGuard DNS over HTTPS (Secundario) + // 2. Cloudflare DNS over HTTPS (Secundario) + final DnsOverHttps cloudflareDns = new DnsOverHttps.Builder() + .client(bootstrap) + .url(HttpUrl.get(CLOUDFLARE_DOH_URL)) + .bootstrapDnsHosts( + getByIp("1.1.1.1"), + getByIp("1.0.0.1")) + .includeIPv6(false) + .build(); + + // 3. AdGuard DNS over HTTPS (Terciario) final DnsOverHttps adGuardDns = new DnsOverHttps.Builder() .client(bootstrap) - .url(HttpUrl.get("https://dns.adguard-dns.com/dns-query")) + .url(HttpUrl.get(ADGUARD_DOH_URL)) .bootstrapDnsHosts( getByIp("94.140.14.14"), getByIp("94.140.15.15")) .includeIPv6(false) .build(); - // Configurar DNS con fallback: Google -> AdGuard -> Sistema + // 4. Quad9 DNS over HTTPS (Cuaternario) + final DnsOverHttps quad9Dns = new DnsOverHttps.Builder() + .client(bootstrap) + .url(HttpUrl.get(QUAD9_DOH_URL)) + .bootstrapDnsHosts( + getByIp("9.9.9.9"), + getByIp("149.112.112.112")) + .includeIPv6(false) + .build(); + + // Configurar DNS con fallback: Google -> Cloudflare -> AdGuard -> Quad9 -> Sistema builder.dns(new Dns() { @Override public List lookup(String hostname) throws UnknownHostException { @@ -63,7 +94,15 @@ public class NetworkUtils { // Falló Google, continuar } - // Intento 2: AdGuard DNS + // Intento 2: Cloudflare DNS + try { + List result = cloudflareDns.lookup(hostname); + if (result != null && !result.isEmpty()) return result; + } catch (Exception ignored) { + // Falló Cloudflare, continuar + } + + // Intento 3: AdGuard DNS try { List result = adGuardDns.lookup(hostname); if (result != null && !result.isEmpty()) return result; @@ -71,7 +110,15 @@ public class NetworkUtils { // Falló AdGuard, continuar } - // Intento 3: DNS del Sistema (Fallback final) + // Intento 4: Quad9 DNS + try { + List result = quad9Dns.lookup(hostname); + if (result != null && !result.isEmpty()) return result; + } catch (Exception ignored) { + // Falló Quad9, continuar + } + + // Intento 5: DNS del Sistema (Fallback final) try { return Dns.SYSTEM.lookup(hostname); } catch (UnknownHostException e) { @@ -82,6 +129,7 @@ public class NetworkUtils { } catch (Exception e) { // Si algo falla en la configuración DNS, usamos por defecto (implícito en el builder) + System.out.println("Error configurando DNS over HTTPS: " + e.getMessage()); } CLIENT = builder.build(); diff --git a/app/src/main/java/com/streamplayer/PlayerActivity.java b/app/src/main/java/com/streamplayer/PlayerActivity.java index cfe1393..c06a9eb 100644 --- a/app/src/main/java/com/streamplayer/PlayerActivity.java +++ b/app/src/main/java/com/streamplayer/PlayerActivity.java @@ -87,7 +87,7 @@ public class PlayerActivity extends AppCompatActivity { initViews(); channelLabel.setText(channelName); - DNSSetter.configureDNSToGoogle(this); + // DNS over HTTPS ya está configurado en NetworkUtils loadChannel(); } diff --git a/app/src/main/java/com/streamplayer/UpdateManager.java b/app/src/main/java/com/streamplayer/UpdateManager.java index d742c40..276d889 100644 --- a/app/src/main/java/com/streamplayer/UpdateManager.java +++ b/app/src/main/java/com/streamplayer/UpdateManager.java @@ -31,10 +31,10 @@ import java.lang.ref.WeakReference; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; import okhttp3.Request; +import okhttp3.Request; import okhttp3.Response; /** @@ -63,11 +63,8 @@ public class UpdateManager { this.appContext = context.getApplicationContext(); this.mainHandler = new Handler(Looper.getMainLooper()); this.networkExecutor = Executors.newSingleThreadExecutor(); - this.httpClient = new OkHttpClient.Builder() - .connectTimeout(15, TimeUnit.SECONDS) - .readTimeout(20, TimeUnit.SECONDS) - .callTimeout(25, TimeUnit.SECONDS) - .build(); + // Usar NetworkUtils para obtener cliente con DNS over HTTPS configurado + this.httpClient = NetworkUtils.getClient(); } public void checkForUpdates(UpdateCallback callback) {