diff --git a/app/src/main/java/com/foxx/androidcast/AppPreferences.java b/app/src/main/java/com/foxx/androidcast/AppPreferences.java
index 3295935..d97a17f 100644
--- a/app/src/main/java/com/foxx/androidcast/AppPreferences.java
+++ b/app/src/main/java/com/foxx/androidcast/AppPreferences.java
@@ -18,6 +18,8 @@ public final class AppPreferences {
private static final String KEY_THEME = "theme_mode";
private static final String KEY_LOCALE = "locale_mode";
private static final String KEY_PLAY_INCOMING_AUDIO = "play_incoming_audio";
+ private static final String KEY_DEV_RECEIVER_DEBUG_OVERLAY = "dev_receiver_debug_overlay";
+ private static final String KEY_DEV_GRAB_SESSION_STATS = "dev_grab_session_stats";
private static final String PREFIX_SENDER = "sender_";
private static final String PREFIX_RECEIVER = "receiver_";
@@ -92,6 +94,24 @@ public final class AppPreferences {
prefs(context).edit().putBoolean(KEY_PLAY_INCOMING_AUDIO, play).apply();
}
+ /** Developer: metrics HTML overlay on receiver video (default on). */
+ public static boolean isShowReceiverDebugOverlay(Context context) {
+ return prefs(context).getBoolean(KEY_DEV_RECEIVER_DEBUG_OVERLAY, true);
+ }
+
+ public static void setShowReceiverDebugOverlay(Context context, boolean show) {
+ prefs(context).edit().putBoolean(KEY_DEV_RECEIVER_DEBUG_OVERLAY, show).apply();
+ }
+
+ /** Developer: write anonymous session_*.json files (default on). */
+ public static boolean isGrabSessionStats(Context context) {
+ return prefs(context).getBoolean(KEY_DEV_GRAB_SESSION_STATS, true);
+ }
+
+ public static void setGrabSessionStats(Context context, boolean grab) {
+ prefs(context).edit().putBoolean(KEY_DEV_GRAB_SESSION_STATS, grab).apply();
+ }
+
public static CastSettings loadSenderDefaults(Context context) {
CastSettings s = new CastSettings();
applyStoredCastSettings(context, PREFIX_SENDER, s);
diff --git a/app/src/main/java/com/foxx/androidcast/CastConfig.java b/app/src/main/java/com/foxx/androidcast/CastConfig.java
index 0bf801e..333b6eb 100644
--- a/app/src/main/java/com/foxx/androidcast/CastConfig.java
+++ b/app/src/main/java/com/foxx/androidcast/CastConfig.java
@@ -56,9 +56,6 @@ public final class CastConfig {
/** Max UDP payload chunk (fits typical Wi‑Fi MTU with header). */
public static final int UDP_CHUNK_SIZE = 1200;
- /** Show diagnostics overlay on receiver playback (debug). */
- public static final boolean SHOW_CAST_DIAGNOSTICS = true;
-
/** Max retained session stat JSON files (room for one new file on next session). */
public static final int SESSION_STATS_MAX_FILES = 20;
diff --git a/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java b/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java
index 799335f..6614eff 100644
--- a/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java
+++ b/app/src/main/java/com/foxx/androidcast/DeveloperSettingsActivity.java
@@ -1,15 +1,34 @@
package com.foxx.androidcast;
+import android.content.Context;
import android.os.Bundle;
+import android.widget.CheckBox;
import androidx.appcompat.app.AppCompatActivity;
/** Hidden developer settings (opened via version label easter egg). */
public class DeveloperSettingsActivity extends AppCompatActivity {
+ @Override
+ protected void attachBaseContext(Context newBase) {
+ super.attachBaseContext(CastLocaleHelper.attach(newBase));
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
+ CastThemeHelper.applyTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_developer_settings);
setTitle(R.string.developer_settings_title);
+
+ CheckBox debugOverlay = findViewById(R.id.check_receiver_debug_overlay);
+ CheckBox sessionStats = findViewById(R.id.check_grab_session_stats);
+
+ debugOverlay.setChecked(AppPreferences.isShowReceiverDebugOverlay(this));
+ sessionStats.setChecked(AppPreferences.isGrabSessionStats(this));
+
+ debugOverlay.setOnCheckedChangeListener((buttonView, isChecked) ->
+ AppPreferences.setShowReceiverDebugOverlay(this, isChecked));
+ sessionStats.setOnCheckedChangeListener((buttonView, isChecked) ->
+ AppPreferences.setGrabSessionStats(this, isChecked));
}
}
diff --git a/app/src/main/java/com/foxx/androidcast/MainActivity.java b/app/src/main/java/com/foxx/androidcast/MainActivity.java
index 181a94d..d8bcec0 100644
--- a/app/src/main/java/com/foxx/androidcast/MainActivity.java
+++ b/app/src/main/java/com/foxx/androidcast/MainActivity.java
@@ -17,7 +17,9 @@ public class MainActivity extends DrawerHostActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- SessionStatsStore.pruneOnAppStart(this);
+ if (AppPreferences.isGrabSessionStats(this)) {
+ SessionStatsStore.pruneOnAppStart(this);
+ }
com.foxx.androidcast.network.CastTransportFactory.init(this);
PermissionHelper.request(this);
diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java
index c0930eb..1a2f408 100644
--- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java
+++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverCastService.java
@@ -159,7 +159,9 @@ public class ReceiverCastService extends Service {
public void onCreate() {
super.onCreate();
CastNotifications.createChannels(this);
- SessionStatsStore.pruneOnAppStart(this);
+ if (AppPreferences.isGrabSessionStats(this)) {
+ SessionStatsStore.pruneOnAppStart(this);
+ }
videoDecodeThread = new HandlerThread("VideoDecode");
videoDecodeThread.start();
videoDecodeHandler = new Handler(videoDecodeThread.getLooper());
@@ -375,12 +377,14 @@ public class ReceiverCastService extends Service {
private void onSenderConnected(String senderName, CastSettings remoteSettings, String videoMime) {
phase = Phase.CONNECTED;
castEnded = false;
- if (sessionStatsRecorder == null) {
- sessionStatsRecorder = new SessionStatsRecorder("receiver", settings.getTransport());
- sessionStatsRecorder.setClientCount(1);
+ if (AppPreferences.isGrabSessionStats(this)) {
+ if (sessionStatsRecorder == null) {
+ sessionStatsRecorder = new SessionStatsRecorder("receiver", settings.getTransport());
+ sessionStatsRecorder.setClientCount(1);
+ }
+ sessionStatsRecorder.mergeSettings(remoteSettings);
+ sessionStatsRecorder.setCodecs(videoMime, "AAC");
}
- sessionStatsRecorder.mergeSettings(remoteSettings);
- sessionStatsRecorder.setCodecs(videoMime, "AAC");
negotiatedVideoMime = videoMime;
remoteCastSettings = remoteSettings;
streamIdle = false;
diff --git a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java
index 0428efa..16942f6 100644
--- a/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java
+++ b/app/src/main/java/com/foxx/androidcast/receiver/ReceiverPlaybackActivity.java
@@ -23,7 +23,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.foxx.androidcast.AppPreferences;
-import com.foxx.androidcast.CastConfig;
import com.foxx.androidcast.CastSettings;
import com.foxx.androidcast.DrawerHostActivity;
import com.foxx.androidcast.CastThemeHelper;
@@ -296,7 +295,7 @@ public class ReceiverPlaybackActivity extends DrawerHostActivity {
if (diagnosticsText == null) {
return;
}
- boolean show = CastConfig.SHOW_CAST_DIAGNOSTICS && streamRendering;
+ boolean show = AppPreferences.isShowReceiverDebugOverlay(this) && streamRendering;
diagnosticsText.setVisibility(show ? View.VISIBLE : View.GONE);
if (show) {
diagnosticsText.bringToFront();
@@ -304,7 +303,8 @@ public class ReceiverPlaybackActivity extends DrawerHostActivity {
}
private void refreshDiagnostics() {
- if (diagnosticsText == null || !CastConfig.SHOW_CAST_DIAGNOSTICS || !bound || receiverService == null) {
+ if (diagnosticsText == null || !AppPreferences.isShowReceiverDebugOverlay(this)
+ || !bound || receiverService == null) {
return;
}
if (!streamRendering) {
diff --git a/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java b/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java
index 2b972ec..05125da 100644
--- a/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java
+++ b/app/src/main/java/com/foxx/androidcast/sender/ScreenCastService.java
@@ -153,7 +153,9 @@ public class ScreenCastService extends Service implements
@Override
public void onCreate() {
super.onCreate();
- SessionStatsStore.pruneOnAppStart(this);
+ if (AppPreferences.isGrabSessionStats(this)) {
+ SessionStatsStore.pruneOnAppStart(this);
+ }
CastNotifications.createChannels(this);
com.foxx.androidcast.network.CastTransportFactory.init(this);
projectionThread = new HandlerThread("CastProjection");
@@ -263,10 +265,12 @@ public class ScreenCastService extends Service implements
CastActiveState.setSenderCasting(true);
CastTrayNotifier.refresh(this);
activeSettings = settings;
- sessionStatsRecorder = new SessionStatsRecorder("sender", settings.getTransport());
- sessionStatsRecorder.mergeSettings(settings);
- sessionStatsRecorder.setClientCount(peers.size());
- sessionStatsRecorder.setCodecs(settings.getNegotiatedVideoMime(), "AAC");
+ if (AppPreferences.isGrabSessionStats(this)) {
+ sessionStatsRecorder = new SessionStatsRecorder("sender", settings.getTransport());
+ sessionStatsRecorder.mergeSettings(settings);
+ sessionStatsRecorder.setClientCount(peers.size());
+ sessionStatsRecorder.setCodecs(settings.getNegotiatedVideoMime(), "AAC");
+ }
final int projResultCode = resultCode;
final Intent projData = data != null ? new Intent(data) : null;
if (calibration) {
diff --git a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java
index a9f2ac4..d67afac 100644
--- a/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java
+++ b/app/src/main/java/com/foxx/androidcast/stats/SessionStatsRecorder.java
@@ -2,6 +2,7 @@ package com.foxx.androidcast.stats;
import android.content.Context;
+import com.foxx.androidcast.AppPreferences;
import com.foxx.androidcast.CastSettings;
import com.foxx.androidcast.network.control.NetworkStatsSnapshot;
import com.foxx.androidcast.network.transport.TransportLossStats;
@@ -139,6 +140,9 @@ public final class SessionStatsRecorder {
}
public void finish(Context context) {
+ if (!AppPreferences.isGrabSessionStats(context)) {
+ return;
+ }
long endedMs = System.currentTimeMillis();
try {
JSONObject root = new JSONObject();
diff --git a/app/src/main/res/layout/activity_developer_settings.xml b/app/src/main/res/layout/activity_developer_settings.xml
index 0c3ab54..293771c 100644
--- a/app/src/main/res/layout/activity_developer_settings.xml
+++ b/app/src/main/res/layout/activity_developer_settings.xml
@@ -1,22 +1,36 @@
-
+ android:fillViewport="true">
-
+ android:orientation="vertical"
+ android:padding="24dp">
-
-
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 03649d5..a67242a 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -186,7 +186,8 @@
Лицензии
Не могу найти факл лицензий
Для разработчиков
- Additional developer options will appear here.
+ Показывать отладочный оверлей на приёмнике
+ Сохранять анонимную статистику сессий
Кодек для звука
libvpx (VP8)
libvpx (VP9)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c0130fa..1ca83d9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -186,7 +186,8 @@
Licenses
Could not load license text.
Developer settings
- Additional developer options will appear here.
+ Show debug overlay on receiver
+ Grab anonymous session stats
Voice codec
libvpx (VP8)
libvpx (VP9)
diff --git a/pull_stats.sh b/pull_stats.sh
index 9c981ad..1ee3264 100755
--- a/pull_stats.sh
+++ b/pull_stats.sh
@@ -1,3 +1,21 @@
-#!/bin/sh
-adb shell run-as com.foxx.androidcast ls files/session_stats/
-adb shell run-as com.foxx.androidcast cat files/session_stats/session_*.json
+#!/bin/bash
+DEVICES_LIST="$(adb devices -l)"
+echo "${DEVICES_LIST}"
+
+
+filter_out() {
+ local -n dev_string=${1}
+ [[ ${dev_string} =~ List* ]] && dev_string=""
+ return 0
+}
+
+echo "${DEVICES_LIST}" | while IFS= read -r DEV; do
+ SERIAL="$(echo "${DEV}" | awk '{print $1}')"
+ filter_out SERIAL
+ [ -z "${SERIAL}" ] && continue
+# echo "Device: ${DEV}"
+# echo "Serial: ${SERIAL}"
+ adb -s "${SERIAL}" shell run-as com.foxx.androidcast ls files/session_stats/
+ adb -s "${SERIAL}" shell run-as com.foxx.androidcast cat files/session_stats/session_*.json
+done
+