Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adfc07b3 authored by Hasib Prince's avatar Hasib Prince
Browse files

Handled gplay api errors

parent cf19a70e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -118,7 +118,7 @@ class FusedAPIRepository @Inject constructor(private val fusedAPIImpl: FusedApi)
    suspend fun getGplaySearchResults(
        query: String,
        nextPageSubBundle: Set<SearchBundle.SubBundle>?
    ): Pair<List<FusedApp>, Set<SearchBundle.SubBundle>> {
    ): GplaySearchResult {
        return fusedAPIImpl.getGplaySearchResult(query, nextPageSubBundle)
    }

+3 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ import foundation.e.apps.data.fused.utils.CategoryType
import foundation.e.apps.data.fusedDownload.models.FusedDownload
import retrofit2.Response

typealias GplaySearchResult = ResultSupreme<Pair<List<FusedApp>, Set<SearchBundle.SubBundle>>>

interface FusedApi {
    companion object {
        const val APP_TYPE_ANY = "any"
@@ -68,7 +70,7 @@ interface FusedApi {
    suspend fun getGplaySearchResult(
        query: String,
        nextPageSubBundle: Set<SearchBundle.SubBundle>?
    ): Pair<List<FusedApp>, Set<SearchBundle.SubBundle>>
    ): GplaySearchResult

    suspend fun getSearchSuggestions(query: String): List<SearchSuggestEntry>

+954 −939
Original line number Diff line number Diff line
@@ -64,11 +64,15 @@ import foundation.e.apps.data.fused.utils.CategoryType
import foundation.e.apps.data.fused.utils.CategoryUtils
import foundation.e.apps.data.fusedDownload.models.FusedDownload
import foundation.e.apps.data.gplay.GplayStoreRepository
import foundation.e.apps.data.gplay.utils.GplayHttpRequestException
import foundation.e.apps.data.gplay.utils.runFlowWithTimeout
import foundation.e.apps.data.login.exceptions.GPlayException
import foundation.e.apps.data.login.exceptions.UnknownSourceException
import foundation.e.apps.data.preference.PreferenceManagerModule
import foundation.e.apps.install.pkg.PWAManagerModule
import foundation.e.apps.install.pkg.PkgManagerModule
import foundation.e.apps.ui.home.model.HomeChildFusedAppDiffUtil
import foundation.e.apps.ui.search.SearchViewModel
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.async
@@ -78,11 +82,11 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withTimeout
import retrofit2.Response
import timber.log.Timber
import java.net.SocketTimeoutException
import javax.inject.Inject
import javax.inject.Named
import javax.inject.Singleton

typealias GplaySearchResultFlow = Flow<ResultSupreme<Pair<List<FusedApp>, Boolean>>>
typealias FusedHomeDeferred = Deferred<ResultSupreme<List<FusedHome>>>

@Singleton
@@ -101,6 +105,8 @@ class FusedApiImpl @Inject constructor(
        private const val CATEGORY_TITLE_REPLACEABLE_CONJUNCTION = "&"
        private const val CATEGORY_OPEN_GAMES_ID = "game_open_games"
        private const val CATEGORY_OPEN_GAMES_TITLE = "Open games"
        private const val ERROR_GPLAY_SEARCH = "Gplay search is failed!"
        private const val ERROR_GPLAY_SOURCE_NOT_SELECTED = "Gplay apps are not selected!"
    }

    /**
@@ -1103,22 +1109,31 @@ private suspend fun getCleanAPKSearchResults(
    override suspend fun getGplaySearchResult(
        query: String,
        nextPageSubBundle: Set<SearchBundle.SubBundle>?
): Pair<List<FusedApp>, Set<SearchBundle.SubBundle>> {
    ): GplaySearchResult {
        try {
            val searchResults =
                gplayRepository.getSearchResult(query, nextPageSubBundle?.toMutableSet())

            if (!preferenceManagerModule.isGplaySelected()) {
        return Pair(emptyList(), emptySet())
                return ResultSupreme.Error(ERROR_GPLAY_SOURCE_NOT_SELECTED)
            }

    val fusedAppList = searchResults.first.map { app -> replaceWithFDroid(app) }.toMutableList()
            val fusedAppList =
                searchResults.first.map { app -> replaceWithFDroid(app) }.toMutableList()
            if (searchResults.second.isNotEmpty()) {
                fusedAppList.add(FusedApp(isPlaceHolder = true))
            }

    return Pair(
        fusedAppList,
        searchResults.second
    )
            return ResultSupreme.Success(Pair(fusedAppList.toList(), searchResults.second.toSet()))
        } catch (e: GplayHttpRequestException) {
            val message = e.localizedMessage?.ifBlank { ERROR_GPLAY_SEARCH } ?: ERROR_GPLAY_SEARCH
            val exception = GPlayException(e.status == 408, message)
            return ResultSupreme.Error(message, exception)
        } catch (e: Exception) {
            val exception =
                GPlayException(e is SocketTimeoutException, e.localizedMessage)
            return ResultSupreme.Error(e.localizedMessage, exception)
        }
    }

    /*
+19 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import timber.log.Timber
import java.io.IOException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.concurrent.TimeUnit
import javax.inject.Inject

class GPlayHttpClient @Inject constructor(
@@ -52,10 +53,12 @@ class GPlayHttpClient @Inject constructor(

    companion object {
        private const val TAG = "GPlayHttpClient"
        private const val HTTP_TIMEOUT_IN_SECOND = 10L
    }

    private val okHttpClient = OkHttpClient().newBuilder()
        .retryOnConnectionFailure(false)
        .callTimeout(HTTP_TIMEOUT_IN_SECOND, TimeUnit.SECONDS)
        .followRedirects(true)
        .followSslRedirects(true)
        .cache(cache)
@@ -155,6 +158,13 @@ class GPlayHttpClient @Inject constructor(
            val call = okHttpClient.newCall(request)
            buildPlayResponse(call.execute())
        } catch (e: Exception) {
            //TODO: exception will be thrown for all apis when all gplay api implementation
            // will handle the exceptions. this will be done in following issue.
            // Issue: https://gitlab.e.foundation/e/os/backlog/-/issues/1483
            if (request.url.toString().contains("search")) {
                throw e
            }

            when (e) {
                is UnknownHostException,
                is SocketTimeoutException -> handleExceptionOnGooglePlayRequest(e)
@@ -185,6 +195,13 @@ class GPlayHttpClient @Inject constructor(

            Timber.d("$TAG: Url: ${response.request.url}\nStatus: $code")

            //TODO: exception will be thrown for all apis when all gplay api implementation
            // will handle the exceptions. this will be done in following issue.
            // Issue: https://gitlab.e.foundation/e/os/backlog/-/issues/1483
            if (response.request.url.toString().contains("search") && code != 200) {
                throw GplayHttpRequestException(code, response.message)
            }

            if (code == 401) {
                MainScope().launch {
                    EventBus.invokeEvent(
@@ -203,3 +220,5 @@ class GPlayHttpClient @Inject constructor(
        }
    }
}

class GplayHttpRequestException (val status: Int, message: String) : Exception(message)
 No newline at end of file
+2 −17
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import foundation.e.apps.install.updates.UpdatesNotifier
import foundation.e.apps.utils.eventBus.AppEvent
import foundation.e.apps.utils.eventBus.EventBus
import foundation.e.apps.utils.getFormattedString
import foundation.e.apps.utils.isNetworkAvailable
import kotlinx.coroutines.flow.transformWhile
import timber.log.Timber
import java.text.NumberFormat
@@ -122,7 +123,7 @@ class AppInstallProcessor @Inject constructor(
                return
            }

            if (!isNetworkAvailable()) {
            if (!context.isNetworkAvailable()) {
                fusedManagerRepository.installationIssue(fusedDownload)
                EventBus.invokeEvent(AppEvent.NoInternetEvent(false))
                return
@@ -185,22 +186,6 @@ class AppInstallProcessor @Inject constructor(
        return statFs.availableBytes
    }

    private fun isNetworkAvailable(): Boolean {
        val connectivityManager =
            context.getSystemService(ConnectivityManager::class.java)
        val capabilities =
            connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
                ?: return false

        if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
            capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
        ) {
            return true
        }

        return false
    }

    suspend fun processInstall(
        fusedDownloadId: String,
        isItUpdateWork: Boolean,
Loading