diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 46452f8b..2bb62205 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -114,7 +114,7 @@ jobs: timeout-minutes: 30 strategy: matrix: - api-level: [26, 33] + api-level: [26, 34] steps: - uses: actions/checkout@v4 diff --git a/app/build.gradle b/app/build.gradle index a9fd187b..e894cc5d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,7 +37,7 @@ android { defaultConfig { applicationId "com.geeksville.mesh" minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works) - targetSdk 33 + targetSdk 34 versionCode 30315 // format is Mmmss (where M is 1+the numeric major number versionName "2.3.15" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0c56ed2b..6aa088e6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -47,6 +47,7 @@ + @@ -101,11 +102,13 @@ android:value="false" /> + = callbackF } } val filter = IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED) - context.registerReceiver(receiver, filter) + context.registerReceiverCompat(receiver, filter) createBond() awaitClose { context.unregisterReceiver(receiver) } diff --git a/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt b/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt index 0a18df10..ec4781ed 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothRepository.kt @@ -14,6 +14,7 @@ import androidx.lifecycle.coroutineScope import com.geeksville.mesh.android.Logging import com.geeksville.mesh.CoroutineDispatchers import com.geeksville.mesh.android.hasBluetoothPermission +import com.geeksville.mesh.util.registerReceiverCompat import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -46,7 +47,7 @@ class BluetoothRepository @Inject constructor( processLifecycle.coroutineScope.launch(dispatchers.default) { updateBluetoothState() bluetoothBroadcastReceiverLazy.get().let { receiver -> - application.registerReceiver(receiver, receiver.intentFilter) + application.registerReceiverCompat(receiver, receiver.intentFilter) } } } diff --git a/app/src/main/java/com/geeksville/mesh/repository/usb/UsbManager.kt b/app/src/main/java/com/geeksville/mesh/repository/usb/UsbManager.kt index 8bdf50b4..35008225 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/usb/UsbManager.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/usb/UsbManager.kt @@ -8,6 +8,7 @@ import android.content.IntentFilter import android.hardware.usb.UsbDevice import android.hardware.usb.UsbManager import com.geeksville.mesh.util.PendingIntentCompat +import com.geeksville.mesh.util.registerReceiverCompat import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow @@ -32,7 +33,7 @@ internal fun UsbManager.requestPermission( PendingIntentCompat.FLAG_MUTABLE ) val filter = IntentFilter(ACTION_USB_PERMISSION) - context.registerReceiver(receiver, filter) + context.registerReceiverCompat(receiver, filter) requestPermission(device, permissionIntent) awaitClose { context.unregisterReceiver(receiver) } diff --git a/app/src/main/java/com/geeksville/mesh/repository/usb/UsbRepository.kt b/app/src/main/java/com/geeksville/mesh/repository/usb/UsbRepository.kt index d9301cd4..9040b6f4 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/usb/UsbRepository.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/usb/UsbRepository.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.coroutineScope import com.geeksville.mesh.android.Logging import com.geeksville.mesh.CoroutineDispatchers +import com.geeksville.mesh.util.registerReceiverCompat import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialProber import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -62,7 +63,7 @@ class UsbRepository @Inject constructor( processLifecycle.coroutineScope.launch(dispatchers.default) { refreshStateInternal() usbBroadcastReceiverLazy.get().let { receiver -> - application.registerReceiver(receiver, receiver.intentFilter) + application.registerReceiverCompat(receiver, receiver.intentFilter) } } } diff --git a/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt b/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt index c0584849..4ab39e67 100644 --- a/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt +++ b/app/src/main/java/com/geeksville/mesh/util/CompatExtensions.kt @@ -5,11 +5,15 @@ import android.bluetooth.BluetoothDevice import android.bluetooth.le.ScanResult import android.companion.AssociationInfo import android.companion.CompanionDeviceManager +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent +import android.content.IntentFilter import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.os.Parcel import android.os.Parcelable +import androidx.core.content.ContextCompat import androidx.core.content.IntentCompat import androidx.core.os.ParcelCompat @@ -40,6 +44,14 @@ fun PackageManager.getPackageInfoCompat(packageName: String, flags: Int = 0): Pa @Suppress("DEPRECATION") getPackageInfo(packageName, flags) } +fun Context.registerReceiverCompat( + receiver: BroadcastReceiver, + filter: IntentFilter, + flag: Int = ContextCompat.RECEIVER_NOT_EXPORTED, +) { + ContextCompat.registerReceiver(this, receiver, filter, flag) +} + fun Intent.getAssociationResult(): String? = when { android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU -> getParcelableExtraCompat(CompanionDeviceManager.EXTRA_ASSOCIATION)