[#479] Compile SDK 33

Since we have strict compiler warnings, the API deprecations in Android API 33 will fail our build. This change therefore:
 - Bumps the compile SDK
 - Adds helper extensions to use the new methods on Android 33+ and old methods for older Android versions.  Although the functionality is the same, the wrappers will make it easier to eliminate legacy API calls in the future
 - Disabled Gradle warning.  #508 is a followup to remove this flag later.
 - Refactor Update screen tests

Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
Carter Jernigan 2022-06-21 07:49:09 -04:00 committed by GitHub
parent c8872104e7
commit 77a1881930
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 121 additions and 116 deletions

View File

@ -3,6 +3,7 @@ package co.electriccoin.zcash.crash.android.internal
import android.content.Context
import android.os.Bundle
import co.electriccoin.zcash.crash.ReportableException
import co.electriccoin.zcash.spackle.getPackageInfoCompat
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
@ -12,7 +13,7 @@ fun ReportableException.Companion.new(
isUncaught: Boolean,
clock: Clock = Clock.System
): ReportableException {
val versionName = context.packageManager.getPackageInfo(context.packageName, 0).versionName
val versionName = context.packageManager.getPackageInfoCompat(context.packageName, 0L).versionName
?: "null"
return ReportableException(

View File

@ -8,9 +8,10 @@ org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m
kotlin.mpp.stability.nowarn=true
android.useAndroidX=true
android.nonTransitiveRClass=true
android.builder.sdkDownload=true
android.nonTransitiveRClass=true
android.suppressUnsupportedCompileSdk=33
android.useAndroidX=true
# Kotlin compiler warnings can be considered errors, failing the build.
ZCASH_IS_TREAT_WARNINGS_AS_ERRORS=true
@ -77,7 +78,7 @@ BIP_39_INCLUDED_BUILD_PATH=
ANDROID_LIB_MIN_SDK_VERSION=24
ANDROID_APP_MIN_SDK_VERSION=27
ANDROID_TARGET_SDK_VERSION=32
ANDROID_COMPILE_SDK_VERSION=32
ANDROID_COMPILE_SDK_VERSION=33
ANDROID_NDK_VERSION=23.0.7599858

View File

@ -0,0 +1,26 @@
package co.electriccoin.zcash.spackle.process
import android.content.pm.PackageInfo
import androidx.test.filters.SmallTest
import co.electriccoin.zcash.spackle.AndroidApiVersion
import co.electriccoin.zcash.spackle.versionCodeCompat
import org.junit.Assert.assertEquals
import org.junit.Test
class VersionCodeCompatTest {
@Test
@SmallTest
fun versionCodeCompat() {
val expectedVersionCode = 123L
val packageInfo = PackageInfo().apply {
@Suppress("Deprecation")
versionCode = expectedVersionCode.toInt()
if (AndroidApiVersion.isAtLeastT) {
longVersionCode = expectedVersionCode
}
}
assertEquals(expectedVersionCode, packageInfo.versionCodeCompat)
}
}

View File

@ -33,5 +33,8 @@ object AndroidApiVersion {
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S)
val isAtLeastS = isAtLeast(Build.VERSION_CODES.S)
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
val isAtLeastT = isAtLeast(Build.VERSION_CODES.TIRAMISU)
val isPreview = 0 != Build.VERSION.PREVIEW_SDK_INT
}

View File

@ -0,0 +1,30 @@
package co.electriccoin.zcash.spackle
import android.annotation.TargetApi
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
fun PackageManager.getPackageInfoCompat(packageName: String, flags: Long): PackageInfo =
if (AndroidApiVersion.isAtLeastT) {
getPackageInfoTPlus(packageName, flags)
} else {
getPackageInfoLegacy(packageName, flags)
}
suspend fun PackageManager.getPackageInfoCompatSuspend(packageName: String, flags: Long): PackageInfo =
if (AndroidApiVersion.isAtLeastT) {
withContext(Dispatchers.IO) { getPackageInfoTPlus(packageName, flags) }
} else {
withContext(Dispatchers.IO) { getPackageInfoLegacy(packageName, flags) }
}
@TargetApi(Build.VERSION_CODES.TIRAMISU)
private fun PackageManager.getPackageInfoTPlus(packageName: String, flags: Long) =
getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(flags))
@Suppress("Deprecation")
private fun PackageManager.getPackageInfoLegacy(packageName: String, flags: Long) =
getPackageInfo(packageName, flags.toInt())

View File

@ -0,0 +1,19 @@
package co.electriccoin.zcash.spackle
import android.annotation.TargetApi
import android.content.pm.PackageInfo
import android.os.Build
val PackageInfo.versionCodeCompat
get() = if (AndroidApiVersion.isAtLeastP) {
getVersionCodePPlus()
} else {
versionCodeLegacy.toLong()
}
@Suppress("Deprecation")
private val PackageInfo.versionCodeLegacy
get() = versionCode
@TargetApi(Build.VERSION_CODES.P)
private fun PackageInfo.getVersionCodePPlus() = longVersionCode

View File

@ -1,59 +0,0 @@
package co.electriccoin.zcash.ui.screen.update.integration
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.filters.MediumTest
import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.common.UiTestingActivity
import co.electriccoin.zcash.ui.screen.update.AppUpdateChecker
import co.electriccoin.zcash.ui.screen.update.UpdateTag
import co.electriccoin.zcash.ui.screen.update.fixture.UpdateInfoFixture
import co.electriccoin.zcash.ui.screen.update.model.UpdateInfo
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
import co.electriccoin.zcash.ui.screen.update.view.UpdateViewTestSetup
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
class UpdateActivityViewTest : UiTestPrerequisites() {
@get:Rule
val composeTestRule = createAndroidComposeRule<UiTestingActivity>()
@Test
@MediumTest
fun later_btn_force_update_test() {
val updateInfo = UpdateInfoFixture.new(
priority = AppUpdateChecker.Priority.HIGH,
force = true,
appUpdateInfo = null,
state = UpdateState.Prepared,
)
val testSetup = newTestSetup(updateInfo)
assertEquals(0, testSetup.getOnLaterCount())
composeTestRule.clickLater()
assertEquals(0, testSetup.getOnLaterCount())
composeTestRule.activity.onBackPressed()
assertEquals(0, testSetup.getOnLaterCount())
}
private fun newTestSetup(updateInfo: UpdateInfo) = UpdateViewTestSetup(
composeTestRule,
updateInfo
).apply {
setDefaultContent()
}
}
private fun ComposeContentTestRule.clickLater() {
onNodeWithTag(UpdateTag.BTN_LATER).also {
it.performClick()
}
}

View File

@ -3,12 +3,12 @@ package co.electriccoin.zcash.ui.screen.update.view
import android.app.Activity
import android.content.Context
import androidx.activity.ComponentActivity
import co.electriccoin.zcash.spackle.getPackageInfoCompat
import co.electriccoin.zcash.spackle.versionCodeCompat
import co.electriccoin.zcash.ui.screen.update.AppUpdateChecker
import co.electriccoin.zcash.ui.screen.update.fixture.UpdateInfoFixture
import co.electriccoin.zcash.ui.screen.update.model.UpdateInfo
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
import co.electriccoin.zcash.util.VersionCodeCompat
import co.electriccoin.zcash.util.myPackageInfo
import com.google.android.play.core.appupdate.AppUpdateInfo
import com.google.android.play.core.appupdate.testing.FakeAppUpdateManager
import com.google.android.play.core.install.model.AppUpdateType
@ -42,7 +42,7 @@ class AppUpdateCheckerMock private constructor() : AppUpdateChecker {
val fakeAppUpdateManager = FakeAppUpdateManager(context.applicationContext).also {
it.setClientVersionStalenessDays(stalenessDays)
it.setUpdateAvailable(
VersionCodeCompat.getVersionCode(context.myPackageInfo(0)).toInt(),
context.packageManager.getPackageInfoCompat(context.packageName, 0L).versionCodeCompat.toInt(),
AppUpdateType.IMMEDIATE
)
it.setUpdatePriority(resultUpdateInfo.priority.priorityUpperBorder())

View File

@ -6,6 +6,7 @@ import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.espresso.Espresso
import androidx.test.filters.MediumTest
import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.R
@ -91,6 +92,28 @@ class UpdateViewTest : UiTestPrerequisites() {
}
}
@Test
@MediumTest
fun later_btn_force_update_test() {
val updateInfo = UpdateInfoFixture.new(
priority = AppUpdateChecker.Priority.HIGH,
force = true,
appUpdateInfo = null,
state = UpdateState.Prepared,
)
val testSetup = newTestSetup(updateInfo)
assertEquals(0, testSetup.getOnLaterCount())
composeTestRule.clickLater()
assertEquals(0, testSetup.getOnLaterCount())
Espresso.pressBack()
assertEquals(0, testSetup.getOnLaterCount())
}
@Test
@MediumTest
fun download_btn_test() {

View File

@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.screen.about
import androidx.activity.ComponentActivity
import androidx.compose.runtime.Composable
import co.electriccoin.zcash.spackle.getPackageInfoCompat
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.screen.about.model.VersionInfo
import co.electriccoin.zcash.ui.screen.about.view.About
@ -18,7 +19,7 @@ internal fun WrapAbout(
activity: ComponentActivity,
goBack: () -> Unit
) {
val packageInfo = activity.packageManager.getPackageInfo(activity.packageName, 0)
val packageInfo = activity.packageManager.getPackageInfoCompat(activity.packageName, 0L)
About(VersionInfo.new(packageInfo), goBack)
}

View File

@ -1,13 +1,13 @@
package co.electriccoin.zcash.ui.screen.about.model
import android.content.pm.PackageInfo
import co.electriccoin.zcash.util.VersionCodeCompat
import co.electriccoin.zcash.spackle.versionCodeCompat
data class VersionInfo(val versionName: String, val versionCode: Long) {
companion object {
fun new(packageInfo: PackageInfo) = VersionInfo(
packageInfo.versionName ?: "null", // Should only be null during tests
VersionCodeCompat.getVersionCode(packageInfo)
packageInfo.versionCodeCompat
)
}
}

View File

@ -2,7 +2,7 @@ package co.electriccoin.zcash.ui.screen.support.model
import android.content.pm.PackageInfo
import co.electriccoin.zcash.build.gitSha
import co.electriccoin.zcash.util.VersionCodeCompat
import co.electriccoin.zcash.spackle.versionCodeCompat
class AppInfo(val versionName: String, val versionCode: Long, val gitSha: String) {
@ -13,7 +13,7 @@ class AppInfo(val versionName: String, val versionCode: Long, val gitSha: String
companion object {
fun new(packageInfo: PackageInfo) = AppInfo(
packageInfo.versionName ?: "null", // Should only be null during tests
VersionCodeCompat.getVersionCode(packageInfo),
packageInfo.versionCodeCompat,
gitSha
)
}

View File

@ -4,7 +4,7 @@ import android.Manifest
import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import co.electriccoin.zcash.util.myPackageInfo
import co.electriccoin.zcash.spackle.getPackageInfoCompatSuspend
class PermissionInfo(val permissionName: String, val permissionStatus: PermissionStatus) {
fun toSupportString() = buildString {
@ -15,7 +15,8 @@ class PermissionInfo(val permissionName: String, val permissionStatus: Permissio
private val permissionsOfInterest = listOf(Manifest.permission.CAMERA)
suspend fun all(context: Context): List<PermissionInfo> {
val myPackageInfo: PackageInfo = context.myPackageInfo(PackageManager.GET_PERMISSIONS)
val myPackageInfo: PackageInfo = context.packageManager
.getPackageInfoCompatSuspend(context.packageName, PackageManager.GET_PERMISSIONS.toLong())
return permissionsOfInterest.map { new(context, myPackageInfo, it) }
}

View File

@ -1,7 +1,7 @@
package co.electriccoin.zcash.ui.screen.support.model
import android.content.Context
import co.electriccoin.zcash.util.myPackageInfo
import co.electriccoin.zcash.spackle.getPackageInfoCompatSuspend
enum class SupportInfoType {
Time,
@ -61,7 +61,7 @@ data class SupportInfo(
// in the future.
suspend fun new(context: Context): SupportInfo {
val applicationContext = context.applicationContext
val packageInfo = applicationContext.myPackageInfo(0)
val packageInfo = applicationContext.packageManager.getPackageInfoCompatSuspend(context.packageName, 0L)
return SupportInfo(
TimeInfo.new(packageInfo),

View File

@ -1,19 +0,0 @@
package co.electriccoin.zcash.util
import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
/**
* @return Current app's package info.
*/
suspend fun Context.myPackageInfo(flags: Int): PackageInfo {
return try {
withContext(Dispatchers.IO) { packageManager.getPackageInfo(packageName, flags) }
} catch (e: PackageManager.NameNotFoundException) {
// The app's own package must exist, so this should never occur.
throw AssertionError(e)
}
}

View File

@ -1,22 +0,0 @@
package co.electriccoin.zcash.util
import android.annotation.TargetApi
import android.content.pm.PackageInfo
import android.os.Build
import co.electriccoin.zcash.spackle.AndroidApiVersion
object VersionCodeCompat {
fun getVersionCode(packageInfo: PackageInfo): Long {
return if (AndroidApiVersion.isAtLeastP) {
getVersionCodePPlus(packageInfo)
} else {
getVersionCodeLegacy(packageInfo).toLong()
}
}
@Suppress("Deprecation")
private fun getVersionCodeLegacy(packageInfo: PackageInfo) = packageInfo.versionCode
@TargetApi(Build.VERSION_CODES.P)
private fun getVersionCodePPlus(packageInfo: PackageInfo) = packageInfo.longVersionCode
}