From 475d4d91627ac32f8d2172c569d01865c6485d26 Mon Sep 17 00:00:00 2001 From: eddy Date: Sun, 26 Jul 2026 12:52:01 +0200 Subject: [PATCH] Fix SettingsActivity: use UsbUtils, add lifecycle guard --- .../com/eddy/atomrelay/SettingsActivity.kt | 463 +++++++++++++++--- 1 file changed, 398 insertions(+), 65 deletions(-) diff --git a/android/app/src/main/java/com/eddy/atomrelay/SettingsActivity.kt b/android/app/src/main/java/com/eddy/atomrelay/SettingsActivity.kt index 99cd006..4b1e74b 100644 --- a/android/app/src/main/java/com/eddy/atomrelay/SettingsActivity.kt +++ b/android/app/src/main/java/com/eddy/atomrelay/SettingsActivity.kt @@ -1,15 +1,26 @@ package com.eddy.atomrelay +import android.app.PendingIntent +import android.app.ProgressDialog +import android.content.BroadcastReceiver import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.hardware.usb.UsbConstants +import android.hardware.usb.UsbDevice +import android.hardware.usb.UsbDeviceConnection +import android.hardware.usb.UsbEndpoint +import android.hardware.usb.UsbInterface +import android.hardware.usb.UsbManager import android.os.Bundle -import android.text.InputType -import android.text.TextWatcher -import android.text.Editable +import android.os.Handler +import android.os.Looper +import android.util.Log import android.widget.Button -import android.widget.EditText -import android.widget.ImageButton -import android.widget.TextView +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity +import java.nio.charset.StandardCharsets +import java.security.SecureRandom class SettingsActivity : AppCompatActivity() { @@ -17,9 +28,65 @@ class SettingsActivity : AppCompatActivity() { const val PREFS_NAME = "relay_prefs" const val PREF_KEY = "hmac_key" const val RESULT_SCAN = 100 + private const val TAG = "SettingsActivity" + private const val ESP_VENDOR_ID = 0x303a + private const val CDC_DATA_INTERFACE_CLASS = 0x0A + private const val KEY_TIMEOUT_MS = 5000L + private const val SET_KEY_TIMEOUT_MS = 5000L + private const val ACTION_USB_PERMISSION = "com.eddy.atomrelay.USB_PERMISSION" } - private var isVisible = false + private enum class UsbAction { NONE, EXCHANGE_KEY, FLASH } + + private var currentAction = UsbAction.NONE + private var dialog: ProgressDialog? = null + private val handler = Handler(Looper.getMainLooper()) + + private val usbAttachedReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (intent.action == UsbManager.ACTION_USB_DEVICE_ATTACHED && currentAction != UsbAction.NONE) { + val device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) + if (device?.vendorId == ESP_VENDOR_ID) { + val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager + if (usbManager.hasPermission(device)) { + onDeviceReady(usbManager, device) + } else { + requestUsbPermission(usbManager, device) + } + } + } + } + } + + private val usbPermissionReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (intent.action == ACTION_USB_PERMISSION && currentAction != UsbAction.NONE) { + val granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) + if (granted) { + val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager + val device = usbManager.deviceList.values.firstOrNull { it.vendorId == ESP_VENDOR_ID } + if (device != null) { + onDeviceReady(usbManager, device) + } + } else { + Toast.makeText(this@SettingsActivity, "USB-toegang geweigerd", Toast.LENGTH_SHORT).show() + cleanupAction() + } + } + } + } + + private val usbDetachedReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + if (intent.action == UsbManager.ACTION_USB_DEVICE_DETACHED) { + val device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) + if (device?.vendorId == ESP_VENDOR_ID && dialog != null && currentAction == UsbAction.NONE) { + dialog?.dismiss() + dialog = null + } + } + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -28,71 +95,337 @@ class SettingsActivity : AppCompatActivity() { supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.title = "Instellingen" - val prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - val keyInput = findViewById(R.id.keyInput) - val toggleBtn = findViewById(R.id.toggleVisibility) - val saveButton = findViewById