chore: update compileSdk and targetSdk to API 33

pull/699/head
andrekir 2023-08-27 06:38:36 -03:00 zatwierdzone przez Andre K
rodzic ef11af6e0b
commit 15ed09680f
7 zmienionych plików z 131 dodań i 34 usunięć

Wyświetl plik

@ -21,6 +21,8 @@ if (keystorePropertiesFile.exists()) {
}
android {
namespace 'com.geeksville.mesh'
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
@ -29,11 +31,11 @@ android {
storePassword keystoreProperties['storePassword']
}
}
compileSdkVersion 33
compileSdk 33
defaultConfig {
applicationId "com.geeksville.mesh"
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
targetSdkVersion 31
targetSdk 33
versionCode 30202 // format is Mmmss (where M is 1+the numeric major number
versionName "2.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -41,7 +43,7 @@ android {
// per https://developer.android.com/studio/write/vector-asset-studio
vectorDrawables.useSupportLibrary = true
}
flavorDimensions 'default'
flavorDimensions = ['default']
productFlavors {
fdroid {
dimension = 'default'
@ -98,7 +100,6 @@ android {
lint {
abortOnError false
}
namespace 'com.geeksville.mesh'
}
// per protobuf-gradle-plugin docs, this is recommended for android

Wyświetl plik

@ -23,6 +23,9 @@
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s" />
<!-- API 33+ Notification runtime permissions -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Permissions required for providing location (from phone GPS) to mesh -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
@ -57,6 +60,10 @@
<!-- zxing library for QR Code scanning using camera -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" />

Wyświetl plik

@ -117,16 +117,28 @@ class MainActivity : AppCompatActivity(), Logging {
private val bluetoothViewModel: BluetoothViewModel by viewModels()
private val model: UIViewModel by viewModels()
private val requestPermissionsLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (!permissions.entries.all { it.value }) {
errormsg("User denied permissions")
private val bluetoothPermissionsLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
if (result.entries.all { it.value }) {
info("Bluetooth permissions granted")
} else {
warn("Bluetooth permissions denied")
showSnackbar(permissionMissing)
}
requestedEnable = false
bluetoothViewModel.permissionsUpdated()
}
private val notificationPermissionsLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
if (result.entries.all { it.value }) {
info("Notification permissions granted")
} else {
warn("Notification permissions denied")
showSnackbar(getString(R.string.notification_denied))
}
}
data class TabInfo(val text: String, val icon: Int, val content: Fragment)
private val tabInfos = arrayOf(
@ -385,6 +397,17 @@ class MainActivity : AppCompatActivity(), Logging {
if (model.provideLocation.value == true)
service.startProvideLocation()
}
if (!hasNotificationPermission()) {
val notificationPermissions = getNotificationPermissions()
rationaleDialog(
shouldShowRequestPermissionRationale(notificationPermissions),
R.string.notification_required,
getString(R.string.why_notification_required),
) {
notificationPermissionsLauncher.launch(notificationPermissions)
}
}
} else {
// For other connection states, just slam them in
model.setConnectionState(newConnection)
@ -640,17 +663,10 @@ class MainActivity : AppCompatActivity(), Logging {
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
bleRequestEnable.launch(enableBtIntent)
} else {
MaterialAlertDialogBuilder(this)
.setTitle(getString(R.string.required_permissions))
.setMessage(permissionMissing)
.setNeutralButton(R.string.cancel) { _, _ ->
warn("User bailed due to permissions")
}
.setPositiveButton(R.string.accept) { _, _ ->
info("requesting permissions")
requestPermissionsLauncher.launch(getBluetoothPermissions())
}
.show()
val bluetoothPermissions = getBluetoothPermissions()
rationaleDialog(shouldShowRequestPermissionRationale(bluetoothPermissions)) {
bluetoothPermissionsLauncher.launch(bluetoothPermissions)
}
}
}
}

Wyświetl plik

@ -2,15 +2,19 @@ package com.geeksville.mesh.android
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.NotificationManager
import android.bluetooth.BluetoothManager
import android.location.LocationManager
import android.companion.CompanionDeviceManager
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.usb.UsbManager
import android.location.LocationManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.geeksville.mesh.R
import com.google.android.material.dialog.MaterialAlertDialogBuilder
/**
* @return null on platforms without a BlueTooth driver (i.e. the emulator)
@ -48,7 +52,7 @@ fun Context.gpsDisabled(): Boolean =
if (hasGps()) !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) else false
/**
* return the text string of the permissions missing
* @return the text string of the permissions missing
*/
val Context.permissionMissing: String
get() = if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S) {
@ -57,6 +61,55 @@ val Context.permissionMissing: String
getString(R.string.permission_missing_31)
}
/**
* Checks if any given permissions need to show rationale.
*
* @return true if should show UI with rationale before requesting a permission.
*/
fun Activity.shouldShowRequestPermissionRationale(permissions: Array<String>): Boolean {
for (permission in permissions) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
return true
}
}
return false
}
/**
* Checks if any given permissions need to show rationale.
*
* @return true if should show UI with rationale before requesting a permission.
*/
fun Fragment.shouldShowRequestPermissionRationale(permissions: Array<String>): Boolean {
for (permission in permissions) {
if (shouldShowRequestPermissionRationale(permission)) {
return true
}
}
return false
}
/**
* Handles whether a rationale dialog should be shown before performing an action.
*/
fun Context.rationaleDialog(
shouldShowRequestPermissionRationale: Boolean = true,
title: Int = R.string.required_permissions,
rationale: CharSequence = permissionMissing,
invokeFun: () -> Unit,
) {
if (!shouldShowRequestPermissionRationale) invokeFun()
else MaterialAlertDialogBuilder(this)
.setTitle(title)
.setMessage(rationale)
.setNeutralButton(R.string.cancel) { _, _ ->
}
.setPositiveButton(R.string.accept) { _, _ ->
invokeFun()
}
.show()
}
/**
* return a list of the permissions we don't have
*/
@ -123,3 +176,17 @@ fun Context.getBackgroundPermissions(): Array<String> {
/** @return true if the user already has background location permission */
fun Context.hasBackgroundPermission() = getBackgroundPermissions().isEmpty()
/**
* Notification permission (or empty if we already have what we need)
*/
fun Context.getNotificationPermissions(): Array<String> {
val perms = mutableListOf<String>()
if (android.os.Build.VERSION.SDK_INT >= 33)
perms.add(Manifest.permission.POST_NOTIFICATIONS)
return getMissingPermissions(perms)
}
/** @return true if the user already has notification permission */
fun Context.hasNotificationPermission() = getNotificationPermissions().isEmpty()

Wyświetl plik

@ -662,11 +662,12 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
val requestPermissionAndScanLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
if (permissions.entries.all { it.value }) {
info("Bluetooth permissions granted")
checkBTEnabled()
if (!hasCompanionDeviceApi) checkLocationEnabled()
scanLeDevice()
} else {
errormsg("User denied scan permissions")
warn("Bluetooth permissions denied")
model.showSnackbar(requireContext().permissionMissing)
}
bluetoothViewModel.permissionsUpdated()
@ -675,21 +676,16 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
binding.changeRadioButton.setOnClickListener {
debug("User clicked changeRadioButton")
scanLeDevice()
if (requireContext().hasBluetoothPermission()) {
val bluetoothPermissions = requireContext().getBluetoothPermissions()
if (bluetoothPermissions.isEmpty()) {
checkBTEnabled()
if (!hasCompanionDeviceApi) checkLocationEnabled()
} else {
MaterialAlertDialogBuilder(requireContext())
.setTitle(getString(R.string.required_permissions))
.setMessage(requireContext().permissionMissing)
.setNeutralButton(R.string.cancel) { _, _ ->
warn("User bailed due to permissions")
}
.setPositiveButton(R.string.accept) { _, _ ->
info("requesting scan permissions")
requestPermissionAndScanLauncher.launch(requireContext().getBluetoothPermissions())
}
.show()
requireContext().rationaleDialog(
shouldShowRequestPermissionRationale(bluetoothPermissions)
) {
requestPermissionAndScanLauncher.launch(bluetoothPermissions)
}
}
}
}

Wyświetl plik

@ -106,6 +106,9 @@
<string name="provide_location_to_mesh">Provide phone location to mesh</string>
<string name="camera_required">Camera permission</string>
<string name="why_camera_required">We must be granted access to the camera to read QR codes. No pictures or videos will be saved.</string>
<string name="notification_required">Notification permission</string>
<string name="why_notification_required">Meshtastic needs permission for service and message notifications.</string>
<string name="notification_denied">Notification permission denied. To turn on notifications, access: Android Settings > Apps > Meshtastic > Notifications.</string>
<string name="modem_config_slow_short">Short Range / Slow</string>
<string name="modem_config_slow_medium">Medium Range / Slow</string>
<plurals name="delete_messages">

Wyświetl plik

@ -4,20 +4,27 @@
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Ensure important default jvmargs aren't overwritten. See https://github.com/gradle/gradle/issues/19750
org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Disable build features that are enabled by default,
# https://developer.android.com/build/releases/gradle-plugin#default-changes
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false