diff --git a/app/build.gradle b/app/build.gradle
index 37d5973..5441d65 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,8 +8,8 @@ android {
applicationId "com.streamplayer"
minSdk 21
targetSdk 33
- versionCode 94500
- versionName "9.4.5"
+ versionCode 94600
+ versionName "9.4.6"
buildConfigField "String", "DEVICE_REGISTRY_URL", '"http://194.163.191.200:4000"'
}
diff --git a/app/src/main/java/com/streamplayer/MainActivity.java b/app/src/main/java/com/streamplayer/MainActivity.java
index 7e1dd5f..b36d16c 100644
--- a/app/src/main/java/com/streamplayer/MainActivity.java
+++ b/app/src/main/java/com/streamplayer/MainActivity.java
@@ -5,11 +5,11 @@ import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
+import android.graphics.drawable.ColorDrawable;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
@@ -69,6 +69,7 @@ public class MainActivity extends AppCompatActivity {
contentTitle = findViewById(R.id.content_title);
eventsRefreshButton = findViewById(R.id.events_refresh_button);
eventsRefreshButton.setOnClickListener(v -> manualRefreshEvents());
+ applyFocusHighlight(eventsRefreshButton);
channelAdapter = new ChannelAdapter(
channel -> openPlayer(channel.getName(), channel.getPageUrl()));
@@ -296,26 +297,41 @@ public class MainActivity extends AppCompatActivity {
if (info == null) {
return;
}
- showUpdateDialog(info, true);
+ showUpdateDialog(info);
}
- private void showUpdateDialog(UpdateManager.UpdateInfo info, boolean mandatory) {
+ private void showUpdateDialog(UpdateManager.UpdateInfo info) {
if (isFinishing()) {
return;
}
if (updateDialog != null && updateDialog.isShowing()) {
updateDialog.dismiss();
}
- AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.ThemeOverlay_StreamPlayer_AlertDialog)
- .setTitle(R.string.update_required_title)
- .setMessage(buildUpdateMessage(info))
- .setPositiveButton(R.string.update_action_download,
- (dialog, which) -> updateManager.downloadUpdate(MainActivity.this, info))
- .setNegativeButton(R.string.update_action_close_app,
- (dialog, which) -> closeAppCompletely())
- .setCancelable(false);
- updateDialog = builder.show();
- updateDialog.setCanceledOnTouchOutside(false);
+ View dialogView = getLayoutInflater().inflate(R.layout.dialog_update, null);
+ TextView titleView = dialogView.findViewById(R.id.update_title);
+ TextView messageView = dialogView.findViewById(R.id.update_message);
+ Button positiveButton = dialogView.findViewById(R.id.update_positive_button);
+ Button negativeButton = dialogView.findViewById(R.id.update_negative_button);
+ titleView.setText(R.string.update_required_title);
+ messageView.setText(buildUpdateMessage(info));
+ AlertDialog dialog = new AlertDialog.Builder(this, R.style.ThemeOverlay_StreamPlayer_AlertDialog)
+ .setView(dialogView)
+ .setCancelable(false)
+ .create();
+ dialog.setCanceledOnTouchOutside(false);
+ dialog.show();
+ if (dialog.getWindow() != null) {
+ dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
+ }
+ positiveButton.setOnClickListener(v -> {
+ dialog.dismiss();
+ updateManager.downloadUpdate(MainActivity.this, info);
+ });
+ negativeButton.setOnClickListener(v -> closeAppCompletely());
+ applyFocusHighlight(positiveButton);
+ applyFocusHighlight(negativeButton);
+ positiveButton.requestFocus();
+ updateDialog = dialog;
}
private CharSequence buildUpdateMessage(UpdateManager.UpdateInfo info) {
@@ -394,6 +410,16 @@ public class MainActivity extends AppCompatActivity {
Toast.makeText(this, R.string.device_blocked_copy_success, Toast.LENGTH_SHORT).show();
}
+ private void applyFocusHighlight(View view) {
+ if (view == null) {
+ return;
+ }
+ view.setOnFocusChangeListener((v, hasFocus) -> {
+ float scale = hasFocus ? 1.05f : 1f;
+ v.animate().scaleX(scale).scaleY(scale).setDuration(120).start();
+ });
+ }
+
private void startEventPrefetchScheduler() {
if (eventPrefetchHandler == null) {
eventPrefetchHandler = new Handler(Looper.getMainLooper());
diff --git a/app/src/main/res/drawable/bg_dialog_button_primary.xml b/app/src/main/res/drawable/bg_dialog_button_primary.xml
new file mode 100644
index 0000000..9f798b1
--- /dev/null
+++ b/app/src/main/res/drawable/bg_dialog_button_primary.xml
@@ -0,0 +1,62 @@
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/bg_dialog_button_secondary.xml b/app/src/main/res/drawable/bg_dialog_button_secondary.xml
new file mode 100644
index 0000000..c7caaf0
--- /dev/null
+++ b/app/src/main/res/drawable/bg_dialog_button_secondary.xml
@@ -0,0 +1,77 @@
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_update.xml b/app/src/main/res/layout/dialog_update.xml
new file mode 100644
index 0000000..8baf6be
--- /dev/null
+++ b/app/src/main/res/layout/dialog_update.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dashboard/data/devices.json b/dashboard/data/devices.json
index 9db2c32..1873c06 100644
--- a/dashboard/data/devices.json
+++ b/dashboard/data/devices.json
@@ -6,8 +6,8 @@
"model": "SM-S928B",
"manufacturer": "Samsung",
"osVersion": "16 (API 36)",
- "appVersionName": "9.4.5",
- "appVersionCode": 94500,
+ "appVersionName": "9.4.6",
+ "appVersionCode": 94600,
"firstSeen": "2025-11-23T22:31:13.359Z",
"lastSeen": "2025-11-23T23:11:07.215Z",
"blocked": false,
diff --git a/update-manifest.json b/update-manifest.json
index 5c2c753..ae42012 100644
--- a/update-manifest.json
+++ b/update-manifest.json
@@ -1,10 +1,10 @@
{
- "versionCode": 94500,
- "versionName": "9.4.5",
+ "versionCode": 94600,
+ "versionName": "9.4.6",
"minSupportedVersionCode": 91000,
"forceUpdate": true,
- "downloadUrl": "https://gitea.cbcren.online/renato97/app/releases/download/v9.4.5/StreamPlayer-v9.4.5.apk",
- "fileName": "StreamPlayer-v9.4.5.apk",
- "sizeBytes": 5947752,
- "notes": "StreamPlayer v9.4.5\n\nNovedades:\n\n- El botón \"Actualizar ahora\" de Eventos resalta cuando está enfocado o presionado para que siempre sepas que quedó seleccionado.\n- Las actualizaciones in-app ahora son obligatorias: cuando hay una versión nueva solo verás las opciones Actualizar o Salir.\n- Se eliminó el botón de \"Ver detalles\" para evitar redirecciones; todo sucede dentro de la app.\n- Ajustes visuales adicionales en los diálogos para mantener el contraste óptimo.\n\nActualiza para asegurarte de recibir inmediatamente las últimas correcciones sin pasos adicionales."
+ "downloadUrl": "https://gitea.cbcren.online/renato97/app/releases/download/v9.4.6/StreamPlayer-v9.4.6.apk",
+ "fileName": "StreamPlayer-v9.4.6.apk",
+ "sizeBytes": 5951142,
+ "notes": "StreamPlayer v9.4.6\n\nMejoras clave:\n\n- Diálogo de actualización totalmente personalizado con fondo oscuro, compatible con OneUI 8/Android 16 y sin cuadros blancos.\n- Botones \"Actualizar\" y \"Salir\" ahora tienen indicadores de foco/hover y animaciones para controles de TV.\n- El botón \"Actualizar ahora\" en Eventos también hereda resaltado al navegar con control remoto.\n- Se mantiene el flujo obligatorio de actualización y la descarga directa desde la app.\n\nRecomendamos instalar esta versión para garantizar la mejor experiencia en televisores y dispositivos Samsung recientes."
}