Skip to content

Commit

Permalink
check available url
Browse files Browse the repository at this point in the history
  • Loading branch information
Okuro3499 committed Dec 4, 2024
1 parent 6e539a4 commit 8153dec
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 65 deletions.
267 changes: 202 additions & 65 deletions app/src/main/java/org/ole/planet/myplanet/datamanager/Service.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ import android.content.DialogInterface
import android.content.SharedPreferences
import android.net.Uri
import android.text.TextUtils
import android.util.Log
import com.google.gson.Gson
import com.google.gson.JsonObject
import io.realm.Realm
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.ResponseBody
import org.ole.planet.myplanet.BuildConfig
import org.ole.planet.myplanet.MainApplication
import org.ole.planet.myplanet.MainApplication.Companion.applicationScope
import org.ole.planet.myplanet.MainApplication.Companion.isServerReachable
import org.ole.planet.myplanet.R
import org.ole.planet.myplanet.callback.SuccessListener
Expand Down Expand Up @@ -321,86 +326,218 @@ class Service(private val context: Context) {
}

fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) {
val customProgressDialog = CustomProgressDialog(context).apply {
setText(context.getString(R.string.check_apk_version))
show()
// Create a list of URLs to try, starting with the original URL
val urlsToTry = mutableListOf(url)

val serverMappings = mapOf(
"http://${BuildConfig.PLANET_URIUR_URL}" to "http://35.231.161.29",
"http://192.168.1.202" to "http://34.35.29.147",
"https://${BuildConfig.PLANET_GUATEMALA_URL}" to "http://guatemala.com/cloudserver",
"http://${BuildConfig.PLANET_XELA_URL}" to "http://xela.com/cloudserver",
"http://${BuildConfig.PLANET_SANPABLO_URL}" to "http://sanpablo.com/cloudserver",
"http://${BuildConfig.PLANET_EMBAKASI_URL}" to "http://embakasi.com/cloudserver",
"https://${BuildConfig.PLANET_VI_URL}" to "http://vi.com/cloudserver"
)

// Add alternative URL from serverMappings if available
serverMappings[url]?.let { alternativeUrl ->
urlsToTry.add(alternativeUrl)
}

retrofitInterface?.getConfiguration("$url/versions")?.enqueue(object : Callback<JsonObject?> {
override fun onResponse(call: Call<JsonObject?>, response: Response<JsonObject?>) {
if (response.isSuccessful) {
response.body()?.let { jsonObject ->
val currentVersion = "${context.resources.getText(R.string.app_version)}"
val minApkVersion = jsonObject.get("minapk").asString
if (isVersionAllowed(currentVersion, minApkVersion)) {
customProgressDialog.setText(context.getString(R.string.checking_server))
val uri = Uri.parse(url)
val couchdbURL: String
if (url.contains("@")) {
getUserInfo(uri)
couchdbURL = url
} else {
val urlUser = "satellite"
couchdbURL = "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}"
}
retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").enqueue(object : Callback<JsonObject?> {
override fun onResponse(call: Call<JsonObject?>, response: Response<JsonObject?>) {
if (response.isSuccessful) {
val jsonObjectResponse = response.body()
val rows = jsonObjectResponse?.getAsJsonArray("rows")
if (rows != null && rows.size() > 0) {
val firstRow = rows.get(0).asJsonObject
val id = firstRow.getAsJsonPrimitive("id").asString
val doc = firstRow.getAsJsonObject("doc")
val code = doc.getAsJsonPrimitive("code").asString
listener?.onConfigurationIdReceived(id, code)
activity.setSyncFailed(false)
// Use coroutine scope to perform concurrent URL checks
applicationScope.launch {
val customProgressDialog = withContext(Dispatchers.Main) {
CustomProgressDialog(context).apply {
setText(context.getString(R.string.check_apk_version))
show()
}
}

try {
// Use withContext(Dispatchers.IO) for network operations
val result = withContext(Dispatchers.IO) {
// Create a list of deferred jobs for concurrent network calls
val deferredResults = urlsToTry.map { currentUrl ->
async {
try {
Log.d("Service", "Checking URL: $currentUrl")
// Check versions concurrently
val versionsResponse = retrofitInterface?.getConfiguration("$currentUrl/versions")?.execute()

if (versionsResponse?.isSuccessful == true) {
val jsonObject = versionsResponse.body()
val currentVersion = "${context.resources.getText(R.string.app_version)}"
val minApkVersion = jsonObject?.get("minapk")?.asString
Log.d("okuro", "first config check is successful")

// Version check
if (minApkVersion != null && isVersionAllowed(currentVersion, minApkVersion)) {
// Perform configuration check for this URL
val uri = Uri.parse(currentUrl)
val couchdbURL = if (currentUrl.contains("@")) {
getUserInfo(uri)
currentUrl
} else {
activity.setSyncFailed(true)
showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false)
val urlUser = "satellite"
"${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}"
}
withContext(Dispatchers.Main) {
customProgressDialog.setText(context.getString(R.string.checking_server))
}
val configResponse = retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").execute()

if (configResponse.isSuccessful) {
Log.d("okuro", "second config check is successful")
val rows = configResponse.body()?.getAsJsonArray("rows")
if (rows != null && rows.size() > 0) {
val firstRow = rows.get(0).asJsonObject
val id = firstRow.getAsJsonPrimitive("id").asString
val doc = firstRow.getAsJsonObject("doc")
val code = doc.getAsJsonPrimitive("code").asString
return@async UrlCheckResult.Success(id, code, currentUrl)
}
}
} else {
activity.setSyncFailed(true)
showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false)
}
customProgressDialog.dismiss()
}

override fun onFailure(call: Call<JsonObject?>, t: Throwable) {
activity.setSyncFailed(true)
customProgressDialog.dismiss()
if (getUrl(couchdbURL) == context.getString(R.string.http_protocol)) {
showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false)
} else if (getUrl(couchdbURL) == context.getString(R.string.https_protocol)) {
showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false)
}
}
})
} else {
activity.setSyncFailed(true)
customProgressDialog.dismiss()
showAlertDialog(context.getString(R.string.below_min_apk), true)
return@async UrlCheckResult.Failure(currentUrl)
} catch (e: Exception) {
e.printStackTrace()
return@async UrlCheckResult.Failure(currentUrl)
}
}
}
} else {
activity.setSyncFailed(true)
customProgressDialog.dismiss()
showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false)

// Wait for the first successful result
deferredResults.awaitFirst { it is UrlCheckResult.Success }
}
}

override fun onFailure(call: Call<JsonObject?>, t: Throwable) {
// Handle the result
when (result) {
is UrlCheckResult.Success -> {
listener?.onConfigurationIdReceived(result.id, result.code)
activity.setSyncFailed(false)
Log.d("Service", "Successfully connected to URL: ${result.url}")
}
is UrlCheckResult.Failure -> {
activity.setSyncFailed(true)
val errorMessage = when (extractProtocol(url)) {
context.getString(R.string.http_protocol) -> context.getString(R.string.device_couldn_t_reach_local_server)
context.getString(R.string.https_protocol) -> context.getString(R.string.device_couldn_t_reach_nation_server)
else -> context.getString(R.string.device_couldn_t_reach_local_server)
}
showAlertDialog(errorMessage, false)
}
}
} catch (e: Exception) {
e.printStackTrace()
activity.setSyncFailed(true)
showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false)
} finally {
customProgressDialog.dismiss()
if (extractProtocol(url) == context.getString(R.string.http_protocol)) {
showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false)
} else if (extractProtocol(url) == context.getString(R.string.https_protocol)) {
showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false)
}
}
})
}
}

// Sealed class to represent URL check results
sealed class UrlCheckResult {
data class Success(val id: String, val code: String, val url: String) : UrlCheckResult()
data class Failure(val url: String) : UrlCheckResult()
}

// Extension function to await the first successful result
private suspend fun <T> List<Deferred<T>>.awaitFirst(predicate: (T) -> Boolean): T {
return firstOrNull { job ->
try {
val result = job.await()
predicate(result)
} catch (e: Exception) {
e.printStackTrace()
false
}
}?.await() ?: throw NoSuchElementException("No matching result found")
}

// fun getMinApk(listener: ConfigurationIdListener?, url: String, pin: String, activity: SyncActivity) {
// val customProgressDialog = CustomProgressDialog(context).apply {
// setText(context.getString(R.string.check_apk_version))
// show()
// }
//
// retrofitInterface?.getConfiguration("$url/versions")?.enqueue(object : Callback<JsonObject?> {
// override fun onResponse(call: Call<JsonObject?>, response: Response<JsonObject?>) {
// if (response.isSuccessful) {
// response.body()?.let { jsonObject ->
// val currentVersion = "${context.resources.getText(R.string.app_version)}"
// val minApkVersion = jsonObject.get("minapk").asString
// if (isVersionAllowed(currentVersion, minApkVersion)) {
// customProgressDialog.setText(context.getString(R.string.checking_server))
// val uri = Uri.parse(url)
// val couchdbURL: String
// if (url.contains("@")) {
// getUserInfo(uri)
// couchdbURL = url
// } else {
// val urlUser = "satellite"
// couchdbURL = "${uri.scheme}://$urlUser:$pin@${uri.host}:${if (uri.port == -1) if (uri.scheme == "http") 80 else 443 else uri.port}"
// }
// retrofitInterface.getConfiguration("${getUrl(couchdbURL)}/configurations/_all_docs?include_docs=true").enqueue(object : Callback<JsonObject?> {
// override fun onResponse(call: Call<JsonObject?>, response: Response<JsonObject?>) {
// if (response.isSuccessful) {
// val jsonObjectResponse = response.body()
// val rows = jsonObjectResponse?.getAsJsonArray("rows")
// if (rows != null && rows.size() > 0) {
// val firstRow = rows.get(0).asJsonObject
// val id = firstRow.getAsJsonPrimitive("id").asString
// val doc = firstRow.getAsJsonObject("doc")
// val code = doc.getAsJsonPrimitive("code").asString
// listener?.onConfigurationIdReceived(id, code)
// activity.setSyncFailed(false)
// } else {
// activity.setSyncFailed(true)
// showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false)
// }
// } else {
// activity.setSyncFailed(true)
// showAlertDialog(context.getString(R.string.failed_to_get_configuration_id), false)
// }
// customProgressDialog.dismiss()
// }
//
// override fun onFailure(call: Call<JsonObject?>, t: Throwable) {
// activity.setSyncFailed(true)
// customProgressDialog.dismiss()
// if (getUrl(couchdbURL) == context.getString(R.string.http_protocol)) {
// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false)
// } else if (getUrl(couchdbURL) == context.getString(R.string.https_protocol)) {
// showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false)
// }
// }
// })
// } else {
// activity.setSyncFailed(true)
// customProgressDialog.dismiss()
// showAlertDialog(context.getString(R.string.below_min_apk), true)
// }
// }
// } else {
// activity.setSyncFailed(true)
// customProgressDialog.dismiss()
// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false)
// }
// }
//
// override fun onFailure(call: Call<JsonObject?>, t: Throwable) {
// activity.setSyncFailed(true)
// customProgressDialog.dismiss()
// if (extractProtocol(url) == context.getString(R.string.http_protocol)) {
// showAlertDialog(context.getString(R.string.device_couldn_t_reach_local_server), false)
// } else if (extractProtocol(url) == context.getString(R.string.https_protocol)) {
// showAlertDialog(context.getString(R.string.device_couldn_t_reach_nation_server), false)
// }
// }
// })
// }

private fun isVersionAllowed(currentVersion: String, minApkVersion: String): Boolean {
return compareVersions(currentVersion, minApkVersion) >= 0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers
}

override fun onConfigurationIdReceived(id: String, code:String) {
Log.d("SyncActivity", "onConfigurationIdReceived: $id")
Log.d("SyncActivity", "onConfigurationIdReceived: $code")
val savedId = settings.getString("configurationId", null)
if (serverConfigAction == "sync") {
if (savedId == null) {
Expand Down Expand Up @@ -742,6 +744,7 @@ abstract class SyncActivity : ProcessUserDataActivity(), SyncListener, CheckVers
}

private fun continueSync(dialog: MaterialDialog) {
Log.d("SyncActivity", "continueSync: $processedUrl")
processedUrl = saveConfigAndContinue(dialog)
if (TextUtils.isEmpty(processedUrl)) return
isSync = true
Expand Down

0 comments on commit 8153dec

Please sign in to comment.