Skip to content

Commit 0f88e95

Browse files
authored
Set export flag on Android receivers on API 33+ (#2990)
* registerReceiver now sets the RECEIVER_EXPORTED flag on API 33+ * updated SDK target version to 34
1 parent 287e750 commit 0f88e95

File tree

7 files changed

+74
-7
lines changed

7 files changed

+74
-7
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Set export flag on Android receivers on API 33+ ([#2990](https://github.com/getsentry/sentry-java/pull/2990))
8+
39
## 6.31.0
410

511
### Features

buildSrc/src/main/java/Config.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ object Config {
3030
}
3131

3232
object Android {
33-
private val sdkVersion = 33
33+
private val sdkVersion = 34
3434

3535
val minSdkVersion = 14
3636
val minSdkVersionOkHttp = 21
@@ -181,10 +181,10 @@ object Config {
181181
val espressoCore = "androidx.test.espresso:espresso-core:$espressoVersion"
182182
val espressoIdlingResource = "androidx.test.espresso:espresso-idling-resource:$espressoVersion"
183183
val androidxTestOrchestrator = "androidx.test:orchestrator:1.4.2"
184-
val androidxJunit = "androidx.test.ext:junit:1.1.3"
184+
val androidxJunit = "androidx.test.ext:junit:1.1.5"
185185
val androidxCoreKtx = "androidx.core:core-ktx:1.7.0"
186-
val robolectric = "org.robolectric:robolectric:4.7.3"
187-
val mockitoKotlin = "org.mockito.kotlin:mockito-kotlin:4.0.0"
186+
val robolectric = "org.robolectric:robolectric:4.10.3"
187+
val mockitoKotlin = "org.mockito.kotlin:mockito-kotlin:4.1.0"
188188
val mockitoInline = "org.mockito:mockito-inline:4.8.0"
189189
val awaitility = "org.awaitility:awaitility-kotlin:4.1.1"
190190
val mockWebserver = "com.squareup.okhttp3:mockwebserver:${Libs.okHttpVersion}"

sentry-android-core/src/main/java/io/sentry/android/core/ContextUtils.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
44
import static android.content.Context.ACTIVITY_SERVICE;
5+
import static android.content.Context.RECEIVER_EXPORTED;
56
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
67

78
import android.annotation.SuppressLint;
89
import android.app.ActivityManager;
10+
import android.content.BroadcastReceiver;
911
import android.content.Context;
12+
import android.content.Intent;
13+
import android.content.IntentFilter;
1014
import android.content.pm.ApplicationInfo;
1115
import android.content.pm.PackageInfo;
1216
import android.content.pm.PackageManager;
@@ -16,6 +20,7 @@
1620
import android.util.DisplayMetrics;
1721
import io.sentry.ILogger;
1822
import io.sentry.SentryLevel;
23+
import io.sentry.SentryOptions;
1924
import io.sentry.protocol.App;
2025
import java.io.BufferedReader;
2126
import java.io.File;
@@ -346,6 +351,33 @@ static boolean isForegroundImportance(final @NotNull Context context) {
346351
}
347352
}
348353

354+
/** Register a not exported BroadcastReceiver, independently from platform version. */
355+
static @Nullable Intent registerReceiver(
356+
final @NotNull Context context,
357+
final @NotNull SentryOptions options,
358+
final @Nullable BroadcastReceiver receiver,
359+
final @NotNull IntentFilter filter) {
360+
return registerReceiver(context, new BuildInfoProvider(options.getLogger()), receiver, filter);
361+
}
362+
363+
/** Register a not exported BroadcastReceiver, independently from platform version. */
364+
@SuppressLint({"NewApi", "UnspecifiedRegisterReceiverFlag"})
365+
static @Nullable Intent registerReceiver(
366+
final @NotNull Context context,
367+
final @NotNull BuildInfoProvider buildInfoProvider,
368+
final @Nullable BroadcastReceiver receiver,
369+
final @NotNull IntentFilter filter) {
370+
if (buildInfoProvider.getSdkInfoVersion() >= Build.VERSION_CODES.TIRAMISU) {
371+
// From https://developer.android.com/guide/components/broadcasts#context-registered-receivers
372+
// If this receiver is listening for broadcasts sent from the system or from other apps, even
373+
// other apps that you own—use the RECEIVER_EXPORTED flag. If instead this receiver is
374+
// listening only for broadcasts sent by your app, use the RECEIVER_NOT_EXPORTED flag.
375+
return context.registerReceiver(receiver, filter, RECEIVER_EXPORTED);
376+
} else {
377+
return context.registerReceiver(receiver, filter);
378+
}
379+
}
380+
349381
// we perform an if-check for that, but lint fails to recognize
350382
@SuppressLint("NewApi")
351383
static void setAppPackageInfo(

sentry-android-core/src/main/java/io/sentry/android/core/DeviceInfoUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ private Date getBootTime() {
262262

263263
@Nullable
264264
private Intent getBatteryIntent() {
265-
return context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
265+
return ContextUtils.registerReceiver(
266+
context, buildInfoProvider, null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
266267
}
267268

268269
/**

sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public void register(final @NotNull IHub hub, final @NotNull SentryOptions optio
9999
}
100100
try {
101101
// registerReceiver can throw SecurityException but it's not documented in the official docs
102-
context.registerReceiver(receiver, filter);
102+
ContextUtils.registerReceiver(context, options, receiver, filter);
103103
this.options
104104
.getLogger()
105105
.log(SentryLevel.DEBUG, "SystemEventsBreadcrumbsIntegration installed.");

sentry-android-core/src/test/java/io/sentry/android/core/ContextUtilsUnitTests.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@ package io.sentry.android.core
22

33
import android.app.ActivityManager
44
import android.app.ActivityManager.MemoryInfo
5+
import android.content.BroadcastReceiver
56
import android.content.Context
7+
import android.content.IntentFilter
8+
import android.os.Build
69
import androidx.test.core.app.ApplicationProvider
710
import androidx.test.ext.junit.runners.AndroidJUnit4
811
import io.sentry.ILogger
912
import io.sentry.NoOpLogger
1013
import org.junit.runner.RunWith
1114
import org.mockito.kotlin.any
15+
import org.mockito.kotlin.eq
1216
import org.mockito.kotlin.mock
1317
import org.mockito.kotlin.spy
18+
import org.mockito.kotlin.verify
1419
import org.mockito.kotlin.whenever
1520
import org.robolectric.annotation.Config
1621
import org.robolectric.shadow.api.Shadow
@@ -24,6 +29,7 @@ import kotlin.test.assertNotNull
2429
import kotlin.test.assertNull
2530
import kotlin.test.assertTrue
2631

32+
@Config(sdk = [33])
2733
@RunWith(AndroidJUnit4::class)
2834
class ContextUtilsUnitTests {
2935

@@ -161,4 +167,26 @@ class ContextUtilsUnitTests {
161167
val memInfo = ContextUtils.getMemInfo(mock(), logger)
162168
assertNull(memInfo)
163169
}
170+
171+
@Test
172+
fun `registerReceiver calls context_registerReceiver without exported flag on API 32-`() {
173+
val buildInfo = mock<BuildInfoProvider>()
174+
val receiver = mock<BroadcastReceiver>()
175+
val filter = mock<IntentFilter>()
176+
val context = mock<Context>()
177+
whenever(buildInfo.sdkInfoVersion).thenReturn(Build.VERSION_CODES.S)
178+
ContextUtils.registerReceiver(context, buildInfo, receiver, filter)
179+
verify(context).registerReceiver(eq(receiver), eq(filter))
180+
}
181+
182+
@Test
183+
fun `registerReceiver calls context_registerReceiver with exported flag on API 33+`() {
184+
val buildInfo = mock<BuildInfoProvider>()
185+
val receiver = mock<BroadcastReceiver>()
186+
val filter = mock<IntentFilter>()
187+
val context = mock<Context>()
188+
whenever(buildInfo.sdkInfoVersion).thenReturn(Build.VERSION_CODES.TIRAMISU)
189+
ContextUtils.registerReceiver(context, buildInfo, receiver, filter)
190+
verify(context).registerReceiver(eq(receiver), eq(filter), eq(Context.RECEIVER_EXPORTED))
191+
}
164192
}

sentry-samples/sentry-samples-android/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,6 @@
150150

151151
<!-- how to disable sentry -->
152152
<!-- <meta-data android:name="io.sentry.enabled" android:value="false" /> -->
153-
153+
154154
</application>
155155
</manifest>

0 commit comments

Comments
 (0)