Skip to content

Commit 88f0753

Browse files
Refactor: Make isServerReachable asynchronous
Refactored `isServerReachable` to be a `suspend` function that uses a Retrofit `HEAD` request instead of a synchronous `HttpURLConnection`. This eliminates the risk of an ANR when checking for server connectivity. - Created a `HealthCheckApi` interface for the `HEAD` request. - Added a custom `OkHttpClient` with a 5-second timeout for the health check. - Restored the `ServerUrlMapper` and URL scheme-prepending logic to maintain existing functionality.
1 parent 83a17ba commit 88f0753

File tree

4 files changed

+73
-26
lines changed

4 files changed

+73
-26
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.ole.planet.myplanet.di
2+
3+
import dagger.hilt.EntryPoint
4+
import dagger.hilt.InstallIn
5+
import dagger.hilt.components.SingletonComponent
6+
7+
@EntryPoint
8+
@InstallIn(SingletonComponent::class)
9+
interface HealthCheckEntryPoint {
10+
fun healthCheckApi(): HealthCheckApi
11+
}

app/src/main/java/org/ole/planet/myplanet/MainApplication.kt

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import android.os.StrictMode.VmPolicy
1212
import android.provider.Settings
1313
import androidx.appcompat.app.AppCompatDelegate
1414
import androidx.work.ExistingPeriodicWorkPolicy
15+
import androidx.annotation.WorkerThread
1516
import androidx.work.PeriodicWorkRequest
1617
import androidx.work.WorkManager
1718
import dagger.hilt.android.EntryPointAccessors
@@ -37,6 +38,7 @@ import org.ole.planet.myplanet.datamanager.DatabaseService
3738
import org.ole.planet.myplanet.di.ApiClientEntryPoint
3839
import org.ole.planet.myplanet.di.AppPreferences
3940
import org.ole.planet.myplanet.di.DefaultPreferences
41+
import org.ole.planet.myplanet.di.HealthCheckEntryPoint
4042
import org.ole.planet.myplanet.di.WorkerDependenciesEntryPoint
4143
import org.ole.planet.myplanet.model.RealmApkLog
4244
import org.ole.planet.myplanet.service.AutoSyncWorker
@@ -51,6 +53,7 @@ import org.ole.planet.myplanet.utilities.NetworkUtils.isNetworkConnectedFlow
5153
import org.ole.planet.myplanet.utilities.NetworkUtils.startListenNetworkState
5254
import org.ole.planet.myplanet.utilities.NetworkUtils.stopListenNetworkState
5355
import org.ole.planet.myplanet.utilities.ServerUrlMapper
56+
import org.ole.planet.myplanet.utilities.ServerUrlMapper
5457
import org.ole.planet.myplanet.utilities.ThemeMode
5558
import org.ole.planet.myplanet.utilities.VersionUtils.getVersionName
5659

@@ -126,39 +129,37 @@ class MainApplication : Application(), Application.ActivityLifecycleCallbacks {
126129
}
127130
}
128131

132+
@WorkerThread
129133
suspend fun isServerReachable(urlString: String): Boolean {
134+
if (urlString.isBlank()) return false
135+
130136
val serverUrlMapper = ServerUrlMapper()
131137
val mapping = serverUrlMapper.processUrl(urlString)
132-
val urlsToTry = mutableListOf(urlString)
138+
val urlsToTry = mutableListOf(mapping.primaryUrl)
133139
mapping.alternativeUrl?.let { urlsToTry.add(it) }
134140

135-
return try {
136-
if (urlString.isBlank()) return false
137-
138-
val formattedUrl = if (!urlString.startsWith("http://") && !urlString.startsWith("https://")) {
139-
"http://$urlString"
140-
} else {
141-
urlString
142-
}
143-
144-
val url = URL(formattedUrl)
145-
val connection = withContext(Dispatchers.IO) {
146-
url.openConnection()
147-
} as HttpURLConnection
148-
connection.requestMethod = "GET"
149-
connection.connectTimeout = 5000
150-
connection.readTimeout = 5000
151-
withContext(Dispatchers.IO) {
152-
connection.connect()
141+
val entryPoint = EntryPointAccessors.fromApplication(
142+
context,
143+
HealthCheckEntryPoint::class.java
144+
)
145+
val healthCheckApi = entryPoint.healthCheckApi()
146+
147+
for (url in urlsToTry) {
148+
try {
149+
val formattedUrl = if (!url.startsWith("http://") && !url.startsWith("https://")) {
150+
"http://$url"
151+
} else {
152+
url
153+
}
154+
val response = withContext(Dispatchers.IO) {
155+
healthCheckApi.checkServerHealth(formattedUrl)
156+
}
157+
if (response.isSuccessful) return true
158+
} catch (e: Exception) {
159+
e.printStackTrace()
153160
}
154-
val responseCode = connection.responseCode
155-
connection.disconnect()
156-
responseCode in 200..299
157-
158-
} catch (e: Exception) {
159-
e.printStackTrace()
160-
false
161161
}
162+
return false
162163
}
163164

164165
fun handleUncaughtException(e: Throwable) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.ole.planet.myplanet.di
2+
3+
import retrofit2.Response
4+
import retrofit2.http.HEAD
5+
import retrofit2.http.Url
6+
7+
interface HealthCheckApi {
8+
@HEAD
9+
suspend fun checkServerHealth(@Url url: String): Response<Void>
10+
}

app/src/main/java/org/ole/planet/myplanet/di/NetworkModule.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import org.ole.planet.myplanet.datamanager.ApiInterface
1616
import retrofit2.Retrofit
1717
import retrofit2.converter.gson.GsonConverterFactory
1818

19+
@Qualifier
20+
@Retention(AnnotationRetention.BINARY)
21+
annotation class HealthCheckHttpClient
22+
1923
@Qualifier
2024
@Retention(AnnotationRetention.BINARY)
2125
annotation class StandardHttpClient
@@ -45,6 +49,27 @@ object NetworkModule {
4549
.build()
4650
}
4751

52+
@Provides
53+
@Singleton
54+
@HealthCheckHttpClient
55+
fun provideHealthCheckOkHttpClient(): OkHttpClient {
56+
return buildOkHttpClient(5, 5, 5)
57+
}
58+
59+
@Provides
60+
@Singleton
61+
fun provideHealthCheckApi(
62+
@HealthCheckHttpClient okHttpClient: OkHttpClient,
63+
gson: Gson
64+
): HealthCheckApi {
65+
val retrofit = Retrofit.Builder()
66+
.baseUrl("http://localhost/") // Base URL is overridden by @Url
67+
.client(okHttpClient)
68+
.addConverterFactory(GsonConverterFactory.create(gson))
69+
.build()
70+
return retrofit.create(HealthCheckApi::class.java)
71+
}
72+
4873
@Provides
4974
@Singleton
5075
@StandardHttpClient

0 commit comments

Comments
 (0)