I am trying to implement a login feature in my Android app using Retrofit and ViewModel. The API works perfectly in Postman, but when called from my app, the request starts (as shown in the logs) but neither a response nor an error is received.
- API interface
data class LoginResponse( val status: String, val data: LoginData)data class LoginData( val token: String)data class LoginRequest( val email: String, val password: String)@POST("users/login")suspend fun loginUser(@Body request: LoginRequest): LoginResponse
- ViewModel
private val _isLoggedIn = MutableLiveData<Boolean>() val isLoggedIn: LiveData<Boolean> = _isLoggedInfun loginUser(email: String, password: String) { viewModelScope.launch { try { val loginRequest = LoginRequest(email, password) Log.d("login", "Starting API call: $loginRequest") val response = RetrofitInstance.UserApi.loginUser(loginRequest) // it seem to stop here? Log.d("login", "Response received: ${response.status}, Token: ${response.data.token}") saveToken(response.data.token) _isLoggedIn.postValue(true) } catch (e: HttpException) { Log.e("login", "HTTP error: ${e.code()}, ${e.message()}") _isLoggedIn.postValue(false) } catch (e: IOException) { Log.e("login", "Network error: ${e.localizedMessage}") _isLoggedIn.postValue(false) } catch (e: Exception) { Log.e("login", "Unexpected error: ${e.localizedMessage}") _isLoggedIn.postValue(false) } }}
Retrofit Instance
object RetrofitInstance { private const val BASE_URL = "https://860a-14-161-24-232.ngrok-free.app" private val client: OkHttpClient by lazy { OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }) .build() } val CourseApi: CourseApiService by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() .create(CourseApiService::class.java) } val UserApi: UserApiService by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() .create(UserApiService::class.java) }}
Logs
D/login: Starting API call: LoginRequest(email=abc@gmail.com, password=123456789) I/OkHttpClient: --> POST https://860a-14-161-24-232.ngrok-free.app/users/login
Usage
@Composablefun LoginScreen(navController: NavController, userAPIViewmodel: UserAPIViewModel) { // State to store user input var username by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } var errorMessage by remember { mutableStateOf("") } val isLoggedIn by userAPIViewmodel.isLoggedIn.observeAsState() fun login(){ userAPIViewmodel.loginUser(username, password) if(userAPIViewmodel.isLoggedIn.value == true){ navController.navigate(Routes.HomeScreen.route) }else if(userAPIViewmodel.isLoggedIn.value == false){ errorMessage = "Invalid username or password" } else{ errorMessage = "Something went wrong" } }}
• Notes:
The API works in Postman and returns the expected response.
I’m using OkHttp’s HttpLoggingInterceptor set to BODY for logging, but no additional details are shown.
The app is using a temporary ngrok URL for testing.
- Questions:
Why does the API call not complete in the app, even though it works in Postman?
How can I debug or fix this issue to ensure the response or error is properly handled?
I have tried to log everything but the log is minimal, the url is correct and i have tried everything for a whole day but did not work.
p/s: it does in fact can call the API, but super slow. How can i boost the performance of it when it take 251170 ms while Postman just take about 100ms.<-- 201 https://860a-14-161-24-232.ngrok-free.app/users/login (251170ms)