From d46d4902df429d1e3939e1f984cb38f840681d98 Mon Sep 17 00:00:00 2001 From: Phenix Date: Sat, 7 Feb 2026 04:48:57 +0800 Subject: [PATCH 1/7] auto-claude: subtask-1-1 - Create NetworkChangeReceiver with NetworkCallback - Created NetworkChangeReceiver extending BroadcastReceiver - Follows BootReceiver pattern for code style consistency - Handles CONNECTIVITY_ACTION and WiFi state change intents - Checks for active WiFi connection using NetworkCapabilities - Includes companion methods for modern NetworkCallback registration - Placeholder for auto-reconnect logic (to be added in subtask-2-2) - Includes comprehensive logging for debugging Co-Authored-By: Claude Sonnet 4.5 --- .../wirelessadb/NetworkChangeReceiver.kt | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt diff --git a/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt new file mode 100644 index 0000000..369809b --- /dev/null +++ b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt @@ -0,0 +1,106 @@ +package com.phenix.wirelessadb + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.NetworkRequest +import android.util.Log + +/** + * Monitors network connectivity changes to automatically re-enable wireless ADB + * when the device connects to a new WiFi network or when network changes occur. + */ +class NetworkChangeReceiver : BroadcastReceiver() { + + override fun onReceive(context: Context, intent: Intent) { + Log.d(TAG, "onReceive: action=${intent.action}") + + when (intent.action) { + ConnectivityManager.CONNECTIVITY_ACTION, + "android.net.wifi.STATE_CHANGE", + "android.net.wifi.WIFI_STATE_CHANGED" -> { + handleNetworkChange(context) + } + } + } + + private fun handleNetworkChange(context: Context) { + Log.d(TAG, "handleNetworkChange: Network state changed") + + // Check if device is connected to WiFi + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager + if (connectivityManager == null) { + Log.e(TAG, "handleNetworkChange: ConnectivityManager not available") + return + } + + val network = connectivityManager.activeNetwork + if (network == null) { + Log.d(TAG, "handleNetworkChange: No active network") + return + } + + val capabilities = connectivityManager.getNetworkCapabilities(network) + if (capabilities == null) { + Log.d(TAG, "handleNetworkChange: No network capabilities") + return + } + + val isWifi = capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + Log.d(TAG, "handleNetworkChange: isWifi=$isWifi") + + if (isWifi) { + // Auto-reconnect logic will be implemented in subtask-2-2 + // For now, just log that WiFi is connected + Log.d(TAG, "handleNetworkChange: WiFi connected, ready for auto-reconnect") + } + } + + companion object { + private const val TAG = "NetworkChangeReceiver" + + /** + * Register a NetworkCallback for more granular network monitoring. + * This is the modern approach compared to using broadcast receivers. + */ + fun registerNetworkCallback(context: Context, callback: ConnectivityManager.NetworkCallback) { + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager + if (connectivityManager == null) { + Log.e(TAG, "registerNetworkCallback: ConnectivityManager not available") + return + } + + val request = NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .build() + + try { + connectivityManager.registerNetworkCallback(request, callback) + Log.d(TAG, "registerNetworkCallback: NetworkCallback registered") + } catch (e: Exception) { + Log.e(TAG, "registerNetworkCallback: Failed to register callback", e) + } + } + + /** + * Unregister a previously registered NetworkCallback. + */ + fun unregisterNetworkCallback(context: Context, callback: ConnectivityManager.NetworkCallback) { + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager + if (connectivityManager == null) { + Log.e(TAG, "unregisterNetworkCallback: ConnectivityManager not available") + return + } + + try { + connectivityManager.unregisterNetworkCallback(callback) + Log.d(TAG, "unregisterNetworkCallback: NetworkCallback unregistered") + } catch (e: Exception) { + Log.e(TAG, "unregisterNetworkCallback: Failed to unregister callback", e) + } + } + } +} From a1f955c47e7a8226d78669419ab67842c0042453 Mon Sep 17 00:00:00 2001 From: Phenix Date: Sat, 7 Feb 2026 04:51:29 +0800 Subject: [PATCH 2/7] auto-claude: subtask-1-2 - Register NetworkChangeReceiver in AndroidManifest --- .auto-claude-security.json | 31 ++++--------------------------- .auto-claude-status | 14 +++++++------- .claude_settings.json | 16 ++++++++-------- app/src/main/AndroidManifest.xml | 9 +++++++++ 4 files changed, 28 insertions(+), 42 deletions(-) diff --git a/.auto-claude-security.json b/.auto-claude-security.json index f740b91..a6f14ec 100644 --- a/.auto-claude-security.json +++ b/.auto-claude-security.json @@ -128,37 +128,15 @@ "zsh" ], "stack_commands": [ - "ant", "gradle", "gradlew", - "ipython", - "jar", - "java", - "javac", - "jupyter", "kotlin", - "kotlinc", - "maven", - "mvn", - "node", - "notebook", - "npm", - "npx", - "pdb", - "pip", - "pip3", - "pipx", - "pudb", - "python", - "python3" + "kotlinc" ], "script_commands": [], "custom_commands": [], "detected_stack": { "languages": [ - "python", - "javascript", - "java", "kotlin" ], "package_managers": [ @@ -178,8 +156,7 @@ "cargo_aliases": [], "shell_scripts": [] }, - "project_dir": "D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb", - "created_at": "2026-02-05T12:56:49.824459", - "project_hash": "0d6be561318e22002fe7a184fb411324", - "inherited_from": "D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb" + "project_dir": "D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change", + "created_at": "2026-02-07T04:33:20.891367", + "project_hash": "952e2679948002cb8b971be36b6a9f99" } \ No newline at end of file diff --git a/.auto-claude-status b/.auto-claude-status index db8b938..407b2a8 100644 --- a/.auto-claude-status +++ b/.auto-claude-status @@ -1,15 +1,15 @@ { "active": true, - "spec": "002-quick-settings-tile", + "spec": "007-auto-reconnect-on-network-change", "state": "building", "subtasks": { - "completed": 9, - "total": 10, + "completed": 1, + "total": 8, "in_progress": 1, "failed": 0 }, "phase": { - "current": "Integration Testing", + "current": "Network Change Detection", "id": null, "total": 2 }, @@ -18,8 +18,8 @@ "max": 1 }, "session": { - "number": 12, - "started_at": "2026-02-07T01:52:02.329153" + "number": 3, + "started_at": "2026-02-07T04:33:05.351503" }, - "last_update": "2026-02-07T02:19:18.722326" + "last_update": "2026-02-07T04:49:32.364477" } \ No newline at end of file diff --git a/.claude_settings.json b/.claude_settings.json index 40e7866..b4bd7ff 100644 --- a/.claude_settings.json +++ b/.claude_settings.json @@ -11,14 +11,14 @@ "Edit(./**)", "Glob(./**)", "Grep(./**)", - "Read(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile/**)", - "Write(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile/**)", - "Edit(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile/**)", - "Glob(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile/**)", - "Grep(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile/**)", - "Read(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile\\.auto-claude\\specs\\002-quick-settings-tile/**)", - "Write(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile\\.auto-claude\\specs\\002-quick-settings-tile/**)", - "Edit(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\002-quick-settings-tile\\.auto-claude\\specs\\002-quick-settings-tile/**)", + "Read(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change/**)", + "Write(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change/**)", + "Edit(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change/**)", + "Glob(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change/**)", + "Grep(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change/**)", + "Read(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change\\.auto-claude\\specs\\007-auto-reconnect-on-network-change/**)", + "Write(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change\\.auto-claude\\specs\\007-auto-reconnect-on-network-change/**)", + "Edit(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude\\worktrees\\tasks\\007-auto-reconnect-on-network-change\\.auto-claude\\specs\\007-auto-reconnect-on-network-change/**)", "Read(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude/**)", "Write(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude/**)", "Edit(D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb\\.auto-claude/**)", diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c8a3740..fd2135a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -59,6 +59,15 @@ + + + + + + Date: Sat, 7 Feb 2026 04:54:48 +0800 Subject: [PATCH 3/7] auto-claude: subtask-2-1 - Add auto-reconnect preferences to PrefsManager --- .../com/phenix/wirelessadb/PrefsManager.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt b/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt index f238dd7..67539e4 100644 --- a/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt +++ b/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt @@ -36,6 +36,13 @@ object PrefsManager { private const val KEY_WARPGATE_TARGET = "warpgate_target" private const val KEY_WARPGATE_LOCAL_PORT = "warpgate_local_port" + // Auto-reconnect settings + private const val KEY_AUTO_RECONNECT_ENABLED = "auto_reconnect_enabled" + private const val KEY_AUTO_RECONNECT_DELAY = "auto_reconnect_delay" + private const val KEY_AUTO_RECONNECT_MAX_RETRIES = "auto_reconnect_max_retries" + private const val DEFAULT_AUTO_RECONNECT_DELAY = 5000 // 5 seconds + private const val DEFAULT_AUTO_RECONNECT_MAX_RETRIES = 3 + private fun getPrefs(context: Context): SharedPreferences { return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) } @@ -149,4 +156,29 @@ object PrefsManager { fun setAccentColor(context: Context, color: AccentColor) { getPrefs(context).edit().putInt(KEY_ACCENT_COLOR, color.ordinal).apply() } + + // Auto-reconnect Configuration + fun isAutoReconnectEnabled(context: Context): Boolean { + return getPrefs(context).getBoolean(KEY_AUTO_RECONNECT_ENABLED, true) + } + + fun setAutoReconnectEnabled(context: Context, enabled: Boolean) { + getPrefs(context).edit().putBoolean(KEY_AUTO_RECONNECT_ENABLED, enabled).apply() + } + + fun getAutoReconnectDelay(context: Context): Int { + return getPrefs(context).getInt(KEY_AUTO_RECONNECT_DELAY, DEFAULT_AUTO_RECONNECT_DELAY) + } + + fun setAutoReconnectDelay(context: Context, delay: Int) { + getPrefs(context).edit().putInt(KEY_AUTO_RECONNECT_DELAY, delay).apply() + } + + fun getAutoReconnectMaxRetries(context: Context): Int { + return getPrefs(context).getInt(KEY_AUTO_RECONNECT_MAX_RETRIES, DEFAULT_AUTO_RECONNECT_MAX_RETRIES) + } + + fun setAutoReconnectMaxRetries(context: Context, retries: Int) { + getPrefs(context).edit().putInt(KEY_AUTO_RECONNECT_MAX_RETRIES, retries).apply() + } } From 4bf415ceb50f9d97f2c63f61b5352c4c9557fc73 Mon Sep 17 00:00:00 2001 From: Phenix Date: Sat, 7 Feb 2026 05:01:22 +0800 Subject: [PATCH 4/7] auto-claude: subtask-2-2 - Implement auto-reconnect logic in NetworkChangeReceiver - Added coroutine imports (CoroutineScope, Dispatchers, launch) - Check if auto-reconnect is enabled via PrefsManager.isAutoReconnectEnabled() - Get current ADB status to verify it was previously enabled - Re-enable ADB on port using AdbManager.enable() in IO coroutine - Follows BootReceiver pattern for async operations - Only reconnects if ADB was already enabled before network change Co-Authored-By: Claude Sonnet 4.5 --- .auto-claude-status | 10 +++---- .../wirelessadb/NetworkChangeReceiver.kt | 29 +++++++++++++++++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/.auto-claude-status b/.auto-claude-status index 407b2a8..351e164 100644 --- a/.auto-claude-status +++ b/.auto-claude-status @@ -3,23 +3,23 @@ "spec": "007-auto-reconnect-on-network-change", "state": "building", "subtasks": { - "completed": 1, + "completed": 3, "total": 8, "in_progress": 1, "failed": 0 }, "phase": { - "current": "Network Change Detection", + "current": "Auto-Reconnect Logic", "id": null, - "total": 2 + "total": 3 }, "workers": { "active": 0, "max": 1 }, "session": { - "number": 3, + "number": 5, "started_at": "2026-02-07T04:33:05.351503" }, - "last_update": "2026-02-07T04:49:32.364477" + "last_update": "2026-02-07T04:55:22.165617" } \ No newline at end of file diff --git a/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt index 369809b..5f0d7d6 100644 --- a/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt +++ b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt @@ -8,6 +8,9 @@ import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest import android.util.Log +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch /** * Monitors network connectivity changes to automatically re-enable wireless ADB @@ -53,9 +56,29 @@ class NetworkChangeReceiver : BroadcastReceiver() { Log.d(TAG, "handleNetworkChange: isWifi=$isWifi") if (isWifi) { - // Auto-reconnect logic will be implemented in subtask-2-2 - // For now, just log that WiFi is connected - Log.d(TAG, "handleNetworkChange: WiFi connected, ready for auto-reconnect") + Log.d(TAG, "handleNetworkChange: WiFi connected, checking auto-reconnect") + + // Check if auto-reconnect is enabled + if (!PrefsManager.isAutoReconnectEnabled(context)) { + Log.d(TAG, "handleNetworkChange: Auto-reconnect is disabled") + return + } + + val port = PrefsManager.getPort(context) + + // Launch coroutine to check status and re-enable if needed + CoroutineScope(Dispatchers.IO).launch { + val status = AdbManager.getStatus(context) + Log.d(TAG, "handleNetworkChange: Current ADB status - enabled=${status.enabled}, port=${status.port}") + + // Only re-enable if ADB was previously enabled + if (status.enabled) { + Log.d(TAG, "handleNetworkChange: Re-enabling ADB on port $port") + AdbManager.enable(port) + } else { + Log.d(TAG, "handleNetworkChange: ADB was not previously enabled, skipping auto-reconnect") + } + } } } From fd4ca87c5f25e6679e2b5b9a9a68e5db78096d4b Mon Sep 17 00:00:00 2001 From: Phenix Date: Sat, 7 Feb 2026 05:10:44 +0800 Subject: [PATCH 5/7] auto-claude: subtask-2-3 - Update AdbService to handle network change notific --- .auto-claude-status | 6 +-- .../java/com/phenix/wirelessadb/AdbService.kt | 37 +++++++++++++++++++ .../wirelessadb/NetworkChangeReceiver.kt | 3 ++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/.auto-claude-status b/.auto-claude-status index 351e164..198c77d 100644 --- a/.auto-claude-status +++ b/.auto-claude-status @@ -3,7 +3,7 @@ "spec": "007-auto-reconnect-on-network-change", "state": "building", "subtasks": { - "completed": 3, + "completed": 4, "total": 8, "in_progress": 1, "failed": 0 @@ -18,8 +18,8 @@ "max": 1 }, "session": { - "number": 5, + "number": 6, "started_at": "2026-02-07T04:33:05.351503" }, - "last_update": "2026-02-07T04:55:22.165617" + "last_update": "2026-02-07T05:01:51.882050" } \ No newline at end of file diff --git a/app/src/main/java/com/phenix/wirelessadb/AdbService.kt b/app/src/main/java/com/phenix/wirelessadb/AdbService.kt index d71ba0b..7491fa3 100644 --- a/app/src/main/java/com/phenix/wirelessadb/AdbService.kt +++ b/app/src/main/java/com/phenix/wirelessadb/AdbService.kt @@ -23,6 +23,9 @@ class AdbService : Service() { private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private var relayServer: AdbRelayServer? = null + private var currentIp: String = "Unknown" + private var currentPort: Int = 5555 + private var currentRelayEnabled: Boolean = false companion object { private const val CHANNEL_ID = "adb_service_channel" @@ -30,6 +33,7 @@ class AdbService : Service() { const val ACTION_PENDING_AUTH = "com.phenix.wirelessadb.PENDING_AUTH" const val ACTION_APPROVE_DEVICE = "com.phenix.wirelessadb.APPROVE_DEVICE" const val ACTION_DENY_DEVICE = "com.phenix.wirelessadb.DENY_DEVICE" + const val ACTION_NETWORK_CHANGED = "com.phenix.wirelessadb.NETWORK_CHANGED" const val EXTRA_CLIENT_IP = "client_ip" fun start(context: Context, ip: String, port: Int, relayEnabled: Boolean = false) { @@ -64,6 +68,13 @@ class AdbService : Service() { } context.startService(intent) } + + fun onNetworkChanged(context: Context) { + val intent = Intent(context, AdbService::class.java).apply { + action = ACTION_NETWORK_CHANGED + } + context.startService(intent) + } } override fun onCreate() { @@ -87,12 +98,21 @@ class AdbService : Service() { } return START_STICKY } + ACTION_NETWORK_CHANGED -> { + handleNetworkChange() + return START_STICKY + } } val ip = intent?.getStringExtra("ip") ?: "Unknown" val port = intent?.getIntExtra("port", 5555) ?: 5555 val relayEnabled = intent?.getBooleanExtra("relay_enabled", false) ?: false + // Update current state + currentIp = ip + currentPort = port + currentRelayEnabled = relayEnabled + val tailscaleIp = TailscaleHelper.getTailscaleIp() startForeground(NOTIFICATION_ID, createNotification(ip, port, tailscaleIp, relayEnabled)) @@ -137,6 +157,23 @@ class AdbService : Service() { LocalBroadcastManager.getInstance(this).sendBroadcast(intent) } + private fun handleNetworkChange() { + serviceScope.launch { + val status = AdbManager.getStatus(this@AdbService) + if (status.enabled && status.ip != null) { + currentIp = status.ip + updateNotification() + } + } + } + + private fun updateNotification() { + val tailscaleIp = TailscaleHelper.getTailscaleIp() + val notification = createNotification(currentIp, currentPort, tailscaleIp, currentRelayEnabled) + val notificationManager = getSystemService(NotificationManager::class.java) + notificationManager.notify(NOTIFICATION_ID, notification) + } + private fun updateNotificationWithActiveConnection() { // Could update notification to show active connections } diff --git a/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt index 5f0d7d6..06515fb 100644 --- a/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt +++ b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt @@ -75,6 +75,9 @@ class NetworkChangeReceiver : BroadcastReceiver() { if (status.enabled) { Log.d(TAG, "handleNetworkChange: Re-enabling ADB on port $port") AdbManager.enable(port) + + // Notify service to update notification with new IP + AdbService.onNetworkChanged(context) } else { Log.d(TAG, "handleNetworkChange: ADB was not previously enabled, skipping auto-reconnect") } From b0a0543510be331469a9f5bd1c76ba2e310f4fcc Mon Sep 17 00:00:00 2001 From: Phenix Date: Sat, 7 Feb 2026 05:15:25 +0800 Subject: [PATCH 6/7] auto-claude: subtask-3-1 - Add trusted networks storage to PrefsManager --- .auto-claude-status | 10 +++---- .../com/phenix/wirelessadb/PrefsManager.kt | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/.auto-claude-status b/.auto-claude-status index 198c77d..ba41619 100644 --- a/.auto-claude-status +++ b/.auto-claude-status @@ -3,23 +3,23 @@ "spec": "007-auto-reconnect-on-network-change", "state": "building", "subtasks": { - "completed": 4, + "completed": 5, "total": 8, "in_progress": 1, "failed": 0 }, "phase": { - "current": "Auto-Reconnect Logic", + "current": "Trusted Networks (Optional)", "id": null, - "total": 3 + "total": 2 }, "workers": { "active": 0, "max": 1 }, "session": { - "number": 6, + "number": 7, "started_at": "2026-02-07T04:33:05.351503" }, - "last_update": "2026-02-07T05:01:51.882050" + "last_update": "2026-02-07T05:13:04.677678" } \ No newline at end of file diff --git a/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt b/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt index 67539e4..47a66f4 100644 --- a/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt +++ b/app/src/main/java/com/phenix/wirelessadb/PrefsManager.kt @@ -43,6 +43,9 @@ object PrefsManager { private const val DEFAULT_AUTO_RECONNECT_DELAY = 5000 // 5 seconds private const val DEFAULT_AUTO_RECONNECT_MAX_RETRIES = 3 + // Trusted networks settings + private const val KEY_TRUSTED_NETWORKS = "trusted_networks" + private fun getPrefs(context: Context): SharedPreferences { return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) } @@ -181,4 +184,29 @@ object PrefsManager { fun setAutoReconnectMaxRetries(context: Context, retries: Int) { getPrefs(context).edit().putInt(KEY_AUTO_RECONNECT_MAX_RETRIES, retries).apply() } + + // Trusted Networks + fun getTrustedNetworks(context: Context): Set { + return getPrefs(context).getStringSet(KEY_TRUSTED_NETWORKS, emptySet()) ?: emptySet() + } + + fun setTrustedNetworks(context: Context, networks: Set) { + getPrefs(context).edit().putStringSet(KEY_TRUSTED_NETWORKS, networks).apply() + } + + fun addTrustedNetwork(context: Context, ssid: String) { + val networks = getTrustedNetworks(context).toMutableSet() + networks.add(ssid) + setTrustedNetworks(context, networks) + } + + fun removeTrustedNetwork(context: Context, ssid: String) { + val networks = getTrustedNetworks(context).toMutableSet() + networks.remove(ssid) + setTrustedNetworks(context, networks) + } + + fun isTrustedNetwork(context: Context, ssid: String): Boolean { + return getTrustedNetworks(context).contains(ssid) + } } From 4431f3611b07f18be69dd7c6de9252676d6797f1 Mon Sep 17 00:00:00 2001 From: Phenix Date: Sat, 7 Feb 2026 05:21:06 +0800 Subject: [PATCH 7/7] auto-claude: subtask-3-2 - Update NetworkChangeReceiver to check trusted networks - Add WifiManager import for SSID detection - Implement getCurrentWifiSsid() to get current WiFi SSID - Check trusted networks before auto-reconnect - Skip auto-reconnect if network is not trusted - Allow all networks if trusted list is empty - Proper error handling and logging throughout Co-Authored-By: Claude Sonnet 4.5 --- .../wirelessadb/NetworkChangeReceiver.kt | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt index 06515fb..61fa86d 100644 --- a/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt +++ b/app/src/main/java/com/phenix/wirelessadb/NetworkChangeReceiver.kt @@ -7,6 +7,7 @@ import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest +import android.net.wifi.WifiManager import android.util.Log import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -64,6 +65,27 @@ class NetworkChangeReceiver : BroadcastReceiver() { return } + // Check trusted networks if configured + val trustedNetworks = PrefsManager.getTrustedNetworks(context) + if (trustedNetworks.isNotEmpty()) { + val currentSsid = getCurrentWifiSsid(context) + Log.d(TAG, "handleNetworkChange: Current SSID=$currentSsid, trusted networks=$trustedNetworks") + + if (currentSsid == null) { + Log.d(TAG, "handleNetworkChange: Cannot determine current SSID, skipping auto-reconnect") + return + } + + if (!PrefsManager.isTrustedNetwork(context, currentSsid)) { + Log.d(TAG, "handleNetworkChange: Network '$currentSsid' is not trusted, skipping auto-reconnect") + return + } + + Log.d(TAG, "handleNetworkChange: Network '$currentSsid' is trusted, proceeding with auto-reconnect") + } else { + Log.d(TAG, "handleNetworkChange: No trusted networks configured, allowing all networks") + } + val port = PrefsManager.getPort(context) // Launch coroutine to check status and re-enable if needed @@ -85,6 +107,40 @@ class NetworkChangeReceiver : BroadcastReceiver() { } } + /** + * Get the current WiFi SSID, removing quotes that Android adds. + * Returns null if not connected to WiFi or SSID cannot be determined. + */ + private fun getCurrentWifiSsid(context: Context): String? { + return try { + val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as? WifiManager + if (wifiManager == null) { + Log.e(TAG, "getCurrentWifiSsid: WifiManager not available") + return null + } + + val connectionInfo = wifiManager.connectionInfo + if (connectionInfo == null) { + Log.d(TAG, "getCurrentWifiSsid: No connection info") + return null + } + + val ssid = connectionInfo.ssid + if (ssid == null || ssid == "" || ssid.isEmpty()) { + Log.d(TAG, "getCurrentWifiSsid: SSID unknown or empty") + return null + } + + // Remove quotes that Android adds around SSID + val cleanSsid = ssid.trim('"') + Log.d(TAG, "getCurrentWifiSsid: raw='$ssid', clean='$cleanSsid'") + cleanSsid + } catch (e: Exception) { + Log.e(TAG, "getCurrentWifiSsid: ERROR ${e.message}") + null + } + } + companion object { private const val TAG = "NetworkChangeReceiver"