In this demo, you’ll learn more about the structure of the project. You’ll also learn how to check your network connectivity in the app.
Open the Starter project for Lesson 1 from the student materials repository. Once it syncs, change your project pane view to Project. It might be set to Android by default. The project view shows a more accurate representation of the structure you’re about to explore.
User
and MovieReview
models that will be
shown in the app. You’ll have all your network-related code in the networking package. For now, that package holds only MovieDiaryApi
, which has some method signatures already prepared for you.
The ui package contains all the UI-related code, further subpackaged by features in the app.
App
and MainActivity
. App
creates and provides access to SharedPreferences
, and MainActivity
is the entry point and a container for the whole app.
<application ..>
tag:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
The first permission lets your app access the internet in general. The second one lets you check the network state.
ConnectivityChecker
in the networking package. Add the following code to the class:
class ConnectivityChecker(
private val connectivityManager: ConnectivityManager?
)
ConnectivityManager
to get information about the network.
Now, create a function that will read the network’s capabilities. Add this code to the class:
class ConnectivityChecker(private val connectivityManager: ConnectivityManager?) {
fun hasNetworkConnection(): Boolean {
val network = connectivityManager?.activeNetwork ?: return false
val capabilities =
connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|| capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
|| capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
|| capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
}
}
connectivityManager
and read its capabilities. Then, you check if it’s
connected to Wi-Fi, ethernet, cellular data, or a VPN. If any of those connections exist, you return true
, meaning
that a user can make a network request.
LoginScreen
composable.
@Composable
fun LoginScreen(
movieDiaryApi: MovieDiaryApi,
connectivityChecker: ConnectivityChecker,
onLogin: (String) -> Unit,
onRegisterTapped: () -> Unit,
)
Button
composable and replace TODO: Add network check
with this code:
if (connectivityChecker.hasNetworkConnection()) {
TODO: Handle no network state
with the following:
else {
scaffoldState.snackbarHostState.showSnackbar("Check your network connection.")
}
}
This checks for a network connection every time a user presses the Login button. If the app’s not connected, a snackbar shows with an error. Otherwise, the program continues normally.
ConnectivityChecker
by adding the following property:
private val connectivityChecker by lazy { ConnectivityChecker(connectivityManager) }
LoginScreen
composable:
LoginScreen(
movieDiaryApi = movieApi,
connectivityChecker = connectivityChecker,
onLogin = { token ->
App.saveUserToken(token)
userLoggedIn = true
currentScreen = Screens.MOVIES
},
onRegisterTapped = { currentScreen = Screens.REGISTER }
)
RegisterScreen.kt
, like this:
@Composable
fun RegisterScreen(
movieDiaryApi: MovieDiaryApi,
connectivityChecker: ConnectivityChecker,
onUserRegistered: () -> Unit = {},
onLoginTapped: () -> Unit,
)
Scroll down to the button and replace it with the following code:
Button(onClick = {
focusManager.clearFocus()
screenScope.launch {
if (username.isNotBlank() && email.isNotBlank() && password.isNotBlank()) {
if (connectivityChecker.hasNetworkConnection()) {
movieDiaryApi.registerUser(
username,
email,
password
) { message, error ->
screenScope.launch {
if (error != null) {
scaffoldState.snackbarHostState.showSnackbar(error.message ?: "")
} else {
onUserRegistered()
}
}
}
} else {
scaffoldState.snackbarHostState.showSnackbar("Check your network connection.")
}
} else {
scaffoldState.snackbarHostState.showSnackbar("Please fill in all the fields.")
}
}
}) {
Text(text = "Register")
}
connectivityChecker
to RegisterScreen
:
RegisterScreen(
movieDiaryApi = movieApi,
connectivityChecker = connectivityChecker,
onUserRegistered = { currentScreen = Screens.LOGIN },
onLoginTapped = { currentScreen = Screens.LOGIN })
Run the app and turn on airplane mode. Add some input and click Login. You see an error message to check your connection.
Click the Register button and notice that the same happens if you try to register.
Soon, you’ll add code to register a user.