Update v9.4.6: Custom Update Dialog & Focus States
This commit is contained in:
@@ -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"'
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
62
app/src/main/res/drawable/bg_dialog_button_primary.xml
Normal file
62
app/src/main/res/drawable/bg_dialog_button_primary.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="false">
|
||||
<shape>
|
||||
<solid android:color="@color/accent_blue_disabled" />
|
||||
<corners android:radius="28dp" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape>
|
||||
<solid android:color="@color/accent_blue_light" />
|
||||
<corners android:radius="28dp" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_focused="true">
|
||||
<shape>
|
||||
<solid android:color="@color/accent_blue_light" />
|
||||
<corners android:radius="28dp" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_hovered="true">
|
||||
<shape>
|
||||
<solid android:color="@color/accent_blue_light" />
|
||||
<corners android:radius="28dp" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="@color/accent_blue" />
|
||||
<corners android:radius="28dp" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
77
app/src/main/res/drawable/bg_dialog_button_secondary.xml
Normal file
77
app/src/main/res/drawable/bg_dialog_button_secondary.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="false">
|
||||
<shape>
|
||||
<solid android:color="#00000000" />
|
||||
<corners android:radius="28dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/accent_blue_disabled" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape>
|
||||
<solid android:color="#26FFFFFF" />
|
||||
<corners android:radius="28dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/white" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_focused="true">
|
||||
<shape>
|
||||
<solid android:color="#26FFFFFF" />
|
||||
<corners android:radius="28dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/white" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_hovered="true">
|
||||
<shape>
|
||||
<solid android:color="#26FFFFFF" />
|
||||
<corners android:radius="28dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/white" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="#00000000" />
|
||||
<corners android:radius="28dp" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/white" />
|
||||
<padding
|
||||
android:bottom="8dp"
|
||||
android:left="16dp"
|
||||
android:right="16dp"
|
||||
android:top="8dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
79
app/src/main/res/layout/dialog_update.xml
Normal file
79
app/src/main/res/layout/dialog_update.xml
Normal file
@@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_dialog_dark"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/update_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/update_required_title" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:maxHeight="320dp"
|
||||
android:overScrollMode="never">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/update_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:lineSpacingExtra="4dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp" />
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/update_button_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/update_positive_button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_dialog_button_primary"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/update_action_download"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<Space
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/update_negative_button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/bg_dialog_button_secondary"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/update_action_close_app"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/white"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -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,
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user