From 355770c1d22fff957591474f32f3aeb69f5a76f0 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Wed, 21 Dec 2022 17:15:18 +0100 Subject: [PATCH 1/9] Add gh workflow for testing release builds against AGP matrix --- .github/workflows/agp-matrix.yml | 36 ++++++++++++++++++++++++++++++++ buildSrc/src/main/java/Config.kt | 3 ++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/agp-matrix.yml diff --git a/.github/workflows/agp-matrix.yml b/.github/workflows/agp-matrix.yml new file mode 100644 index 00000000000..2f2fdf0e5da --- /dev/null +++ b/.github/workflows/agp-matrix.yml @@ -0,0 +1,36 @@ +name: AGP Matrix Sample Release + +on: + push: + branches: + - main + - release/** + pull_request: + +jobs: + agp-matrix-sample-release: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + agp: ['7.3.0','7.4.0-rc01','8.0.0-alpha09'] + + name: AGP Matrix Sample Release - AGP ${{ matrix.agp }} + env: + VERSION_AGP: ${{ matrix.agp }} + + steps: + - name: Checkout Repo + uses: actions/checkout@v2 + + - name: Setup Java Version + uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: '17' + + - name: Build the Release variant + uses: gradle/gradle-build-action@v2 + with: + cache-read-only: ${{ github.ref != 'refs/heads/main' }} + arguments: sentry-samples:sentry-samples-android:assembleRelease diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index a0a269115b0..4001ac01012 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -1,6 +1,7 @@ import java.math.BigDecimal object Config { + val AGP = System.getenv("VERSION_AGP") ?: "7.3.0" val kotlinVersion = "1.6.10" val kotlinStdLib = "stdlib-jdk8" @@ -11,7 +12,7 @@ object Config { val composeVersion = "1.1.1" object BuildPlugins { - val androidGradle = "com.android.tools.build:gradle:7.3.0" + val androidGradle = "com.android.tools.build:gradle:$AGP" val kotlinGradlePlugin = "gradle-plugin" val buildConfig = "com.github.gmazzo.buildconfig" val buildConfigVersion = "3.0.3" From 05322a677aa17e3c27c0c01318e981773c53ff75 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Wed, 21 Dec 2022 20:56:46 +0100 Subject: [PATCH 2/9] Pin build-action version and add a flag for AGP 8+ --- .github/workflows/agp-matrix.yml | 2 +- gradle.properties | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/agp-matrix.yml b/.github/workflows/agp-matrix.yml index 2f2fdf0e5da..6683eb7521f 100644 --- a/.github/workflows/agp-matrix.yml +++ b/.github/workflows/agp-matrix.yml @@ -30,7 +30,7 @@ jobs: java-version: '17' - name: Build the Release variant - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef # pin@v2 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} arguments: sentry-samples:sentry-samples-android:assembleRelease diff --git a/gradle.properties b/gradle.properties index c2c4e223169..00a59c30bc8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,6 +6,9 @@ org.gradle.parallel=true # AndroidX required by AGP >= 3.6.x android.useAndroidX=true +# Required by AGP >= 8.0.x +android.defaults.buildfeatures.buildconfig=true + # Release information versionName=6.10.0 From 6123ae0c8364aafd69aca31b52ef6782a6c5ba55 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Thu, 22 Dec 2022 11:57:00 +0100 Subject: [PATCH 3/9] Add test project for AGP compatibility matrix --- .github/workflows/agp-matrix.yml | 4 +- sentry-android-integration-tests/README.md | 1 + .../sentry-test-agp/.gitignore | 1 + .../sentry-test-agp/build.gradle.kts | 64 +++++++++++++++++++ .../sentry-test-agp/proguard-rules.pro | 21 ++++++ .../src/main/AndroidManifest.xml | 6 ++ .../java/io/sentry/test/agp/MainActivity.java | 19 ++++++ settings.gradle.kts | 3 +- 8 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 sentry-android-integration-tests/sentry-test-agp/.gitignore create mode 100644 sentry-android-integration-tests/sentry-test-agp/build.gradle.kts create mode 100644 sentry-android-integration-tests/sentry-test-agp/proguard-rules.pro create mode 100644 sentry-android-integration-tests/sentry-test-agp/src/main/AndroidManifest.xml create mode 100644 sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java diff --git a/.github/workflows/agp-matrix.yml b/.github/workflows/agp-matrix.yml index 6683eb7521f..16a81e827d7 100644 --- a/.github/workflows/agp-matrix.yml +++ b/.github/workflows/agp-matrix.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - agp: ['7.3.0','7.4.0-rc01','8.0.0-alpha09'] + agp: ['7.3.0','7.4.0-rc01','8.0.0-alpha05'] name: AGP Matrix Sample Release - AGP ${{ matrix.agp }} env: @@ -33,4 +33,4 @@ jobs: uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef # pin@v2 with: cache-read-only: ${{ github.ref != 'refs/heads/main' }} - arguments: sentry-samples:sentry-samples-android:assembleRelease + arguments: sentry-android-integration-tests:sentry-test-agp:assembleRelease diff --git a/sentry-android-integration-tests/README.md b/sentry-android-integration-tests/README.md index 585fa5fa06e..26c4a327f48 100644 --- a/sentry-android-integration-tests/README.md +++ b/sentry-android-integration-tests/README.md @@ -5,3 +5,4 @@ * [App metrics test specification (yaml)](./metrics-test.yml) * [Espresso-based benchmarks](./sentry-uitest-android-benchmark) - run within SauceLabs (see /.sauce/*.yml) * [Espresso-based UI tests](./sentry-uitest-android) - run within SauceLabs (see /.sauce/*.yml) +* [Sample app for testing against AGP compatibility matrix](./sentry-test-agp) diff --git a/sentry-android-integration-tests/sentry-test-agp/.gitignore b/sentry-android-integration-tests/sentry-test-agp/.gitignore new file mode 100644 index 00000000000..42afabfd2ab --- /dev/null +++ b/sentry-android-integration-tests/sentry-test-agp/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts b/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts new file mode 100644 index 00000000000..be8d8f7f43d --- /dev/null +++ b/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts @@ -0,0 +1,64 @@ +plugins { + id("com.android.application") +} + +android { + compileSdk = Config.Android.compileSdkVersion + namespace = "io.sentry.test.agp" + + defaultConfig { + applicationId = "io.sentry.test.agp" + minSdk = Config.Android.minSdkVersionNdk + targetSdk = Config.Android.targetSdkVersion + versionCode = 1 + versionName = "1.0" + } + + buildTypes { + getByName("release") { + isMinifyEnabled = true + signingConfig = signingConfigs.getByName("debug") // to be able to run release mode + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "benchmark-proguard-rules.pro" + ) + ndk { + abiFilters.clear() + abiFilters.add("arm64-v8a") + } + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding = true + } + signingConfigs { + getByName("debug") { + storeFile = rootProject.file("debug.keystore") + storePassword = "android" + keyAlias = "androiddebugkey" + keyPassword = "android" + } + } + + variantFilter { + if (Config.Android.shouldSkipDebugVariant(buildType.name)) { + ignore = true + } + } +} +dependencies { + // just a mix of different dependencies to test how our logic for checking classes at runtime + // works with r8 + implementation(projects.sentryAndroid) + implementation(projects.sentryAndroidOkhttp) + implementation(projects.sentryAndroidFragment) + implementation(projects.sentryAndroidTimber) + + implementation(Config.Libs.fragment) + + implementation(Config.Libs.retrofit2) +} diff --git a/sentry-android-integration-tests/sentry-test-agp/proguard-rules.pro b/sentry-android-integration-tests/sentry-test-agp/proguard-rules.pro new file mode 100644 index 00000000000..481bb434814 --- /dev/null +++ b/sentry-android-integration-tests/sentry-test-agp/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/sentry-android-integration-tests/sentry-test-agp/src/main/AndroidManifest.xml b/sentry-android-integration-tests/sentry-test-agp/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..5ee3c0aa470 --- /dev/null +++ b/sentry-android-integration-tests/sentry-test-agp/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java b/sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java new file mode 100644 index 00000000000..5065b5f0002 --- /dev/null +++ b/sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java @@ -0,0 +1,19 @@ +package io.sentry.test.agp; + +import android.app.Activity; +import android.os.Bundle; + +public class MainActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + helloWorld(); + } + + public void helloWorld() { + System.out.println("¯\\_(ツ)_/¯"); + } + +} + diff --git a/settings.gradle.kts b/settings.gradle.kts index 3d8af338089..bfbce6c7dac 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -58,7 +58,8 @@ include( "sentry-android-integration-tests:sentry-uitest-android-benchmark", "sentry-android-integration-tests:sentry-uitest-android", "sentry-android-integration-tests:test-app-plain", - "sentry-android-integration-tests:test-app-sentry" + "sentry-android-integration-tests:test-app-sentry", + "sentry-android-integration-tests:sentry-test-agp" ) gradle.beforeProject { From b0f4cb455400cc06640d88fc86d9fa7e457fce17 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Thu, 22 Dec 2022 11:01:22 +0000 Subject: [PATCH 4/9] Format code --- .../src/main/java/io/sentry/test/agp/MainActivity.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java b/sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java index 5065b5f0002..839683d942f 100644 --- a/sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java +++ b/sentry-android-integration-tests/sentry-test-agp/src/main/java/io/sentry/test/agp/MainActivity.java @@ -14,6 +14,4 @@ protected void onCreate(Bundle savedInstanceState) { public void helloWorld() { System.out.println("¯\\_(ツ)_/¯"); } - } - From dc25f499f3ab4fce302f0d814a639267a1584e70 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Thu, 22 Dec 2022 12:04:03 +0100 Subject: [PATCH 5/9] Bump minSdkVersion --- .github/workflows/agp-matrix.yml | 2 +- .../sentry-test-agp/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/agp-matrix.yml b/.github/workflows/agp-matrix.yml index 16a81e827d7..8fd9bff8ed6 100644 --- a/.github/workflows/agp-matrix.yml +++ b/.github/workflows/agp-matrix.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - agp: ['7.3.0','7.4.0-rc01','8.0.0-alpha05'] + agp: ['7.3.0','7.4.0-rc01','8.0.0-alpha09'] name: AGP Matrix Sample Release - AGP ${{ matrix.agp }} env: diff --git a/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts b/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts index be8d8f7f43d..189926e1527 100644 --- a/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts @@ -8,7 +8,7 @@ android { defaultConfig { applicationId = "io.sentry.test.agp" - minSdk = Config.Android.minSdkVersionNdk + minSdk = Config.Android.minSdkVersionOkHttp targetSdk = Config.Android.targetSdkVersion versionCode = 1 versionName = "1.0" From 99fd7454688e4a8647565f5f1ace769b2b991546 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Thu, 22 Dec 2022 12:17:38 +0100 Subject: [PATCH 6/9] Cancel previous runs --- .github/workflows/agp-matrix.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/agp-matrix.yml b/.github/workflows/agp-matrix.yml index 8fd9bff8ed6..f2c918422be 100644 --- a/.github/workflows/agp-matrix.yml +++ b/.github/workflows/agp-matrix.yml @@ -8,6 +8,14 @@ on: pull_request: jobs: + cancel-previous-workflow: + runs-on: ubuntu-latest + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # pin@0.11.0 + with: + access_token: ${{ github.token }} + agp-matrix-sample-release: runs-on: ubuntu-latest strategy: From 9c3ca09fe9d322a3ce8ca2f92779079a80817778 Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Sat, 24 Dec 2022 00:31:44 +0100 Subject: [PATCH 7/9] Check for compose classes via reflection instead of try-catch --- buildSrc/src/main/java/Config.kt | 1 + sentry-android-core/build.gradle.kts | 2 + .../core/AndroidOptionsInitializer.java | 21 +++++---- .../src/test/AndroidManifest.xml | 21 +++++++++ .../core/AndroidOptionsInitializerTest.kt | 45 +++++++++++++++---- sentry-compose/proguard-rules.pro | 4 ++ 6 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 sentry-android-core/src/test/AndroidManifest.xml diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index 4001ac01012..47d80f0d931 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -131,6 +131,7 @@ object Config { val composeNavigation = "androidx.navigation:navigation-compose:$navigationVersion" val composeActivity = "androidx.activity:activity-compose:1.4.0" val composeFoundation = "androidx.compose.foundation:foundation:$composeVersion" + val composeUi = "androidx.compose.ui:ui:$composeVersion" val composeFoundationLayout = "androidx.compose.foundation:foundation-layout:$composeVersion" val composeMaterial = "androidx.compose.material3:material3:1.0.0-alpha13" diff --git a/sentry-android-core/build.gradle.kts b/sentry-android-core/build.gradle.kts index 9b8a2623acf..de6ce205965 100644 --- a/sentry-android-core/build.gradle.kts +++ b/sentry-android-core/build.gradle.kts @@ -108,6 +108,8 @@ dependencies { testImplementation(projects.sentryTestSupport) testImplementation(projects.sentryAndroidFragment) testImplementation(projects.sentryAndroidTimber) + testImplementation(projects.sentryComposeHelper) + testImplementation(projects.sentryAndroidNdk) testRuntimeOnly(Config.Libs.timber) testRuntimeOnly(Config.Libs.fragment) } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java index 620fbed05c4..d5f1ae85a92 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java @@ -41,6 +41,11 @@ @SuppressWarnings("Convert2MethodRef") // older AGP versions do not support method references final class AndroidOptionsInitializer { + static final String SENTRY_COMPOSE_INTEGRATION_CLASS_NAME = + "io.sentry.compose.gestures.ComposeGestureTargetLocator"; + + static final String COMPOSE_CLASS_NAME = "androidx.compose.ui.node.Owner"; + /** private ctor */ private AndroidOptionsInitializer() {} @@ -143,15 +148,15 @@ static void initializeIntegrationsAndProcessors( if (options.getGestureTargetLocators().isEmpty()) { final List gestureTargetLocators = new ArrayList<>(2); gestureTargetLocators.add(new AndroidViewGestureTargetLocator(isAndroidXScrollViewAvailable)); - try { + + final boolean isComposeUpstreamAvailable = + loadClass.isClassAvailable(COMPOSE_CLASS_NAME, options); + final boolean isComposeAvailable = + (isComposeUpstreamAvailable + && loadClass.isClassAvailable(SENTRY_COMPOSE_INTEGRATION_CLASS_NAME, options)); + + if (isComposeAvailable) { gestureTargetLocators.add(new ComposeGestureTargetLocator()); - } catch (NoClassDefFoundError error) { - options - .getLogger() - .log( - SentryLevel.DEBUG, - "ComposeGestureTargetLocator not available, consider adding the `sentry-compose` library.", - error); } options.setGestureTargetLocators(gestureTargetLocators); } diff --git a/sentry-android-core/src/test/AndroidManifest.xml b/sentry-android-core/src/test/AndroidManifest.xml new file mode 100644 index 00000000000..87fa579cf66 --- /dev/null +++ b/sentry-android-core/src/test/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt index cf61131fe37..5b8dadf0979 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt @@ -8,12 +8,15 @@ import io.sentry.ILogger import io.sentry.MainEventProcessor import io.sentry.SentryOptions import io.sentry.android.core.cache.AndroidEnvelopeCache +import io.sentry.android.core.internal.gestures.AndroidViewGestureTargetLocator import io.sentry.android.core.internal.modules.AssetsModulesLoader import io.sentry.android.core.internal.util.AndroidMainThreadChecker import io.sentry.android.fragment.FragmentLifecycleIntegration import io.sentry.android.timber.SentryTimberIntegration +import io.sentry.compose.gestures.ComposeGestureTargetLocator import org.junit.runner.RunWith import org.mockito.kotlin.any +import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.whenever import java.io.File @@ -66,7 +69,7 @@ class AndroidOptionsInitializerTest { fun initSutWithClassLoader( minApi: Int = 16, - classToLoad: Class<*>? = null, + classesToLoad: List = emptyList(), isFragmentAvailable: Boolean = false, isTimberAvailable: Boolean = false ) { @@ -89,7 +92,7 @@ class AndroidOptionsInitializerTest { sentryOptions, context, buildInfo, - createClassMock(classToLoad), + createClassMock(classesToLoad), isFragmentAvailable, isTimberAvailable ) @@ -101,10 +104,14 @@ class AndroidOptionsInitializerTest { return buildInfo } - private fun createClassMock(clazz: Class<*>?): LoadClass { + private fun createClassMock(classes: List): LoadClass { val loadClassMock = mock() - whenever(loadClassMock.loadClass(any(), any())).thenReturn(clazz) - whenever(loadClassMock.isClassAvailable(any(), any())).thenReturn(clazz != null) + classes.forEach { + whenever(loadClassMock.loadClass(eq(it), any())) + .thenReturn(Class.forName(it, false, this::class.java.classLoader)) + whenever(loadClassMock.isClassAvailable(eq(it), any())) + .thenReturn(true) + } return loadClassMock } } @@ -267,7 +274,7 @@ class AndroidOptionsInitializerTest { @Test fun `NdkIntegration will load SentryNdk class and add to the integration list`() { - fixture.initSutWithClassLoader(classToLoad = SentryNdk::class.java) + fixture.initSutWithClassLoader(classesToLoad = listOfNotNull(NdkIntegration.SENTRY_NDK_CLASS_NAME)) val actual = fixture.sentryOptions.integrations.firstOrNull { it is NdkIntegration } assertNotNull((actual as NdkIntegration).sentryNdkClass) @@ -275,7 +282,7 @@ class AndroidOptionsInitializerTest { @Test fun `NdkIntegration won't be enabled because API is lower than 16`() { - fixture.initSutWithClassLoader(minApi = 14, classToLoad = SentryNdk::class.java) + fixture.initSutWithClassLoader(minApi = 14, classesToLoad = listOfNotNull(NdkIntegration.SENTRY_NDK_CLASS_NAME)) val actual = fixture.sentryOptions.integrations.firstOrNull { it is NdkIntegration } assertNull((actual as NdkIntegration).sentryNdkClass) @@ -283,7 +290,7 @@ class AndroidOptionsInitializerTest { @Test fun `NdkIntegration won't be enabled, if class not found`() { - fixture.initSutWithClassLoader(classToLoad = null) + fixture.initSutWithClassLoader(classesToLoad = emptyList()) val actual = fixture.sentryOptions.integrations.firstOrNull { it is NdkIntegration } assertNull((actual as NdkIntegration).sentryNdkClass) @@ -455,4 +462,26 @@ class AndroidOptionsInitializerTest { assertTrue { fixture.sentryOptions.mainThreadChecker is AndroidMainThreadChecker } } + + @Test + fun `does not install ComposeGestureTargetLocator, if sentry-compose is not available`() { + fixture.initSutWithClassLoader() + + assertTrue { fixture.sentryOptions.gestureTargetLocators.size == 1 } + assertTrue { fixture.sentryOptions.gestureTargetLocators[0] is AndroidViewGestureTargetLocator } + } + + @Test + fun `installs ComposeGestureTargetLocator, if sentry-compose is available`() { + fixture.initSutWithClassLoader( + classesToLoad = listOf( + AndroidOptionsInitializer.COMPOSE_CLASS_NAME, + AndroidOptionsInitializer.SENTRY_COMPOSE_INTEGRATION_CLASS_NAME + ) + ) + + assertTrue { fixture.sentryOptions.gestureTargetLocators.size == 2 } + assertTrue { fixture.sentryOptions.gestureTargetLocators[0] is AndroidViewGestureTargetLocator } + assertTrue { fixture.sentryOptions.gestureTargetLocators[1] is ComposeGestureTargetLocator } + } } diff --git a/sentry-compose/proguard-rules.pro b/sentry-compose/proguard-rules.pro index 244282115a5..d2c978a746c 100644 --- a/sentry-compose/proguard-rules.pro +++ b/sentry-compose/proguard-rules.pro @@ -1,5 +1,9 @@ ##---------------Begin: proguard configuration for Compose ---------- +# The Android SDK checks at runtime if these classes are available via Class.forName +-keep class io.sentry.compose.gestures.ComposeGestureTargetLocator { (...); } +-keepnames interface androidx.compose.ui.node.Owner + # To ensure that stack traces is unambiguous # https://developer.android.com/studio/build/shrink-code#decode-stack-trace -keepattributes LineNumberTable,SourceFile From da650a5fa604acb14f3a48586f3e341a8dfe54f3 Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Fri, 23 Dec 2022 23:35:01 +0000 Subject: [PATCH 8/9] Format code --- .../io/sentry/android/core/AndroidOptionsInitializer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java index d5f1ae85a92..5b3e473743e 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java @@ -42,7 +42,7 @@ final class AndroidOptionsInitializer { static final String SENTRY_COMPOSE_INTEGRATION_CLASS_NAME = - "io.sentry.compose.gestures.ComposeGestureTargetLocator"; + "io.sentry.compose.gestures.ComposeGestureTargetLocator"; static final String COMPOSE_CLASS_NAME = "androidx.compose.ui.node.Owner"; @@ -150,10 +150,10 @@ static void initializeIntegrationsAndProcessors( gestureTargetLocators.add(new AndroidViewGestureTargetLocator(isAndroidXScrollViewAvailable)); final boolean isComposeUpstreamAvailable = - loadClass.isClassAvailable(COMPOSE_CLASS_NAME, options); + loadClass.isClassAvailable(COMPOSE_CLASS_NAME, options); final boolean isComposeAvailable = - (isComposeUpstreamAvailable - && loadClass.isClassAvailable(SENTRY_COMPOSE_INTEGRATION_CLASS_NAME, options)); + (isComposeUpstreamAvailable + && loadClass.isClassAvailable(SENTRY_COMPOSE_INTEGRATION_CLASS_NAME, options)); if (isComposeAvailable) { gestureTargetLocators.add(new ComposeGestureTargetLocator()); From c91ac0efd0b005d43a666a85a841248b3eea19dc Mon Sep 17 00:00:00 2001 From: Roman Zavarnitsyn Date: Sat, 24 Dec 2022 11:18:04 +0100 Subject: [PATCH 9/9] Dontwarn about missing compose class as we check for it at runtime --- CHANGELOG.md | 1 + sentry-android-core/proguard-rules.pro | 4 ++-- .../sentry-test-agp/build.gradle.kts | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 950ea4671e1..7c6989b3707 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixes - Use minSdk compatible `Objects` class ([#2436](https://github.com/getsentry/sentry-java/pull/2436)) +- Prevent R8 from warning on missing classes, as we check for their presence at runtime ([#2439](https://github.com/getsentry/sentry-java/pull/2439)) ### Features diff --git a/sentry-android-core/proguard-rules.pro b/sentry-android-core/proguard-rules.pro index 5b1934a8e38..b9d371c29fd 100644 --- a/sentry-android-core/proguard-rules.pro +++ b/sentry-android-core/proguard-rules.pro @@ -20,10 +20,10 @@ # don't warn jetbrains annotations -dontwarn org.jetbrains.annotations.** -# don't warn about missing classes (mainly for Guardsquare's proguard). -# We are checking for their presence at runtime +# don't warn about missing classes, as we are checking for their presence at runtime -dontwarn io.sentry.android.timber.SentryTimberIntegration -dontwarn io.sentry.android.fragment.FragmentLifecycleIntegration +-dontwarn io.sentry.compose.gestures.ComposeGestureTargetLocator # To ensure that stack traces is unambiguous # https://developer.android.com/studio/build/shrink-code#decode-stack-trace diff --git a/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts b/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts index 189926e1527..7f6e8d79f18 100644 --- a/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts +++ b/sentry-android-integration-tests/sentry-test-agp/build.gradle.kts @@ -19,8 +19,7 @@ android { isMinifyEnabled = true signingConfig = signingConfigs.getByName("debug") // to be able to run release mode proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "benchmark-proguard-rules.pro" + getDefaultProguardFile("proguard-android-optimize.txt") ) ndk { abiFilters.clear() @@ -59,6 +58,7 @@ dependencies { implementation(projects.sentryAndroidTimber) implementation(Config.Libs.fragment) + implementation(Config.Libs.timber) implementation(Config.Libs.retrofit2) }