diff --git a/app/build.gradle b/app/build.gradle index 4a6a01320..b74bfe28d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { applicationId "com.geeksville.mesh" minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works) targetSdkVersion 29 - versionCode 10793 // format is Mmmss (where M is 1+the numeric major number - versionName "0.7.93" + versionCode 10795 // format is Mmmss (where M is 1+the numeric major number + versionName "0.7.95" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -95,7 +95,7 @@ dependencies { implementation 'androidx.fragment:fragment-ktx:1.2.5' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta7' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta8' implementation 'com.google.android.material:material:1.1.0' implementation 'androidx.viewpager2:viewpager2:1.0.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7dd67e5fb..5422c73bc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,14 @@ xmlns:tools="http://schemas.android.com/tools" tools:ignore="GoogleAppIndexingWarning"> + + + + @@ -50,7 +58,7 @@ + android:required="false" /> ) { // This callback is invoked after we are connected diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt index c96cd66a3..e8d92f8ed 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -183,54 +183,59 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging { // if that device later disconnects remove it as a candidate override fun onScanResult(callbackType: Int, result: ScanResult) { - val addr = result.device.address - val fullAddr = "x$addr" // full address with the bluetooh prefix - // prevent logspam because weill get get lots of redundant scan results - val isBonded = result.device.bondState == BluetoothDevice.BOND_BONDED - val oldDevs = devices.value!! - val oldEntry = oldDevs[fullAddr] - if (oldEntry == null || oldEntry.bonded != isBonded) { // Don't spam the GUI with endless updates for non changing nodes + if ((result.device.name?.startsWith("Mesh") ?: false)) { + val addr = result.device.address + val fullAddr = "x$addr" // full address with the bluetooh prefix + // prevent logspam because weill get get lots of redundant scan results + val isBonded = result.device.bondState == BluetoothDevice.BOND_BONDED + val oldDevs = devices.value!! + val oldEntry = oldDevs[fullAddr] + if (oldEntry == null || oldEntry.bonded != isBonded) { // Don't spam the GUI with endless updates for non changing nodes - val skipBogus = try { - // Note Soyes XS has a buggy BLE scan implementation and returns devices we didn't ask for. So we check to see if the - // last two chars of the name matches the last two of the address - if not we skip it + val skipBogus = try { + // Note Soyes XS has a buggy BLE scan implementation and returns devices we didn't ask for. So we check to see if the + // last two chars of the name matches the last two of the address - if not we skip it - // Note: the address is always two more than the hex string we show in the name + // Note: the address is always two more than the hex string we show in the name - // nasty parsing of a string that ends with ab:45 as four hex digits - val lastAddr = (addr.substring( - addr.length - 5, - addr.length - 3 - ) + addr.substring(addr.length - 2)).toInt(16) + // nasty parsing of a string that ends with ab:45 as four hex digits + val lastAddr = (addr.substring( + addr.length - 5, + addr.length - 3 + ) + addr.substring(addr.length - 2)).toInt(16) - val lastName = - result.device.name.substring(result.device.name.length - 4).toInt(16) + val lastName = + result.device.name.substring(result.device.name.length - 4).toInt(16) - (lastAddr - 2) != lastName - } catch (ex: Throwable) { - false // If we fail parsing anything, don't do this nasty hack - } + // ESP32 macaddr are two higher than the reported device name + // NRF52 macaddrs match the portion used in the string + // either would be acceptable + (lastAddr - 2) != lastName && lastAddr != lastName + } catch (ex: Throwable) { + false // If we fail parsing anything, don't do this nasty hack + } - if (skipBogus) - errormsg("Skipping bogus BLE entry $result") - else { - val entry = DeviceListEntry( - result.device.name - ?: "unnamed-$addr", // autobug: some devices might not have a name, if someone is running really old device code? - fullAddr, - isBonded - ) - debug("onScanResult ${entry}") - - // If nothing was selected, by default select the first valid thing we see - val activity = - GeeksvilleApplication.currentActivity as MainActivity? // Can be null if app is shutting down - if (selectedAddress == null && entry.bonded && activity != null) - changeScanSelection( - activity, - fullAddr + if (skipBogus) + errormsg("Skipping bogus BLE entry $result") + else { + val entry = DeviceListEntry( + result.device.name + ?: "unnamed-$addr", // autobug: some devices might not have a name, if someone is running really old device code? + fullAddr, + isBonded ) - addDevice(entry) // Add/replace entry + debug("onScanResult ${entry}") + + // If nothing was selected, by default select the first valid thing we see + val activity = + GeeksvilleApplication.currentActivity as MainActivity? // Can be null if app is shutting down + if (selectedAddress == null && entry.bonded && activity != null) + changeScanSelection( + activity, + fullAddr + ) + addDevice(entry) // Add/replace entry + } } } } @@ -313,6 +318,8 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging { // filter and only accept devices that have our service val filter = ScanFilter.Builder() + // Note: NRF52 doesn't put the service in the avertizement, so we can't filter by service here + // Instead we check in the callback .setServiceUuid(ParcelUuid(BluetoothInterface.BTM_SERVICE_UUID)) .build() diff --git a/app/src/main/res/layout/messages_fragment.xml b/app/src/main/res/layout/messages_fragment.xml index c00e573ee..42e81fb78 100644 --- a/app/src/main/res/layout/messages_fragment.xml +++ b/app/src/main/res/layout/messages_fragment.xml @@ -12,7 +12,7 @@ android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" - android:contentDescription="Text messages" + android:contentDescription="@string/text_messages" app:layout_constraintBottom_toTopOf="@+id/textInputLayout" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/nodelist_fragment.xml b/app/src/main/res/layout/nodelist_fragment.xml index 113f23c12..3b2d3a883 100644 --- a/app/src/main/res/layout/nodelist_fragment.xml +++ b/app/src/main/res/layout/nodelist_fragment.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - android:contentDescription="A list of nodes in the mesh"> + android:contentDescription="@string/a_list_of_nodes_in_the_mesh"> Meshtastic Service Notifications You must turn on location services in Android Settings About + A list of nodes in the mesh + Text messages