From 3c1a323b35989ea3ca90c44edefcd1a1c255d901 Mon Sep 17 00:00:00 2001 From: renato97 Date: Wed, 28 Jan 2026 21:26:58 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20v10.1.2:=20Reproductor=20robusto?= =?UTF-8?q?=20con=20calidad=20adaptativa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✨ Mejoras principales: - Reproductor más robusto: reintenta automáticamente en errores 404 - Calidad adaptativa: eliminado forzamiento de 1080p - Sistema de reintentos: 3 intentos automáticos con delays - Timeouts mejorados: 20s connect, 30s read - Manejo granular de errores recuperables 📱 Cambios técnicos: - setForceHighestSupportedBitrate(false) - calidad adaptativa - Configuración de reintentos (MAX_RETRIES = 3) - Detección de errores 404, 403, timeout, network - Feedback visual durante reintentos - Timeouts incrementados para conexiones lentas 🔧 Build: - Incrementado versionCode: 100101 → 100102 - Incrementado versionName: 10.1.1 → 10.1.2 - APK compilado y subido a Gitea 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .env | 2 +- app/build.gradle | 4 +- .../java/com/streamplayer/PlayerActivity.java | 61 ++++++++++++++++--- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/.env b/.env index 21b9916..65c01bd 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -GITEA_TOKEN=7921aa22187b39125d29399d26f527ba26a2fb5b +GITEA_TOKEN=efeed2af00597883adb04da70bd6a7c2993ae92d GEMINI_API_KEY=AIzaSyDWOgyAJqscuPU6iSpS6gxupWBm4soNw5o TELEGRAM_BOT_TOKEN=8593525164:AAGCX9B_RJGN35_F7tSB72rEZhS_4Zpcszs TELEGRAM_CHAT_ID=692714536 diff --git a/app/build.gradle b/app/build.gradle index 5442c5d..df85da8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.streamplayer" minSdk 21 targetSdk 35 - versionCode 100101 - versionName "10.1.1" + versionCode 100102 + versionName "10.1.2" buildConfigField "String", "DEVICE_REGISTRY_URL", '"http://194.163.191.200:4000"' } diff --git a/app/src/main/java/com/streamplayer/PlayerActivity.java b/app/src/main/java/com/streamplayer/PlayerActivity.java index 5d1480d..cfe1393 100644 --- a/app/src/main/java/com/streamplayer/PlayerActivity.java +++ b/app/src/main/java/com/streamplayer/PlayerActivity.java @@ -55,6 +55,9 @@ public class PlayerActivity extends AppCompatActivity { private String channelUrl; private boolean overlayVisible = true; private OkHttpClient okHttpClient; + private int retryCount = 0; + private static final int MAX_RETRIES = 3; + private String lastStreamUrl; @Override protected void onCreate(Bundle savedInstanceState) { @@ -102,6 +105,7 @@ public class PlayerActivity extends AppCompatActivity { private void loadChannel() { showLoading(true); + retryCount = 0; // Resetear contador al cargar nuevo canal new Thread(() -> { try { String resolvedUrl = StreamUrlResolver.resolve(channelUrl); @@ -117,14 +121,17 @@ public class PlayerActivity extends AppCompatActivity { private void startPlayback(String streamUrl) { try { releasePlayer(); + lastStreamUrl = streamUrl; // Guardar URL para reintentos + retryCount = 0; // Resetear contador al iniciar nueva reproducción DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(this) .setEnableDecoderFallback(true) .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON); - // Configurar track selector para máxima calidad + // Configurar track selector para calidad adaptativa (no forzar máxima calidad) trackSelector = new DefaultTrackSelector(this); DefaultTrackSelector.Parameters params = trackSelector.buildUponParameters() - .setForceHighestSupportedBitrate(true) // Forzar máximo bitrate + .setForceHighestSupportedBitrate(false) // Permitir calidad adaptativa + .setMaxVideoBitrate(Integer.MAX_VALUE) // Sin límite máximo de bitrate .build(); trackSelector.setParameters(params); @@ -140,6 +147,7 @@ public class PlayerActivity extends AppCompatActivity { public void onPlaybackStateChanged(int playbackState) { if (playbackState == Player.STATE_READY) { showLoading(false); + retryCount = 0; // Resetear contador de reintentos al reproducir exitosamente } else if (playbackState == Player.STATE_BUFFERING) { showLoading(true); } @@ -147,9 +155,46 @@ public class PlayerActivity extends AppCompatActivity { @Override public void onPlayerError(PlaybackException error) { - String detail = error.getCause() != null ? + String errorMsg = error.getMessage() != null ? error.getMessage() : ""; + String detail = error.getCause() != null ? error.getCause().getMessage() : ""; - showError("Error al reproducir: " + error.getMessage() + " " + detail); + String fullError = errorMsg + " " + detail; + + // Verificar si es un error que justifica reintento (404, conectividad, etc.) + boolean isRetryableError = + fullError.contains("404") || + fullError.contains("403") || + fullError.contains("timeout") || + fullError.contains("Unable to connect") || + fullError.contains("Network") || + fullError.contains("source error") || + error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED || + error.errorCode == PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT || + error.errorCode == PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS; + + if (isRetryableError && retryCount < MAX_RETRIES) { + retryCount++; + runOnUiThread(() -> { + showLoading(true); + showError("Error de conexión. Reintentando... (" + retryCount + "/" + MAX_RETRIES + ")"); + }); + + // Reintentar después de 2 segundos + new android.os.Handler(android.os.Looper.getMainLooper()).postDelayed(() -> { + if (lastStreamUrl != null) { + startPlayback(lastStreamUrl); + } else { + loadChannel(); + } + }, 2000); + } else { + // Mostrar error final después de agotar reintentos + String finalMessage = "Error al reproducir: " + fullError; + if (retryCount >= MAX_RETRIES) { + finalMessage += "\n\nSe agotaron los reintentos (" + MAX_RETRIES + ")."; + } + showError(finalMessage); + } } }); @@ -210,8 +255,8 @@ public class PlayerActivity extends AppCompatActivity { try { OkHttpClient bootstrap = new OkHttpClient.Builder() - .connectTimeout(15, TimeUnit.SECONDS) - .readTimeout(15, TimeUnit.SECONDS) + .connectTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); @@ -228,8 +273,8 @@ public class PlayerActivity extends AppCompatActivity { .build(); } catch (UnknownHostException e) { okHttpClient = new OkHttpClient.Builder() - .connectTimeout(15, TimeUnit.SECONDS) - .readTimeout(15, TimeUnit.SECONDS) + .connectTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) .retryOnConnectionFailure(true) .build(); }