@@ -54,6 +54,7 @@ public final class AndroidConnectionStatusProvider
5454 private static final @ NotNull AutoClosableReentrantLock childCallbacksLock =
5555 new AutoClosableReentrantLock ();
5656 private static final @ NotNull List <NetworkCallback > childCallbacks = new ArrayList <>();
57+ private static final AtomicBoolean isUpdatingCache = new AtomicBoolean (false );
5758
5859 private static final int [] transports = {
5960 NetworkCapabilities .TRANSPORT_WIFI ,
@@ -268,10 +269,19 @@ private void updateCacheAndNotifyObservers(
268269
269270 // Only notify observers if something meaningful changed
270271 if (shouldUpdate ) {
271- updateCache (networkCapabilities );
272-
273- final @ NotNull ConnectionStatus status = getConnectionStatusFromCache ();
274272 try (final @ NotNull ISentryLifecycleToken ignored = lock .acquire ()) {
273+ cachedNetworkCapabilities = networkCapabilities ;
274+ lastCacheUpdateTime = timeProvider .getCurrentTimeMillis ();
275+ final @ NotNull ConnectionStatus status = getConnectionStatusFromCache ();
276+ options
277+ .getLogger ()
278+ .log (
279+ SentryLevel .DEBUG ,
280+ "Cache updated - Status: "
281+ + status
282+ + ", Type: "
283+ + getConnectionTypeFromCache ());
284+
275285 for (final @ NotNull IConnectionStatusObserver observer :
276286 connectionStatusObservers ) {
277287 observer .onConnectionStatusChanged (status );
@@ -349,56 +359,57 @@ private boolean hasSignificantTransportChanges(
349359 }
350360
351361 @ SuppressLint ({"NewApi" , "MissingPermission" })
352- private void updateCache (@ Nullable NetworkCapabilities networkCapabilities ) {
362+ private void updateCache () {
353363 try (final @ NotNull ISentryLifecycleToken ignored = lock .acquire ()) {
354- try {
355- if (networkCapabilities != null ) {
356- cachedNetworkCapabilities = networkCapabilities ;
357- } else {
358- if (!Permissions .hasPermission (context , Manifest .permission .ACCESS_NETWORK_STATE )) {
359- options
360- .getLogger ()
361- .log (
362- SentryLevel .INFO ,
363- "No permission (ACCESS_NETWORK_STATE) to check network status." );
364- cachedNetworkCapabilities = null ;
365- lastCacheUpdateTime = timeProvider .getCurrentTimeMillis ();
366- return ;
367- }
364+ cachedNetworkCapabilities = null ;
365+ lastCacheUpdateTime = timeProvider .getCurrentTimeMillis ();
366+ }
367+ try {
368+ if (!Permissions .hasPermission (context , Manifest .permission .ACCESS_NETWORK_STATE )) {
369+ options
370+ .getLogger ()
371+ .log (SentryLevel .INFO , "No permission (ACCESS_NETWORK_STATE) to check network status." );
372+ return ;
373+ }
368374
369- if (buildInfoProvider .getSdkInfoVersion () < Build .VERSION_CODES .M ) {
370- cachedNetworkCapabilities = null ;
371- lastCacheUpdateTime = timeProvider .getCurrentTimeMillis ();
372- return ;
373- }
375+ if (buildInfoProvider .getSdkInfoVersion () < Build .VERSION_CODES .M ) {
376+ return ;
377+ }
374378
375- // Fallback: query current active network
376- final ConnectivityManager connectivityManager =
377- getConnectivityManager (context , options .getLogger ());
378- if (connectivityManager != null ) {
379- final Network activeNetwork = connectivityManager .getActiveNetwork ();
380-
381- cachedNetworkCapabilities =
382- activeNetwork != null
383- ? connectivityManager .getNetworkCapabilities (activeNetwork )
384- : null ;
385- } else {
386- cachedNetworkCapabilities =
387- null ; // Clear cached capabilities if connectivity manager is null
388- }
389- }
390- lastCacheUpdateTime = timeProvider .getCurrentTimeMillis ();
379+ // Fallback: query current active network in the background
380+ submitSafe (
381+ () -> {
382+ // Avoid concurrent updates
383+ if (!isUpdatingCache .getAndSet (true )) {
384+ final ConnectivityManager connectivityManager =
385+ getConnectivityManager (context , options .getLogger ());
386+ if (connectivityManager != null ) {
387+ final @ Nullable NetworkCapabilities capabilities =
388+ getNetworkCapabilities (connectivityManager );
389+
390+ try (final @ NotNull ISentryLifecycleToken ignored2 = lock .acquire ()) {
391+ cachedNetworkCapabilities = capabilities ;
392+ lastCacheUpdateTime = timeProvider .getCurrentTimeMillis ();
393+
394+ if (capabilities != null ) {
395+ options
396+ .getLogger ()
397+ .log (
398+ SentryLevel .DEBUG ,
399+ "Cache updated - Status: "
400+ + getConnectionStatusFromCache ()
401+ + ", Type: "
402+ + getConnectionTypeFromCache ());
403+ }
404+ }
405+ }
406+ isUpdatingCache .set (false );
407+ }
408+ });
391409
392- options
393- .getLogger ()
394- .log (
395- SentryLevel .DEBUG ,
396- "Cache updated - Status: "
397- + getConnectionStatusFromCache ()
398- + ", Type: "
399- + getConnectionTypeFromCache ());
400- } catch (Throwable t ) {
401- options .getLogger ().log (SentryLevel .WARNING , "Failed to update connection status cache" , t );
410+ } catch (Throwable t ) {
411+ options .getLogger ().log (SentryLevel .WARNING , "Failed to update connection status cache" , t );
412+ try (final @ NotNull ISentryLifecycleToken ignored = lock .acquire ()) {
402413 cachedNetworkCapabilities = null ;
403414 lastCacheUpdateTime = timeProvider .getCurrentTimeMillis ();
404415 }
@@ -412,15 +423,15 @@ private boolean isCacheValid() {
412423 @ Override
413424 public @ NotNull ConnectionStatus getConnectionStatus () {
414425 if (!isCacheValid ()) {
415- updateCache (null );
426+ updateCache ();
416427 }
417428 return getConnectionStatusFromCache ();
418429 }
419430
420431 @ Override
421432 public @ Nullable String getConnectionType () {
422433 if (!isCacheValid ()) {
423- updateCache (null );
434+ updateCache ();
424435 }
425436 return getConnectionTypeFromCache ();
426437 }
@@ -490,7 +501,7 @@ public void onForeground() {
490501 () -> {
491502 // proactively update cache and notify observers on foreground to ensure connectivity
492503 // state is not stale
493- updateCache (null );
504+ updateCache ();
494505
495506 final @ NotNull ConnectionStatus status = getConnectionStatusFromCache ();
496507 if (status == ConnectionStatus .DISCONNECTED ) {
@@ -575,6 +586,14 @@ public NetworkCapabilities getCachedNetworkCapabilities() {
575586 }
576587 }
577588
589+ @ RequiresApi (Build .VERSION_CODES .M )
590+ @ SuppressLint ("MissingPermission" )
591+ private static @ Nullable NetworkCapabilities getNetworkCapabilities (
592+ final @ NotNull ConnectivityManager connectivityManager ) {
593+ final Network activeNetwork = connectivityManager .getActiveNetwork ();
594+ return activeNetwork != null ? connectivityManager .getNetworkCapabilities (activeNetwork ) : null ;
595+ }
596+
578597 /**
579598 * Check the connection type of the active network
580599 *
@@ -603,14 +622,7 @@ public NetworkCapabilities getCachedNetworkCapabilities() {
603622 boolean cellular = false ;
604623
605624 if (buildInfoProvider .getSdkInfoVersion () >= Build .VERSION_CODES .M ) {
606-
607- final Network activeNetwork = connectivityManager .getActiveNetwork ();
608- if (activeNetwork == null ) {
609- logger .log (SentryLevel .INFO , "Network is null and cannot check network status" );
610- return null ;
611- }
612- final NetworkCapabilities networkCapabilities =
613- connectivityManager .getNetworkCapabilities (activeNetwork );
625+ final NetworkCapabilities networkCapabilities = getNetworkCapabilities (connectivityManager );
614626 if (networkCapabilities == null ) {
615627 logger .log (SentryLevel .INFO , "NetworkCapabilities is null and cannot check network type" );
616628 return null ;
0 commit comments