Как обработать ошибку в Api android
Вот мой код с работающим Api, в целом он работает нормально. Это Погодный Api, в котором я подставляю города, и он выдает погоду в определенном городе. Но у меня возникает проблема, если я подставляю неправильный город, которого не существует, соответственно, из Api сервера я получаю какую-то ошибку, которую я хотел бы обработать и сделать тост, в котором я говорю вам ввести правильное название города.
Api
interface ApixuWeatherApiService {
@GET("current.json")
fun getCurrentWeather(
@Query("q") location: String,
@Query("lang") languageCode: String = "en"
): Deferred<CurrentWeatherResponse>
@GET("forecast.json")
fun getFutureWeather(
@Query("q") location: String,
@Query("days")days: Int,
@Query("lang")languageCode: String = "en")
:Deferred<FutureWeatherResponse>
companion object {
operator fun invoke(
connectivityInterceptor: ConnectivityInterceptor
): ApixuWeatherApiService {
val requestInterceptor = Interceptor { chain ->
val url = chain.request()
.url()
.newBuilder()
.addQueryParameter("key", API_KEY)
.build()
val request = chain.request()
.newBuilder()
.url(url)
.build()
return@Interceptor chain.proceed(request)
}
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(requestInterceptor)
.addInterceptor(connectivityInterceptor)
.build()
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://api.weatherapi.com/v1/")
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApixuWeatherApiService::class.java)
}
}
}
Log FATAL EXCEPTION: main Process: com.ggenius.wtw, PID: 28498 retrofit2.HttpException: HTTP 400 at com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory$BodyCallAdapter$adapt$2.onResponse(CoroutineCallAdapterFactory.kt:104) at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:123) at okhttp3.RealCall$AsyncCall.execute(RealCall.java:153) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:919) LocationProviderImpl
const val USE_DEVICE_LOCATION = "USE_DEVICE_LOCATION"
const val CUSTOM_LOCATION = "CUSTOM_LOCATION"
class LocationProviderImpl(
private val fusedLocationProviderClient: FusedLocationProviderClient,
context: Context) : PreferenceProvider(context), LocationProvider {
private val appContext = context.applicationContext
override suspend fun hasLocationChanged(lastWeatherLocation: WeatherLocation): Boolean {
val deviceLocationChanged = try {
hasDeviceLocationChanged(lastWeatherLocation)
} catch (e: LocationPermissionNotGrantedException) {
false
}
return deviceLocationChanged || hasCustomLocationChanged(lastWeatherLocation)
}
override suspend fun getPreferredLocationString(): String {
if(isUsingDeviceLocation()) {
try {
val deviceLocation = getLastDeviceLocation()
?: return "${getCustomLocationName()}"
return "${deviceLocation.latitude},${deviceLocation.longitude}"
} catch (e: LocationPermissionNotGrantedException) {
return "${getCustomLocationName()}"
}
}
else {
return "${getCustomLocationName()}"
}
}
private suspend fun hasDeviceLocationChanged(lastWeatherLocation: WeatherLocation): Boolean {
if (!isUsingDeviceLocation())
return false
val deviceLocation = getLastDeviceLocation()
?: return false
// Comparing doubles cannot be done with "=="
val comparisonThreshold = 0.03
return Math.abs(deviceLocation.latitude - lastWeatherLocation.lat) > comparisonThreshold &&
Math.abs(deviceLocation.longitude - lastWeatherLocation.lon) > comparisonThreshold
}
private fun hasCustomLocationChanged(lastWeatherLocation: WeatherLocation): Boolean {
if (!isUsingDeviceLocation()) {
val customLocationName = getCustomLocationName()
return customLocationName != lastWeatherLocation.name
}
return false
}
private fun getCustomLocationName(): String? {
return preferences.getString(CUSTOM_LOCATION, null)
}
private fun isUsingDeviceLocation(): Boolean {
return preferences.getBoolean(USE_DEVICE_LOCATION, true)
}
@SuppressLint("MissingPermission")
private suspend fun getLastDeviceLocation(): Location? {
return (if (hasLocationPermission())
fusedLocationProviderClient.lastLocation.asDeferred()
else {
throw LocationPermissionNotGrantedException()
}).await()
}
private fun hasLocationPermission(): Boolean {
return ContextCompat.checkSelfPermission(appContext,
android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
}
Здесь использую ApiService
class WeatherNetworkDataSourceImpl(
private val apixuWeatherApiService: ApixuWeatherApiService
) : WeatherNetworkDataSource {
private val _downloadedCurrentWeather = MutableLiveData<CurrentWeatherResponse>()
override val downloadedCurrentWeather: LiveData<CurrentWeatherResponse>
get() = _downloadedCurrentWeather
override suspend fun fetchCurrentWeather(location: String, languageCode: String) {
try {
val fetchedCurrentWeather = apixuWeatherApiService
.getCurrentWeather(location,languageCode)
.await()
_downloadedCurrentWeather.postValue(fetchedCurrentWeather)
}
catch (e: Exception) {
Log.e("Connectivity", "UnCorrentCITY", e)
val pref = PreferenceManager.getDefaultSharedPreferences(this)
pref.edit().putString("CUSTOM_LOCATION", "London").apply()
}
}
private val _downloadedFutureWeather = MutableLiveData<FutureWeatherResponse>()
override val downloadedFutureWeather: LiveData<FutureWeatherResponse>
get() = _downloadedFutureWeather
override suspend fun fetchFutureWeather(
location: String,
languageCode: String
) {
try {
val fetchedFutureWeather = apixuWeatherApiService
.getFutureWeather(location, FORECAST_DAYS_COUNT, languageCode)
.await()
_downloadedFutureWeather.postValue(fetchedFutureWeather)
}
catch (e: NoConnectivityException) {
Log.e("Connectivity", "There is no internet connection.", e)
}
}
}