├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── themes.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.webp
│ │ │ └── ic_launcher_round.webp
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── values-night
│ │ │ └── themes.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ └── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ └── template
│ │ │ ├── theme
│ │ │ ├── Color.kt
│ │ │ ├── Shape.kt
│ │ │ ├── Type.kt
│ │ │ └── Theme.kt
│ │ │ └── MainActivity.kt
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle.kts
├── git-hooks
├── pre-push.sh
└── pre-commit.sh
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── libs.versions.toml
├── Gemfile
├── .gitignore
├── .editorconfig
├── .github
├── pull_request_template.md
└── workflows
│ ├── android_ui_tests.yml
│ ├── android_build.yml
│ └── template_change_test.yml
├── settings.gradle.kts
├── documentation
├── GitHubActions.md
├── GitHooks.md
└── StaticAnalysis.md
├── Dangerfile
├── gradle.properties
├── gradlew.bat
├── README.md
├── gradlew
└── config
└── detekt
└── detekt.yml
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/git-hooks/pre-push.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "Running static analysis."
4 |
5 | ./gradlew lintKotlin
6 | ./gradlew detektAll
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4 |
5 | gem "danger"
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aslansari/android-app-template/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 | .cxx
10 | local.properties
11 | build/
12 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*.{kt,kts}]
4 | max_line_length = 140
5 | indent_size = 4
6 | insert_final_newline = true
7 | ij_kotlin_allow_trailing_comma = true
8 | ij_kotlin_allow_trailing_comma_on_call_site = true
9 | ktlint_disabled_rules = filename
10 |
--------------------------------------------------------------------------------
/app/src/main/java/template/theme/Color.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("MagicNumber")
2 |
3 | package template.theme
4 |
5 | import androidx.compose.ui.graphics.Color
6 |
7 | val Purple200 = Color(0xFFBB86FC)
8 | val Purple500 = Color(0xFF6200EE)
9 | val Teal200 = Color(0xFF03DAC5)
10 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Oct 10 21:53:17 EDT 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/template/theme/Shape.kt:
--------------------------------------------------------------------------------
1 | package template.theme
2 |
3 | import androidx.compose.foundation.shape.RoundedCornerShape
4 | import androidx.compose.material3.Shapes
5 | import androidx.compose.ui.unit.dp
6 |
7 | val Shapes = Shapes(
8 | small = RoundedCornerShape(4.dp),
9 | medium = RoundedCornerShape(4.dp),
10 | large = RoundedCornerShape(0.dp),
11 | )
12 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Summary
2 |
3 |
4 |
5 | ## How It Was Tested
6 |
7 |
8 |
9 | ## Screenshot/Gif
10 |
11 |
12 |
13 |
14 |
15 | Screenshot Name
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | includeBuild("build-logic")
3 | repositories {
4 | google()
5 | mavenCentral()
6 | gradlePluginPortal()
7 | maven(url = "https://plugins.gradle.org/m2/")
8 | }
9 | }
10 | dependencyResolutionManagement {
11 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
12 | repositories {
13 | google()
14 | mavenCentral()
15 | }
16 | }
17 | rootProject.name = "template"
18 | include(":app")
19 |
--------------------------------------------------------------------------------
/app/src/main/java/template/theme/Type.kt:
--------------------------------------------------------------------------------
1 | package template.theme
2 |
3 | import androidx.compose.material3.Typography
4 | import androidx.compose.ui.text.TextStyle
5 | import androidx.compose.ui.text.font.FontFamily
6 | import androidx.compose.ui.text.font.FontWeight
7 | import androidx.compose.ui.unit.sp
8 |
9 | // Set of Material typography styles to start with
10 | val Typography = Typography(
11 | bodyMedium = TextStyle(
12 | fontFamily = FontFamily.Default,
13 | fontWeight = FontWeight.Normal,
14 | fontSize = 16.sp,
15 | ),
16 | )
17 |
--------------------------------------------------------------------------------
/git-hooks/pre-commit.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ######## KTLINT-GRADLE HOOK START ########
4 |
5 | CHANGED_FILES="$(git --no-pager diff --name-status --no-color --cached | awk '$1 != "D" && $2 ~ /\.kts|\.kt/ { print $2}')"
6 |
7 | if [ -z "$CHANGED_FILES" ]; then
8 | echo "No Kotlin staged files."
9 | exit 0
10 | fi;
11 |
12 | echo "Running ktlint over these files:"
13 | echo "$CHANGED_FILES"
14 |
15 | ./gradlew --quiet formatKotlin -PinternalKtlintGitFilter="$CHANGED_FILES"
16 |
17 | echo "Completed ktlint run."
18 |
19 | echo "$CHANGED_FILES" | while read -r file; do
20 | if [ -f $file ]; then
21 | git add $file
22 | fi
23 | done
24 |
25 | echo "Completed ktlint hook."
26 | ######## KTLINT-GRADLE HOOK END ########
--------------------------------------------------------------------------------
/documentation/GitHubActions.md:
--------------------------------------------------------------------------------
1 | # GitHub Actions
2 |
3 | This project has [GitHub Actions](https://github.com/features/actions) workflows to validate our code for us automatically. The project currently uses two workflows.
4 |
5 | ## Android Build
6 |
7 | The [Android Build](/.github/workflows/android_build.yml) workflow automates the core checks for the repository: compile, unit tests, lint checks. This is set to run on every push.
8 |
9 | ## Android UI Tests
10 |
11 | The [Android UI Tests](/.github/workflows/android_ui_tests.yml) is a separate workflow that is set to only run on pull request. This is because UI tests are slow and take up a lot of resources, so we only want to validate them when we're ready to merge changes into our base branch.
12 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.kts.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/.github/workflows/android_ui_tests.yml:
--------------------------------------------------------------------------------
1 | name: Android UI Tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - develop
7 | pull_request:
8 |
9 | jobs:
10 | android-test:
11 | runs-on: macos-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 |
16 | - name: Set Up JDK
17 | uses: actions/setup-java@v3
18 | with:
19 | distribution: 'zulu'
20 | java-version: 17
21 |
22 | - name: Setup Gradle
23 | uses: gradle/gradle-build-action@v2
24 | with:
25 | # Only write to the cache for builds on the 'development' branch
26 | cache-read-only: ${{ github.ref != 'refs/heads/development' }}
27 |
28 | - name: Run Tests
29 | uses: reactivecircus/android-emulator-runner@v2
30 | with:
31 | api-level: 29
32 | script: ./gradlew app:connectedCheck
--------------------------------------------------------------------------------
/.github/workflows/android_build.yml:
--------------------------------------------------------------------------------
1 | name: Android Build
2 |
3 | on:
4 | push:
5 | branches:
6 | - develop
7 | - main
8 | pull_request:
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v3
15 |
16 | - name: Set Up JDK
17 | uses: actions/setup-java@v3
18 | with:
19 | distribution: 'zulu'
20 | java-version: 17
21 |
22 | - name: Setup Gradle
23 | uses: gradle/gradle-build-action@v2
24 | with:
25 | # Only write to the cache for builds on the 'development' branch
26 | cache-read-only: ${{ github.ref != 'refs/heads/development' }}
27 |
28 | - name: Build Project
29 | run: ./gradlew assemble
30 |
31 | - name: Run Tests
32 | run: ./gradlew test
33 |
34 | - name: Lint Checks
35 | run: ./gradlew detektAll lintKotlin lint
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/documentation/GitHooks.md:
--------------------------------------------------------------------------------
1 | # Git Hooks
2 |
3 | This project has some Git hooks included inside the [git-hooks](/git-hooks) folder. These hooks can be installed automatically via the Gradle commands `./gradlew copyGitHooks` and `./gradlew installGitHooks`. You can find these commands in [this Gradle file](/buildscripts/githooks.gradle), but it's also good to know that the hooks are installed automatically just by running a `clean` task. Thanks to [Sebastiano's blog post](https://blog.sebastiano.dev/ooga-chaka-git-hooks-to-enforce-code-quality/) for that inspiration.
4 |
5 | ## Pre-Commit
6 |
7 | There is a [pre-commit](/git-hooks/pre-commit.sh) hook that will automatically run Ktlint formatting over any modified Kotlin files. This way you can just commit your code and trust that formatting happens behind the scenes, without having to consciously worry about it.
8 |
9 | ## Pre-Push
10 |
11 | There is a [pre-push](/git-hooks/pre-push.sh) hook that will run static analysis checks before any code is pushed up to the remote repository. This way, if you have any code smells, you can be alerted right away without waiting for the GitHub Actions to fail.
--------------------------------------------------------------------------------
/Dangerfile:
--------------------------------------------------------------------------------
1 | message "Thanks @#{github.pr_author}!"
2 |
3 | if github.pr_body.length == 0
4 | fail "Please provide a summary in the Pull Request description."
5 | end
6 |
7 | if git.lines_of_code > 500
8 | warn "Please consider breaking up this pull request."
9 | end
10 |
11 | if github.pr_labels.empty?
12 | warn "Please add labels to this PR."
13 | end
14 |
15 | if git.deletions > git.insertions
16 | message "🎉 Code Cleanup!"
17 | end
18 |
19 | # Notify of outdated dependencies
20 | dependencyUpdatesHeader = "The following dependencies have later milestone versions:"
21 | dependencyReportsFile = "build/dependencyUpdates/report.txt"
22 |
23 | # Due to the formatting of this output file, we first check if there are any dependencies
24 | # by looking for a `->` arrow, then we check for the relevant headers. We do this to handle a case
25 | # where there are no app dependencies but there are Gradle dependencies.
26 | hasDependencyUpdatesHeader = File.readlines(dependencyReportsFile).grep(/#{dependencyUpdatesHeader}/).any?
27 |
28 | if hasDependencyUpdatesHeader
29 | file = File.open(dependencyReportsFile, "rb").read
30 | index = file.index(dependencyUpdatesHeader)
31 | message file.slice(index..-1)
32 | end
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx6g -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/template/theme/Theme.kt:
--------------------------------------------------------------------------------
1 | package template.theme
2 |
3 | import android.annotation.TargetApi
4 | import android.os.Build
5 | import androidx.compose.foundation.isSystemInDarkTheme
6 | import androidx.compose.material3.MaterialTheme
7 | import androidx.compose.material3.darkColorScheme
8 | import androidx.compose.material3.dynamicDarkColorScheme
9 | import androidx.compose.material3.dynamicLightColorScheme
10 | import androidx.compose.material3.lightColorScheme
11 | import androidx.compose.runtime.Composable
12 | import androidx.compose.ui.platform.LocalContext
13 |
14 | private val darkColorScheme = darkColorScheme(
15 | primary = Purple200,
16 | secondary = Teal200,
17 | )
18 |
19 | private val lightColorScheme = lightColorScheme(
20 | primary = Purple500,
21 | secondary = Teal200,
22 | )
23 |
24 | @Composable
25 | @TargetApi(Build.VERSION_CODES.S)
26 | fun TemplateTheme(
27 | darkTheme: Boolean = isSystemInDarkTheme(),
28 | dynamicTheme: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S,
29 | content: @Composable () -> Unit,
30 | ) {
31 | val colorScheme = when {
32 | dynamicTheme && darkTheme -> dynamicDarkColorScheme(LocalContext.current)
33 | dynamicTheme && !darkTheme -> dynamicLightColorScheme(LocalContext.current)
34 | darkTheme -> darkColorScheme
35 | else -> lightColorScheme
36 | }
37 |
38 | MaterialTheme(
39 | colorScheme = colorScheme,
40 | typography = Typography,
41 | shapes = Shapes,
42 | content = content,
43 | )
44 | }
45 |
--------------------------------------------------------------------------------
/documentation/StaticAnalysis.md:
--------------------------------------------------------------------------------
1 | # Static Analysis
2 |
3 | This project leverages static analysis to ensure that the codebase meets certain standards that can be verified through automation. Two of these libraries are Detekt and Ktlint.
4 |
5 | ## Detekt
6 |
7 | [Detekt](https://github.com/detekt/detekt) is a static analysis tool that checks for code smells. Examples include magic numbers, complicated conditionals, long methods, long parameter lists, and so much more. It is highly configurable, and if you choose to turn off any checks or customize thresholds you can do so in the [config file](/config/detekt/detekt.yml).
8 |
9 | To run a detekt validation, use the one of the following Gradle commands:
10 |
11 | ```
12 | ./gradlew detekt # Runs over each module synchronously
13 | ./gradlew detektAll # Runs over each module in parallel.
14 | ```
15 |
16 | ## Ktlint
17 |
18 | [Ktlint](https://github.com/pinterest/ktlint) is a static analysis tool from Pinterest that prevents bike shedding when it comes to code formatting. It also comes with a Gradle task to automatically format your entire codebase, if it can. The benefit of a tool like this is to ensure everyone on the team will have code formatted the same way, and there's no debating around white spaces, indentation, imports, etc.
19 |
20 | We use the [Kotlinter](https://github.com/jeremymailen/kotlinter-gradle) Ktlint Gradle plugin in this project.
21 |
22 | The following Gradle commands can be helpful:
23 |
24 | ```
25 | // Will format the codebase
26 | ./gradlew formatKotlin
27 |
28 | // Will check if everything is formatted correctly
29 | ./gradlew lintKotlin
30 | ```
--------------------------------------------------------------------------------
/.github/workflows/template_change_test.yml:
--------------------------------------------------------------------------------
1 | name: Rename Template
2 |
3 | on: pull_request
4 |
5 | jobs:
6 | rename-template:
7 | strategy:
8 | matrix:
9 | useHiltDependencies: [true, false]
10 | useRoomDependencies: [true, false]
11 | useRetrofitDependencies: [true, false]
12 |
13 | runs-on: ubuntu-latest
14 | steps:
15 | - uses: actions/checkout@v3
16 |
17 | - name: Set useHiltDependencies
18 | uses: jacobtomlinson/gha-find-replace@v3
19 | with:
20 | find: "useHiltDependencies[ ]+ : true"
21 | replace: "useHiltDependencies : ${{ matrix.useHiltDependencies }}"
22 | include: "**setup.gradle"
23 |
24 | - name: Set useRoomDependencies
25 | uses: jacobtomlinson/gha-find-replace@v3
26 | with:
27 | find: "useRoomDependencies[ ]+ : true"
28 | replace: "useRoomDependencies : ${{ matrix.useRoomDependencies }}"
29 | include: "**setup.gradle"
30 |
31 | - name: Set useRetrofitDependencies
32 | uses: jacobtomlinson/gha-find-replace@v3
33 | with:
34 | find: "useRetrofitDependencies[ ]+ : true"
35 | replace: "useRetrofitDependencies : ${{ matrix.useRetrofitDependencies }}"
36 | include: "**setup.gradle"
37 |
38 | - name: Set Up JDK
39 | uses: actions/setup-java@v3
40 | with:
41 | distribution: 'zulu'
42 | java-version: 17
43 |
44 | - name: Setup Gradle
45 | uses: gradle/gradle-build-action@v2
46 |
47 | - name: Rename
48 | run: ./gradlew renameTemplate
49 |
50 | - name: Build
51 | run: ./gradlew build
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | alias(libs.plugins.convention.android.application)
3 | alias(libs.plugins.convention.android.application.compose)
4 | alias(libs.plugins.convention.android.room)
5 | alias(libs.plugins.convention.android.hilt)
6 | alias(libs.plugins.convention.kotlinter)
7 | }
8 |
9 | android {
10 |
11 | defaultConfig {
12 | applicationId = "template.app.id"
13 | versionCode = 1
14 | versionName = "1.0"
15 |
16 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
17 | vectorDrawables {
18 | useSupportLibrary = true
19 | }
20 | }
21 |
22 | buildTypes {
23 | release {
24 | isMinifyEnabled = false
25 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
26 | }
27 | }
28 |
29 | packaging {
30 | resources {
31 | excludes += "/META-INF/{AL2.0,LGPL2.1}"
32 | }
33 | }
34 |
35 | namespace = "template"
36 | }
37 |
38 | dependencies {
39 |
40 | implementation(libs.androidx.activity.compose)
41 | implementation(libs.androidx.appcompat)
42 | implementation(libs.androidx.core.ktx)
43 | implementation(libs.androidx.lifecycle.runtime.ktx)
44 | implementation(libs.android.material)
45 | implementation(libs.compose.ui)
46 | implementation(libs.compose.material)
47 | implementation(libs.compose.ui.tooling)
48 | implementation(libs.moshi.kotlin.core)
49 | implementation(libs.retrofit)
50 | implementation(libs.retrofit.converter.moshi)
51 |
52 | testImplementation(libs.junit4)
53 |
54 | androidTestImplementation(libs.androidx.test.junit)
55 | androidTestImplementation(libs.androidx.test.espresso.core)
56 | androidTestImplementation(libs.compose.ui.test.junit)
57 | androidTestImplementation(libs.hilt.android.testing)
58 |
59 | debugImplementation(libs.compose.ui.test.manifest)
60 | debugImplementation(libs.compose.ui.tooling)
61 | debugImplementation(libs.leakcanary)
62 |
63 | ksp(libs.moshi.kotlin.codegen)
64 | }
65 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/app/src/main/java/template/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package template
2 |
3 | import android.os.Bundle
4 | import androidx.activity.ComponentActivity
5 | import androidx.activity.SystemBarStyle
6 | import androidx.activity.compose.setContent
7 | import androidx.activity.enableEdgeToEdge
8 | import androidx.compose.foundation.isSystemInDarkTheme
9 | import androidx.compose.foundation.layout.Column
10 | import androidx.compose.foundation.layout.WindowInsets
11 | import androidx.compose.foundation.layout.fillMaxSize
12 | import androidx.compose.foundation.layout.systemBars
13 | import androidx.compose.foundation.layout.windowInsetsPadding
14 | import androidx.compose.material3.Surface
15 | import androidx.compose.material3.Text
16 | import androidx.compose.runtime.Composable
17 | import androidx.compose.runtime.DisposableEffect
18 | import androidx.compose.ui.Modifier
19 | import template.theme.TemplateTheme
20 |
21 | class MainActivity : ComponentActivity() {
22 | override fun onCreate(savedInstanceState: Bundle?) {
23 | super.onCreate(savedInstanceState)
24 |
25 | enableEdgeToEdge()
26 |
27 | setContent {
28 | val darkTheme = isSystemInDarkTheme()
29 |
30 | SystemBarStyleEffect(darkTheme = darkTheme)
31 |
32 | TemplateTheme {
33 | Surface {
34 | Column(
35 | modifier = Modifier
36 | .fillMaxSize()
37 | .windowInsetsPadding(WindowInsets.systemBars),
38 | ) {
39 | Greeting("Android")
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
46 | /**
47 | * Update the edge to edge configuration to match the theme
48 | * This is the same parameters as the default enableEdgeToEdge call, but we manually
49 | * resolve whether or not to show dark theme using uiState, since it can be different
50 | * than the configuration's dark theme value based on the user preference.
51 | */
52 | @Composable
53 | private fun SystemBarStyleEffect(darkTheme: Boolean) {
54 | DisposableEffect(darkTheme) {
55 | enableEdgeToEdge(
56 | statusBarStyle = SystemBarStyle.auto(
57 | android.graphics.Color.TRANSPARENT,
58 | android.graphics.Color.TRANSPARENT,
59 | ) { darkTheme },
60 | navigationBarStyle = SystemBarStyle.auto(
61 | lightScrim,
62 | darkScrim,
63 | ) { darkTheme },
64 | )
65 | onDispose {}
66 | }
67 | }
68 | }
69 |
70 | @Composable
71 | fun Greeting(name: String) {
72 | Text(text = "Hello $name!")
73 | }
74 |
75 | /**
76 | * The default light scrim, as defined by androidx and the platform:
77 | * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt;l=35-38;drc=27e7d52e8604a080133e8b842db10c89b4482598
78 | */
79 | @Suppress("MagicNumber")
80 | private val lightScrim = android.graphics.Color.argb(0xe6, 0xFF, 0xFF, 0xFF)
81 |
82 | /**
83 | * The default dark scrim, as defined by androidx and the platform:
84 | * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt;l=40-44;drc=27e7d52e8604a080133e8b842db10c89b4482598
85 | */
86 | @Suppress("MagicNumber")
87 | private val darkScrim = android.graphics.Color.argb(0x80, 0x1b, 0x1b, 0x1b)
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android App Template
2 |
3 | This GitHub template repository serves as a starting point for developing Android applications.
4 | I've started this Android application template using [Adam](https://github.com/AdamMc331)'s template.
5 | Along with the existing tools, I've added some features that align with my specific needs. These enhancements aim to make the development process smoother and improve the app's functionality. However, I'm open to suggestions and improvements. If you think there are other important elements to include or have recommendations for modifying the current setup, please share your thoughts. Your input is highly appreciated.
6 | Note that, since Adam did a really good job with the documentation, I left it mostly unchanged.
7 |
8 | ## Why This Template?
9 |
10 | The purpose of this template is to avoid any opinions on writing code. The developers should have the freedom to choose their own architecture, third party dependencies, package structure, and more.
11 |
12 | This template _is_ opinionated about developer tooling. Dependency management is configured, git hooks are defined, code formatting and static analysis are all there, and it even has pull request templates. The purpose of this repo is to help you get started building your next project with confidence in your code, and not telling you how to write it.
13 |
14 | ## Walkthrough
15 |
16 | If you'd like a video walk through of this template and all it has to offer, you can find that on YouTube.
17 |
18 | https://youtu.be/E0iMUWJn76E
19 |
20 | ## Using This Template
21 |
22 | To use this template in your own project, click the "Use this template" button at the top right of the repository. Once you do, a repository will be created for your account that you can clone and use on your device.
23 |
24 | To setup this repository to your needs, open the [setup.gradle](buildscripts/setup.gradle) file
25 | and tweak the `renameConfig` block to your needs. After that, you can run the `renameTemplate`
26 | gradle task to have the app module's package name and relevant strings replaced.
27 |
28 | ## What's Included
29 |
30 | A number of third party dependencies are included in this template. They are also documented inside the [documentation folder](/documentation). The files inside this documentation folder are written in such a way that you can keep them in your real project, to let team members read up on why dependencies are included and how they work.
31 |
32 | The dependencies in the template include:
33 |
34 | * [Ktlint](/documentation/StaticAnalysis.md) for formatting.
35 | * [Detekt](/documentation/StaticAnalysis.md) for code smells.
36 | * [Git Hooks](/documentation/GitHooks.md) for automatically perform static analysis checks.
37 | * [GitHub Actions](/documentation/GitHubActions.md) for running continuous integration and ensuring code quality with every PR.
38 | * [LeakCanary](https://square.github.io/leakcanary/) for detecting memory leaks.
39 | * [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) dependencies, which can be removed via setup.gradle if necessary.
40 | * [Room](https://developer.android.com/training/data-storage/room) dependencies, which can be removed via setup.gradle if necessary.
41 |
42 | ### Templates
43 |
44 | There are also templates within this template. This repo comes shipped with a [Pull Request Template](/.github/pull_request_template.md) that will help you and your team write organized and detailed pull request descriptions.
45 |
46 | ## Dependency Setup
47 |
48 | You may notice that dependencies are set up in a very specific way. Each of the tools has its own Gradle file in the [buildscripts folder](/buildscripts). This is by design so that if you chose to have a multi module project, these dependencies can easily be shared between them. This is already configured inside our root `build.gradle.kts` file, by applying to each sub project:
49 |
50 | ```groovy
51 | subprojects {
52 | apply from: "../buildscripts/versionsplugin.gradle"
53 | }
54 | ```
55 |
56 | In addition, all of the app module dependencies are defined using a gradle version catalog, found in this [toml](gradle/libs.versions.toml) file.
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradle/libs.versions.toml:
--------------------------------------------------------------------------------
1 | [versions]
2 | # Project
3 | minSdk = "21"
4 | compile-sdk = "34"
5 | compose-compiler = "1.5.7"
6 | kotlin = "1.9.21"
7 |
8 | # Plugins
9 | android-gradle-plugin = "8.2.1"
10 | com-android-test = "8.2.1"
11 | firebase-crashlytics-plugin = "2.9.9"
12 | gms-plugin = "4.4.1"
13 | ksp-plugin = "1.9.21-1.0.16"
14 | dagger-plugin = "2.51"
15 | detekt-plugin = "1.22.0"
16 | kotlinter-plugin = "3.14.0"
17 |
18 | # Libraries
19 | accompanist = "0.32.0"
20 | andrdoid-desugar-jdk-libs = "2.0.4"
21 | androidx-activity = "1.8.2"
22 | androidx-appcompat = "1.6.1"
23 | androidx-browser = "1.4.0"
24 | androidx-core = "1.9.0"
25 | androidx-splashscreen = "1.0.0"
26 | androidx-datastore = "1.0.0"
27 | androidx-espresso = "3.5.0"
28 | androidx-lifecycle = "2.6.0-alpha05"
29 | androidx-test = "1.1.5"
30 | compose-bom = "2024.03.00"
31 | compose-material3 = "1.1.0-alpha06"
32 | compose-runtime-tracing = "1.0.0-alpha01"
33 | hilt-navigation-compose = "1.0.0"
34 | firebaseBom = "31.2.0"
35 | espresso = "3.5.1"
36 | junit = "4.13.2"
37 | ktx-core = "1.12.0"
38 | leakCanary = "2.10"
39 | lifecycle = "2.7.0"
40 | material = "1.11.0"
41 | moshi = "1.15.0"
42 | retrofit = "2.9.0"
43 | room = "2.6.1"
44 |
45 | [libraries]
46 | accompanist-permissions = { group = "com.google.accompanist", name = "accompanist-permissions", version.ref = "accompanist" }
47 | android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "andrdoid-desugar-jdk-libs" }
48 | android-material = { group = "com.google.android.material", name = "material", version.ref = "material" }
49 | androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidx-activity" }
50 | androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktx-core" }
51 | androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
52 | androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" }
53 | androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
54 | androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
55 | androidx-room-paging = { group = "androidx.room", name = "room-paging", version.ref = "room" }
56 | androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
57 | androidx-room-testing = { group = "androidx.room", name = "room-testing", version.ref = "room" }
58 | androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" }
59 | androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test" }
60 | compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
61 | compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" }
62 | compose-material = { group = "androidx.compose.material3", name = "material3" }
63 | compose-ui = { group = "androidx.compose.ui", name = "ui" }
64 | compose-ui-test-junit = { group = "androidx.compose.ui", name = "ui-test-junit4" }
65 | compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
66 | compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
67 | compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
68 | compose-ui-util = { group = "androidx.compose.ui", name = "ui-util" }
69 | hilt-android-core = { module = "com.google.dagger:hilt-android", version.ref = "dagger-plugin" }
70 | hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "dagger-plugin" }
71 | hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "dagger-plugin" }
72 | hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "dagger-plugin" }
73 | junit4 = { module = "junit:junit", version.ref = "junit" }
74 | leakcanary = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakCanary" }
75 | moshi-kotlin-core = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
76 | moshi-kotlin-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
77 | retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
78 | retrofit-converter-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
79 |
80 | # Dependencies of the included build-logic
81 | android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "android-gradle-plugin" }
82 | kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
83 | firebase-crashlytics-gradlePlugin = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "firebase-crashlytics-plugin" }
84 | ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp-plugin" }
85 |
86 | [plugins]
87 | com-android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" }
88 | com-android-library = { id = "com.android.library", version.ref = "android-gradle-plugin" }
89 | org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
90 | dagger-hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "dagger-plugin" }
91 | google-services = { id = "com.google.gms.google-services", version.ref = "gms-plugin" }
92 | firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics-plugin" }
93 | com-android-test = { id = "com.android.test", version.ref = "com-android-test" }
94 | detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt-plugin" }
95 | kotlinter = { id = "org.jmailen.kotlinter", version.ref = "kotlinter-plugin" }
96 | ksp = { id = "com.google.devtools.ksp", version.ref = "ksp-plugin" }
97 |
98 | convention-android-application = { id = "convention.android.application", version = "unspecified" }
99 | convention-android-application-compose = { id = "convention.android.application.compose", version = "unspecified" }
100 | convention-android-application-firebase = { id = "convention.android.application.firebase", version = "unspecified" }
101 | convention-android-application-flavors = { id = "convention.android.application.flavors", version = "unspecified" }
102 | convention-android-application-jacoco = { id = "convention.android.application.jacoco", version = "unspecified" }
103 | convention-android-feature = { id = "convention.android.feature", version = "unspecified" }
104 | convention-android-hilt = { id = "convention.android.hilt", version = "unspecified" }
105 | convention-android-library = { id = "convention.android.library", version = "unspecified" }
106 | convention-android-library-compose = { id = "convention.android.library.compose", version = "unspecified" }
107 | convention-android-library-jacoco = { id = "convention.android.library.jacoco", version = "unspecified" }
108 | convention-android-lint = { id = "convention.android.lint", version = "unspecified" }
109 | convention-android-room = { id = "convention.android.room", version = "unspecified" }
110 | convention-android-test = { id = "convention.android.test", version = "unspecified" }
111 | convention-jvm-library = { id = "convention.jvm.library", version = "unspecified" }
112 | convention-kotlinter = { id = "convention.kotlinter", version = "unspecified" }
113 |
--------------------------------------------------------------------------------
/config/detekt/detekt.yml:
--------------------------------------------------------------------------------
1 | build:
2 | maxIssues: 0
3 | excludeCorrectable: false
4 | weights:
5 | # complexity: 2
6 | # LongParameterList: 1
7 | # style: 1
8 | # comments: 1
9 |
10 | config:
11 | validation: true
12 | warningsAsErrors: false
13 | # when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
14 | excludes: ''
15 |
16 | processors:
17 | active: true
18 | exclude:
19 | - 'DetektProgressListener'
20 | # - 'KtFileCountProcessor'
21 | # - 'PackageCountProcessor'
22 | # - 'ClassCountProcessor'
23 | # - 'FunctionCountProcessor'
24 | # - 'PropertyCountProcessor'
25 | # - 'ProjectComplexityProcessor'
26 | # - 'ProjectCognitiveComplexityProcessor'
27 | # - 'ProjectLLOCProcessor'
28 | # - 'ProjectCLOCProcessor'
29 | # - 'ProjectLOCProcessor'
30 | # - 'ProjectSLOCProcessor'
31 | # - 'LicenseHeaderLoaderExtension'
32 |
33 | console-reports:
34 | active: true
35 | exclude:
36 | - 'ProjectStatisticsReport'
37 | - 'ComplexityReport'
38 | - 'NotificationReport'
39 | # - 'FindingsReport'
40 | - 'FileBasedFindingsReport'
41 |
42 | output-reports:
43 | active: true
44 | exclude:
45 | # - 'TxtOutputReport'
46 | # - 'XmlOutputReport'
47 | # - 'HtmlOutputReport'
48 |
49 | comments:
50 | active: true
51 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
52 | AbsentOrWrongFileLicense:
53 | active: false
54 | licenseTemplateFile: 'license.template'
55 | licenseTemplateIsRegex: false
56 | CommentOverPrivateFunction:
57 | active: false
58 | CommentOverPrivateProperty:
59 | active: false
60 | DeprecatedBlockTag:
61 | active: false
62 | EndOfSentenceFormat:
63 | active: false
64 | endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
65 | UndocumentedPublicClass:
66 | active: false
67 | searchInNestedClass: true
68 | searchInInnerClass: true
69 | searchInInnerObject: true
70 | searchInInnerInterface: true
71 | UndocumentedPublicFunction:
72 | active: false
73 | UndocumentedPublicProperty:
74 | active: false
75 |
76 | complexity:
77 | active: true
78 | ComplexCondition:
79 | active: true
80 | threshold: 4
81 | ComplexInterface:
82 | active: false
83 | threshold: 10
84 | includeStaticDeclarations: false
85 | includePrivateDeclarations: false
86 | ComplexMethod:
87 | active: true
88 | threshold: 15
89 | ignoreSingleWhenExpression: false
90 | ignoreSimpleWhenEntries: false
91 | ignoreNestingFunctions: false
92 | nestingFunctions: ['run', 'let', 'apply', 'with', 'also', 'use', 'forEach', 'isNotNull', 'ifNull']
93 | LabeledExpression:
94 | active: false
95 | ignoredLabels: []
96 | LargeClass:
97 | active: true
98 | threshold: 600
99 | LongMethod:
100 | active: true
101 | threshold: 60
102 | LongParameterList:
103 | active: true
104 | functionThreshold: 6
105 | constructorThreshold: 7
106 | ignoreDefaultParameters: false
107 | ignoreDataClasses: true
108 | ignoreAnnotated: []
109 | MethodOverloading:
110 | active: false
111 | threshold: 6
112 | NamedArguments:
113 | active: false
114 | threshold: 3
115 | NestedBlockDepth:
116 | active: true
117 | threshold: 4
118 | ReplaceSafeCallChainWithRun:
119 | active: false
120 | StringLiteralDuplication:
121 | active: false
122 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
123 | threshold: 3
124 | ignoreAnnotation: true
125 | excludeStringsWithLessThan5Characters: true
126 | ignoreStringsRegex: '$^'
127 | TooManyFunctions:
128 | active: true
129 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
130 | thresholdInFiles: 11
131 | thresholdInClasses: 11
132 | thresholdInInterfaces: 11
133 | thresholdInObjects: 11
134 | thresholdInEnums: 11
135 | ignoreDeprecated: false
136 | ignorePrivate: false
137 | ignoreOverridden: false
138 |
139 | coroutines:
140 | active: true
141 | GlobalCoroutineUsage:
142 | active: false
143 | RedundantSuspendModifier:
144 | active: false
145 | SleepInsteadOfDelay:
146 | active: false
147 | SuspendFunWithFlowReturnType:
148 | active: false
149 |
150 | empty-blocks:
151 | active: true
152 | EmptyCatchBlock:
153 | active: true
154 | allowedExceptionNameRegex: '_|(ignore|expected).*'
155 | EmptyClassBlock:
156 | active: true
157 | EmptyDefaultConstructor:
158 | active: true
159 | EmptyDoWhileBlock:
160 | active: true
161 | EmptyElseBlock:
162 | active: true
163 | EmptyFinallyBlock:
164 | active: true
165 | EmptyForBlock:
166 | active: true
167 | EmptyFunctionBlock:
168 | active: true
169 | ignoreOverridden: false
170 | EmptyIfBlock:
171 | active: true
172 | EmptyInitBlock:
173 | active: true
174 | EmptyKtFile:
175 | active: true
176 | EmptySecondaryConstructor:
177 | active: true
178 | EmptyTryBlock:
179 | active: true
180 | EmptyWhenBlock:
181 | active: true
182 | EmptyWhileBlock:
183 | active: true
184 |
185 | exceptions:
186 | active: true
187 | ExceptionRaisedInUnexpectedLocation:
188 | active: true
189 | methodNames: [toString, hashCode, equals, finalize]
190 | InstanceOfCheckForException:
191 | active: false
192 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
193 | NotImplementedDeclaration:
194 | active: false
195 | ObjectExtendsThrowable:
196 | active: false
197 | PrintStackTrace:
198 | active: true
199 | RethrowCaughtException:
200 | active: true
201 | ReturnFromFinally:
202 | active: true
203 | ignoreLabeled: false
204 | SwallowedException:
205 | active: true
206 | ignoredExceptionTypes:
207 | - InterruptedException
208 | - NumberFormatException
209 | - ParseException
210 | - MalformedURLException
211 | allowedExceptionNameRegex: '_|(ignore|expected).*'
212 | ThrowingExceptionFromFinally:
213 | active: true
214 | ThrowingExceptionInMain:
215 | active: false
216 | ThrowingExceptionsWithoutMessageOrCause:
217 | active: true
218 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
219 | exceptions:
220 | - IllegalArgumentException
221 | - IllegalStateException
222 | - IOException
223 | ThrowingNewInstanceOfSameException:
224 | active: true
225 | TooGenericExceptionCaught:
226 | active: true
227 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
228 | exceptionNames:
229 | - ArrayIndexOutOfBoundsException
230 | - Error
231 | - Exception
232 | - IllegalMonitorStateException
233 | - NullPointerException
234 | - IndexOutOfBoundsException
235 | - RuntimeException
236 | - Throwable
237 | allowedExceptionNameRegex: '_|(ignore|expected).*'
238 | TooGenericExceptionThrown:
239 | active: true
240 | exceptionNames:
241 | - Error
242 | - Exception
243 | - Throwable
244 | - RuntimeException
245 |
246 | naming:
247 | active: true
248 | ClassNaming:
249 | active: true
250 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
251 | classPattern: '[A-Z][a-zA-Z0-9]*'
252 | ConstructorParameterNaming:
253 | active: true
254 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
255 | parameterPattern: '[a-z][A-Za-z0-9]*'
256 | privateParameterPattern: '[a-z][A-Za-z0-9]*'
257 | excludeClassPattern: '$^'
258 | ignoreOverridden: true
259 | EnumNaming:
260 | active: true
261 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
262 | enumEntryPattern: '[A-Z][_a-zA-Z0-9]*'
263 | ForbiddenClassName:
264 | active: false
265 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
266 | forbiddenName: []
267 | FunctionMaxLength:
268 | active: false
269 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
270 | maximumFunctionNameLength: 30
271 | FunctionMinLength:
272 | active: false
273 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
274 | minimumFunctionNameLength: 3
275 | FunctionNaming:
276 | active: true
277 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
278 | functionPattern: '([a-z][a-zA-Z0-9]*)|(`.*`)'
279 | excludeClassPattern: '$^'
280 | ignoreOverridden: true
281 | ignoreAnnotated: ['Composable']
282 | FunctionParameterNaming:
283 | active: true
284 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
285 | parameterPattern: '[a-z][A-Za-z0-9]*'
286 | excludeClassPattern: '$^'
287 | ignoreOverridden: true
288 | InvalidPackageDeclaration:
289 | active: false
290 | excludes: ['*.kts']
291 | rootPackage: ''
292 | MatchingDeclarationName:
293 | active: true
294 | mustBeFirst: true
295 | MemberNameEqualsClassName:
296 | active: true
297 | ignoreOverridden: true
298 | NoNameShadowing:
299 | active: false
300 | NonBooleanPropertyPrefixedWithIs:
301 | active: false
302 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
303 | ObjectPropertyNaming:
304 | active: true
305 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
306 | constantPattern: '[A-Za-z][_A-Za-z0-9]*'
307 | propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
308 | privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
309 | PackageNaming:
310 | active: true
311 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
312 | packagePattern: '[a-z]+(\.[a-z][A-Za-z0-9]*)*'
313 | TopLevelPropertyNaming:
314 | active: true
315 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
316 | constantPattern: '[A-Z][_A-Z0-9]*'
317 | propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
318 | privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
319 | VariableMaxLength:
320 | active: false
321 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
322 | maximumVariableNameLength: 64
323 | VariableMinLength:
324 | active: false
325 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
326 | minimumVariableNameLength: 1
327 | VariableNaming:
328 | active: true
329 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
330 | variablePattern: '[a-z][A-Za-z0-9]*'
331 | privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
332 | excludeClassPattern: '$^'
333 | ignoreOverridden: true
334 |
335 | performance:
336 | active: true
337 | ArrayPrimitive:
338 | active: true
339 | ForEachOnRange:
340 | active: true
341 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
342 | SpreadOperator:
343 | active: true
344 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
345 | UnnecessaryTemporaryInstantiation:
346 | active: true
347 |
348 | potential-bugs:
349 | active: true
350 | CastToNullableType:
351 | active: false
352 | Deprecation:
353 | active: false
354 | DontDowncastCollectionTypes:
355 | active: false
356 | DoubleMutabilityForCollection:
357 | active: false
358 | DuplicateCaseInWhenExpression:
359 | active: true
360 | EqualsAlwaysReturnsTrueOrFalse:
361 | active: true
362 | EqualsWithHashCodeExist:
363 | active: true
364 | ExitOutsideMain:
365 | active: false
366 | ExplicitGarbageCollectionCall:
367 | active: true
368 | HasPlatformType:
369 | active: false
370 | IgnoredReturnValue:
371 | active: false
372 | restrictToAnnotatedMethods: true
373 | returnValueAnnotations: ['*.CheckReturnValue', '*.CheckResult']
374 | ImplicitDefaultLocale:
375 | active: true
376 | ImplicitUnitReturnType:
377 | active: false
378 | allowExplicitReturnType: true
379 | InvalidRange:
380 | active: true
381 | IteratorHasNextCallsNextMethod:
382 | active: true
383 | IteratorNotThrowingNoSuchElementException:
384 | active: true
385 | LateinitUsage:
386 | active: false
387 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
388 | excludeAnnotatedProperties: []
389 | ignoreOnClassesPattern: ''
390 | MapGetWithNotNullAssertionOperator:
391 | active: false
392 | MissingWhenCase:
393 | active: true
394 | allowElseExpression: true
395 | NullableToStringCall:
396 | active: false
397 | RedundantElseInWhen:
398 | active: true
399 | UnconditionalJumpStatementInLoop:
400 | active: false
401 | UnnecessaryNotNullOperator:
402 | active: true
403 | UnnecessarySafeCall:
404 | active: true
405 | UnreachableCatchBlock:
406 | active: false
407 | UnreachableCode:
408 | active: true
409 | UnsafeCallOnNullableType:
410 | active: true
411 | UnsafeCast:
412 | active: true
413 | UnusedUnaryOperator:
414 | active: false
415 | UselessPostfixExpression:
416 | active: false
417 | WrongEqualsTypeParameter:
418 | active: true
419 |
420 | style:
421 | active: true
422 | ClassOrdering:
423 | active: false
424 | CollapsibleIfStatements:
425 | active: false
426 | DataClassContainsFunctions:
427 | active: false
428 | conversionFunctionPrefix: 'to'
429 | DataClassShouldBeImmutable:
430 | active: false
431 | DestructuringDeclarationWithTooManyEntries:
432 | active: false
433 | maxDestructuringEntries: 3
434 | EqualsNullCall:
435 | active: true
436 | EqualsOnSignatureLine:
437 | active: false
438 | ExplicitCollectionElementAccessMethod:
439 | active: false
440 | ExplicitItLambdaParameter:
441 | active: false
442 | ExpressionBodySyntax:
443 | active: false
444 | includeLineWrapping: false
445 | ForbiddenComment:
446 | active: false
447 | values: ['TODO:', 'FIXME:', 'STOPSHIP:']
448 | allowedPatterns: ''
449 | ForbiddenImport:
450 | active: false
451 | imports: []
452 | forbiddenPatterns: ''
453 | ForbiddenMethodCall:
454 | active: false
455 | methods: ['kotlin.io.println', 'kotlin.io.print']
456 | ForbiddenPublicDataClass:
457 | active: true
458 | excludes: ['**']
459 | ignorePackages: ['*.internal', '*.internal.*']
460 | ForbiddenVoid:
461 | active: false
462 | ignoreOverridden: false
463 | ignoreUsageInGenerics: false
464 | FunctionOnlyReturningConstant:
465 | active: true
466 | ignoreOverridableFunction: true
467 | ignoreActualFunction: true
468 | excludedFunctions: 'describeContents'
469 | excludeAnnotatedFunction: ['dagger.Provides']
470 | LibraryCodeMustSpecifyReturnType:
471 | active: true
472 | excludes: ['**']
473 | LibraryEntitiesShouldNotBePublic:
474 | active: true
475 | excludes: ['**']
476 | LoopWithTooManyJumpStatements:
477 | active: true
478 | maxJumpCount: 1
479 | MagicNumber:
480 | active: true
481 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**', '**/build-logic/**']
482 | ignoreNumbers: ['-1', '0', '1', '2']
483 | ignoreHashCodeFunction: true
484 | ignorePropertyDeclaration: false
485 | ignoreLocalVariableDeclaration: false
486 | ignoreConstantDeclaration: true
487 | ignoreCompanionObjectPropertyDeclaration: true
488 | ignoreAnnotation: false
489 | ignoreNamedArgument: true
490 | ignoreEnums: false
491 | ignoreRanges: false
492 | ignoreExtensionFunctions: true
493 | ignoreAnnotated: ['Preview']
494 | MandatoryBracesIfStatements:
495 | active: false
496 | MandatoryBracesLoops:
497 | active: false
498 | MaxLineLength:
499 | active: true
500 | maxLineLength: 120
501 | excludePackageStatements: true
502 | excludeImportStatements: true
503 | excludeCommentStatements: false
504 | MayBeConst:
505 | active: true
506 | ModifierOrder:
507 | active: true
508 | MultilineLambdaItParameter:
509 | active: false
510 | NestedClassesVisibility:
511 | active: true
512 | NewLineAtEndOfFile:
513 | active: true
514 | NoTabs:
515 | active: false
516 | ObjectLiteralToLambda:
517 | active: false
518 | OptionalAbstractKeyword:
519 | active: true
520 | OptionalUnit:
521 | active: false
522 | OptionalWhenBraces:
523 | active: false
524 | PreferToOverPairSyntax:
525 | active: false
526 | ProtectedMemberInFinalClass:
527 | active: true
528 | RedundantExplicitType:
529 | active: false
530 | RedundantHigherOrderMapUsage:
531 | active: false
532 | RedundantVisibilityModifierRule:
533 | active: false
534 | ReturnCount:
535 | active: true
536 | max: 2
537 | excludedFunctions: 'equals'
538 | excludeLabeled: false
539 | excludeReturnFromLambda: true
540 | excludeGuardClauses: false
541 | SafeCast:
542 | active: true
543 | SerialVersionUIDInSerializableClass:
544 | active: true
545 | SpacingBetweenPackageAndImports:
546 | active: false
547 | ThrowsCount:
548 | active: true
549 | max: 4
550 | TrailingWhitespace:
551 | active: false
552 | UnderscoresInNumericLiterals:
553 | active: false
554 | acceptableDecimalLength: 5
555 | UnnecessaryAbstractClass:
556 | active: true
557 | excludeAnnotatedClasses: ['dagger.Module']
558 | UnnecessaryAnnotationUseSiteTarget:
559 | active: false
560 | UnnecessaryApply:
561 | active: true
562 | UnnecessaryFilter:
563 | active: false
564 | UnnecessaryInheritance:
565 | active: true
566 | UnnecessaryLet:
567 | active: false
568 | UnnecessaryParentheses:
569 | active: false
570 | UntilInsteadOfRangeTo:
571 | active: false
572 | UnusedImports:
573 | active: false
574 | UnusedPrivateClass:
575 | active: true
576 | UnusedPrivateMember:
577 | active: true
578 | allowedNames: '(_|ignored|expected|serialVersionUID)'
579 | ignoreAnnotated: ['Preview']
580 | UseArrayLiteralsInAnnotations:
581 | active: false
582 | UseCheckNotNull:
583 | active: false
584 | UseCheckOrError:
585 | active: false
586 | UseDataClass:
587 | active: false
588 | excludeAnnotatedClasses: []
589 | allowVars: false
590 | UseEmptyCounterpart:
591 | active: false
592 | UseIfEmptyOrIfBlank:
593 | active: false
594 | UseIfInsteadOfWhen:
595 | active: false
596 | UseIsNullOrEmpty:
597 | active: false
598 | UseOrEmpty:
599 | active: false
600 | UseRequire:
601 | active: false
602 | UseRequireNotNull:
603 | active: false
604 | UselessCallOnNotNull:
605 | active: true
606 | UtilityClassWithPublicConstructor:
607 | active: true
608 | VarCouldBeVal:
609 | active: true
610 | WildcardImport:
611 | active: true
612 | excludes: ['**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/jsTest/**', '**/iosTest/**']
613 | excludeImports: ['java.util.*', 'kotlinx.android.synthetic.*']
614 |
--------------------------------------------------------------------------------