Skip to content
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

# Unreleased

### Improvements

- Update Android targetSdk to API 36 (Android 16) ([#5016](https://github.com/getsentry/sentry-java/pull/5016))

## 8.31.0

### Features
Expand Down
12 changes: 6 additions & 6 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ springboot2 = "2.7.18"
springboot3 = "3.5.0"
springboot4 = "4.0.0"
# Android
targetSdk = "34"
compileSdk = "34"
targetSdk = "36"
compileSdk = "36"
minSdk = "21"
spotless = "7.0.4"
gummyBears = "0.12.0"
Expand Down Expand Up @@ -204,15 +204,15 @@ tomcat-catalina-jakarta = { module = "org.apache.tomcat:tomcat-catalina", versio
tomcat-embed-jasper-jakarta = { module = "org.apache.tomcat.embed:tomcat-embed-jasper", version = "11.0.10" }

# test libraries
androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version = "1.6.8" }
androidx-compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4", version = "1.10.1" }
androidx-test-core = { module = "androidx.test:core", version.ref = "androidxTestCore" }
androidx-test-core-ktx = { module = "androidx.test:core-ktx", version.ref = "androidxTestCore" }
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" }
androidx-test-espresso-idling-resource = { module = "androidx.test.espresso:espresso-idling-resource", version.ref = "espresso" }
androidx-test-ext-junit = { module = "androidx.test.ext:junit", version = "1.1.5" }
androidx-test-orchestrator = { module = "androidx.test:orchestrator", version = "1.5.0" }
androidx-test-ext-junit = { module = "androidx.test.ext:junit", version = "1.3.0" }
androidx-test-orchestrator = { module = "androidx.test:orchestrator", version = "1.6.1" }
androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidxTestCore" }
androidx-test-runner = { module = "androidx.test:runner", version = "1.6.2" }
androidx-test-runner = { module = "androidx.test:runner", version = "1.7.0" }
awaitility-kotlin = { module = "org.awaitility:awaitility-kotlin", version = "4.1.1" }
awaitility-kotlin-spring7 = { module = "org.awaitility:awaitility-kotlin", version = "4.3.0" }
awaitility3-kotlin = { module = "org.awaitility:awaitility-kotlin", version = "3.1.6" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public void onConfigurationChanged(@NotNull Configuration newConfig) {
executeInBackground(() -> captureConfigurationChangedBreadcrumb(now, newConfig));
}

@SuppressWarnings("deprecation")
@Override
public void onLowMemory() {
// we do this in onTrimMemory below already, this is legacy API (14 or below)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.sentry.android.core.internal.util;

import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
Expand All @@ -24,14 +25,32 @@ private AndroidThreadChecker() {
new Handler(Looper.getMainLooper()).post(() -> mainThreadSystemId = Process.myTid());
}

/**
* Gets the thread ID in a way that's compatible across Android versions.
*
* <p>Uses {@link Thread#threadId()} on Android 14 (API 34) and above, and falls back to {@link
* Thread#getId()} on older versions.
*
* @param thread the thread to get the ID for
* @return the thread ID
*/
@SuppressWarnings("deprecation")
public static long getThreadId(final @NotNull Thread thread) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong API level constant in version check

Medium Severity

The Javadoc states the method uses Thread.threadId() on "Android 14 (API 34) and above", and the PR description confirms threadId() is "available since API 34". However, the version check uses Build.VERSION_CODES.BAKLAVA (API 36) instead of UPSIDE_DOWN_CAKE (API 34). This causes devices running Android 14 and 15 to unnecessarily use the deprecated getId() method when threadId() is available.

Fix in Cursor Fix in Web

return thread.threadId();
} else {
return thread.getId();
}
}

@Override
public boolean isMainThread(final long threadId) {
return Looper.getMainLooper().getThread().getId() == threadId;
return getThreadId(Looper.getMainLooper().getThread()) == threadId;
}

@Override
public boolean isMainThread(final @NotNull Thread thread) {
return isMainThread(thread.getId());
return isMainThread(getThreadId(thread));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.sentry.SpanDataConvention;
import io.sentry.SpanStatus;
import io.sentry.android.core.AndroidDateUtils;
import io.sentry.android.core.internal.util.AndroidThreadChecker;
import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -129,7 +130,9 @@ public void clear() {
}

private void setDefaultStartSpanData(final @NotNull ISpan span) {
span.setData(SpanDataConvention.THREAD_ID, Looper.getMainLooper().getThread().getId());
span.setData(
SpanDataConvention.THREAD_ID,
AndroidThreadChecker.getThreadId(Looper.getMainLooper().getThread()));
span.setData(SpanDataConvention.THREAD_NAME, "main");
span.setData(SpanDataConvention.CONTRIBUTES_TTID, true);
span.setData(SpanDataConvention.CONTRIBUTES_TTFD, true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.sentry.uitest.android

import android.graphics.Color
import android.util.TypedValue
import android.view.View
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
Expand Down Expand Up @@ -550,10 +550,6 @@ class UserFeedbackUiTest : BaseUiTest() {
assertEquals((densityScale * 12).toInt(), widget.paddingTop)
assertEquals((densityScale * 12).toInt(), widget.paddingBottom)

val typedValue = TypedValue()
widget.context.theme.resolveAttribute(android.R.attr.colorForeground, typedValue, true)
assertEquals(typedValue.data, widget.currentTextColor)

assertEquals("Report a Bug", widget.text)
}

Expand Down Expand Up @@ -666,14 +662,19 @@ class UserFeedbackUiTest : BaseUiTest() {
val buttonId = Int.MAX_VALUE - 1
val feedbackScenario = launchActivity<EmptyActivity>()
feedbackScenario.onActivity {
val layoutParams =
FrameLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT,
)
val view =
LinearLayout(it).apply {
orientation = LinearLayout.VERTICAL
FrameLayout(it).apply {
addView(
SentryUserFeedbackButton(it).apply {
id = buttonId
widgetConfig?.invoke(this)
}
},
layoutParams,
)
}
it.setContentView(view)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.View
import android.widget.SeekBar
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import io.sentry.ITransaction
Expand All @@ -24,6 +25,21 @@ class ProfilingActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

onBackPressedDispatcher.addCallback(
this,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (profileFinished) {
isEnabled = false
onBackPressedDispatcher.onBackPressed()
} else {
Toast.makeText(this@ProfilingActivity, R.string.profiling_running, Toast.LENGTH_SHORT)
.show()
}
}
},
)
binding = ActivityProfilingBinding.inflate(layoutInflater)

binding.profilingDurationSeekbar.setOnSeekBarChangeListener(
Expand Down Expand Up @@ -156,14 +172,6 @@ class ProfilingActivity : AppCompatActivity() {
else -> fibonacci(n - 1) + fibonacci(n - 2)
}

override fun onBackPressed() {
if (profileFinished) {
super.onBackPressed()
} else {
Toast.makeText(this, R.string.profiling_running, Toast.LENGTH_SHORT).show()
}
}

private fun getProfileDuration(): Float {
// Minimum duration of the profile is 100 milliseconds
return binding.profilingDurationSeekbar.progress / 10.0F + 0.1F
Expand Down
Loading