REST services

Server address

The first thing we need to think about is how the client will communicate with the server.

If the server is running on a separate machine, the client can communicate with it using that machine's server name or IP address. But if we're running the server on the same machine as an emulator, what IP address do we use?

You might think we'd use 127.0.0.1. The problem is that if we use that on an Android device, it refers to the Android device itself. We want to connect to the computer that's hosting that Android device.

Android defines 10.0.2.2 as the computer hosting the emulator. So our REST requests using this server and an emulator will look like http://10.0.2.2:8080/movie.

If instead, you're running your application on a separate device or another computer, you would use the IP address of that computer. For example, if the computer was at 192.168.1.157 and the android device was on the same network, you could use http://129.168.1.157:8080/movie

Depending on how your application works, the server address might be hardcoded or set as a user option. For debugging, you may want to have the server name be different. To do this, we can set up debug and release source sets that define different versions of the same types or functions.

These source sets are automatically defined; you just need to create the directories.

We set up our project as follows:

movie-rest/
    app/
        src/
            androidTest/...
            debug/java/com/androidbyexample/compose/movies/
                ServerInfo.kt
            main/...
            release/java/com/androidbyexample/compose/movies/
                ServerInfo.kt
            test/...

This allows us to define the contents of ServerInfo.kt differently if used for a debug build vs a release build. When building for debug, the code under the app/src/main/debug directory will be used. When building for release, the code under the app/src/main/release will be used.

We'll use this for a simple getServerAddress() function:

show in full file app/src/debug/java/com/androidbyexample/compose/movies/ServerInfo.kt
package com.androidbyexample.compose.movies

fun getServerAddress() = "http://10.0.2.2:8080"
show in full file app/src/release/java/com/androidbyexample/compose/movies/ServerInfo.kt
package com.androidbyexample.compose.movies

fun getServerAddress() = "http://real.server.address:8080"

All code changes

ADDED: app/src/debug/java/com/androidbyexample/compose/movies/ServerInfo.kt
package com.androidbyexample.compose.movies

fun getServerAddress() = "http://10.0.2.2:8080"
CHANGED: app/src/main/java/com/androidbyexample/compose/movies/MainActivity.kt
package com.androidbyexample.compose.movies

import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import com.androidbyexample.compose.movies.screens.MovieDisplay
import com.androidbyexample.compose.movies.screens.MovieList
import com.androidbyexample.compose.movies.screens.Ui
import com.androidbyexample.compose.movies.ui.theme.MoviesTheme

const val MOVIE_ID_EXTRA = "movieId"
class MainActivity : ComponentActivity() {
    private val viewModel by viewModels<MovieViewModel> { MovieViewModel.Factory }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        intent.handleMovieId()

        enableEdgeToEdge()
        setContent {
            MoviesTheme {
                Ui(
                    viewModel = viewModel,
                    modifier = Modifier.fillMaxSize()
                ) {
                    finish()
                }
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        intent.handleMovieId()
    }

    private fun Intent.handleMovieId() {
        val movieId = extras?.getString(MOVIE_ID_EXTRA)
        if (movieId != null) {
            viewModel.setScreens(MovieList, MovieDisplay(movieId))
        }
    }
}
ADDED: app/src/release/java/com/androidbyexample/compose/movies/ServerInfo.kt
package com.androidbyexample.compose.movies

fun getServerAddress() = "http://real.server.address:8080"