Android Compose Base is a boilerplate project created by Rootstrap for new projects using Kotlin and Jetpack Compose. The main objective is helping any new projects jump-start into feature development by providing a solid foundation.
You can use this open-source project as a template of your new Android projects. Steps:
-
Clone: Clone the repository to your local machine.
-
Build with Android Studio: Open the project in Android Studio and build it.
Use Example module as an example of how to setup your project (see the login/sign up examples).
- Minimum SDK level 24
- Jetpack Compose for UI
- Navigation Compose for in-app navigation
- ViewModel from Architecture Components
- Retrofit for network requests
- Coil for image loading
- Koin for dependency injection
The app uses MVVM architecture and Clean Architecture principles with a separation of concerns between:
- Presentation Layer: ViewModels and Compose UI. ViewModels retrieve data from use-cases and expose it to Compose UI.
- Domain Layer: Models
- Use-cases: Business logic
- Data Layer: Repositories, network, local data sources
We use the ErrorHandler
class that extends AbstractCoroutineContextElement
and implements CoroutineExceptionHandler
to handle errors in coroutines.
To listen to those errors we use the ErrorNotifier
singleton that exposes a flow of errors. Usually you will only need to listen to it in your app's main activity. In this template it is being listened in the AppActivity
class
To check lint issues, use ktlintCheck
and ktlintFormat
.
UI package contains a base ViewModel, BaseViewModel
, designed for use in Android applications developed in Kotlin.
It extends ViewModel
and is designed to be used with Jetpack Compose UI components.
This base ViewModel facilitates state and navigation event management within Android UI components.
- State Management: Utilizes
MutableStateFlow
for managing UI state, providing a thread-safe way to observe and update the UI state reactively. - Navigation Events: Uses a
Channel
to handle one-time navigation events, ensuring that events are handled once and state management is decoupled from event handling. - Ensure your UI state classes implement the UiState interface provided in this package for type safety.
- Add nav config and deep link example with a guide for it. Issue
Note: To add deep links:
Add the .well-known/assetlinks.json
file to your server to register the app
Check the documentation: Docs
To test deep link locally call with adb:
adb shell am start -a android.intent.action.VIEW \
-c android.intent.category.BROWSABLE \
-d "http://awesomewebpage.com"
Note: Once you upload the app to Google Play Store you will find the .well-known/assetlinks.json file config in the signature menu
To verify the assetlinks.json was registered with the app use:
- adb shell pm verify-app-links --re-verify PACKAGE_NAME'
- adb shell pm get-app-links PACKAGE_NAME
When verified, you should see the following output:
com.rs.androidcomposebase
ID: 01234567-89ab-cdef-0123-456789abcdef
Signatures: [***]
Domain verification state:
awesomewebpage.com: verified
Navigation: Example of nav with arguments:
composable(
route = NavRoutes.BusinessDetails.route,
arguments = listOf(navArgument("id") { type = NavType.StringType })
) { backStackEntry ->
backStackEntry.arguments?.getString("id")?.run {
BusinessDetailPage(this)
} ?: run {
ErrorPage(message = "404")
}
}
Example of calling a route with arguments:
AppData.mainNavController.navigate(
NavRoutes.BusinessDetailPage.withArg(
business.id
)
)
To set deep links:
composable(
route = NavRoutes.BusinessDetailPage.route,
arguments = listOf(navArgument("id") { type = NavType.StringType }),
// URI is your page deeplink in this case "awesomewebpage.com",
// get your uri from your desired configuration: const var, env, gradle, etc..
deepLinks = listOf(navDeepLink { uriPattern = "https://awesomewebpage.com/business/{id}"}),
) { backStackEntry ->
backStackEntry.arguments?.getString("id")?.run {
BusinessDetailPage(this)
} ?: run {
ErrorPage(message = "404")
}
}