Skip to content

Commit f6896c7

Browse files
authored
Merge pull request #20 from tuuhin/enhancements
Feat: Major Enhancements, Refactoring, and Test Coverage
2 parents 33075a8 + 3c9fe1b commit f6896c7

190 files changed

Lines changed: 5502 additions & 3253 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/android_build_ci.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,24 @@ jobs:
1313
- name: Checkout code
1414
uses: actions/checkout@v4
1515

16+
# Optional, but good security practice
17+
- name: 📝 Validate Gradle wrapper
18+
uses: gradle/wrapper-validation-action@v3
19+
1620
- name: Set up JDK
1721
uses: actions/setup-java@v4
1822
with:
1923
distribution: 'temurin'
2024
java-version: '17'
21-
cache: 'gradle'
22-
23-
- name: Set up Android SDK
24-
uses: android-actions/setup-android@v3
2525

26-
- name: Grant execute permission for gradlew
26+
- name: 🛡️ Grant execute permission for gradlew
2727
run: chmod +x gradlew
2828

29-
- name: Validate Gradle wrapper
30-
uses: gradle/wrapper-validation-action@v1
29+
- name: 🔧 Setup Gradle (Caching & Optimization)
30+
uses: gradle/actions/setup-gradle@v4
3131

32-
- name: Create a debug build
33-
run: ./gradlew assembleDebug
32+
- name: 🏗️ Build debug APK
33+
run: ./gradlew assembleDebug --stacktrace
3434

3535
- name: Check if there is any build errors
3636
run: |
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Android Instrumented Tests
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: read
12+
checks: write
13+
pull-requests: write
14+
15+
jobs:
16+
instrumented-tests:
17+
runs-on: ubuntu-latest
18+
timeout-minutes: 45
19+
20+
strategy:
21+
matrix:
22+
api-level: [ 36 ]
23+
target: [ google_apis ]
24+
arch: [ x86_64 ]
25+
26+
steps:
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
30+
- name: Set up JDK 17
31+
uses: actions/setup-java@v4
32+
with:
33+
java-version: '17'
34+
distribution: 'temurin'
35+
cache: gradle
36+
37+
- name: Grant execute permission for gradlew
38+
run: chmod +x gradlew
39+
40+
- name: Configure Gradle memory
41+
run: |
42+
mkdir -p ~/.gradle
43+
echo "org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m" >> ~/.gradle/gradle.properties
44+
echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties
45+
46+
- name: Enable KVM
47+
run: |
48+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
49+
sudo udevadm control --reload-rules
50+
sudo udevadm trigger --name-match=kvm
51+
52+
- name: Gradle cache
53+
uses: gradle/actions/setup-gradle@v3
54+
55+
- name: AVD cache
56+
uses: actions/cache@v4
57+
id: avd-cache
58+
with:
59+
path: |
60+
~/.android/avd/*
61+
~/.android/adb*
62+
key: avd-${{ matrix.api-level }}-${{ matrix.target }}-${{ matrix.arch }}
63+
64+
- name: Create AVD and generate snapshot for caching
65+
if: steps.avd-cache.outputs.cache-hit != 'true'
66+
uses: reactivecircus/android-emulator-runner@v2
67+
with:
68+
api-level: ${{ matrix.api-level }}
69+
target: ${{ matrix.target }}
70+
arch: ${{ matrix.arch }}
71+
force-avd-creation: false
72+
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
73+
disable-animations: false
74+
script: echo "Generated AVD snapshot for caching."
75+
76+
- name: Run instrumented tests
77+
uses: reactivecircus/android-emulator-runner@v2
78+
with:
79+
api-level: ${{ matrix.api-level }}
80+
target: ${{ matrix.target }}
81+
arch: ${{ matrix.arch }}
82+
force-avd-creation: false
83+
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
84+
disable-animations: true
85+
script: |
86+
adb devices
87+
./gradlew connectedAndroidTest --stacktrace
88+
89+
- name: Publish test results
90+
if: always()
91+
uses: EnricoMi/publish-unit-test-result-action@v2
92+
with:
93+
files: |
94+
**/build/test-results/**/*.xml
95+
**/build/outputs/androidTest-results/**/*.xml
96+
check_name: Instrumented Test Results (API ${{ matrix.api-level }})

.idea/gradle.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/kotlinc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/markdown.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle.kts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import java.util.Properties
44
plugins {
55
alias(libs.plugins.android.application)
66
alias(libs.plugins.jetbrains.kotlin.android)
7+
// custom plugins
78
alias(libs.plugins.recorderapp.hilt)
89
alias(libs.plugins.recorderapp.compose.compiler)
910
}
@@ -16,8 +17,8 @@ android {
1617
applicationId = "com.eva.recorderapp"
1718
minSdk = libs.versions.minSdk.get().toInt()
1819
targetSdk = libs.versions.compileSdk.get().toInt()
19-
versionCode = 10
20-
versionName = "1.4.0"
20+
versionCode = 11
21+
versionName = "1.4.1"
2122

2223
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2324
vectorDrawables {
@@ -68,6 +69,10 @@ android {
6869
"proguard-rules.pro"
6970
)
7071
}
72+
debug {
73+
applicationIdSuffix = ".debug"
74+
resValue("string", "app_name", "RecorderApp (DEBUG)")
75+
}
7176
}
7277
compileOptions {
7378
sourceCompatibility = JavaVersion.VERSION_17
@@ -111,4 +116,6 @@ dependencies {
111116
implementation(project(":feature:widget"))
112117
implementation(project(":feature:onboarding"))
113118

119+
// android testing
120+
androidTestImplementation(libs.androidx.runner)
114121
}

app/src/androidTest/java/com/eva/recorderapp/ExampleInstrumentedTest.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.

app/src/main/java/com/eva/recorderapp/RecorderApp.kt

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package com.eva.recorderapp
33
import android.app.Application
44
import android.app.NotificationChannel
55
import android.app.NotificationManager
6+
import androidx.compose.runtime.Composer
7+
import androidx.compose.runtime.ExperimentalComposeRuntimeApi
68
import androidx.core.app.NotificationCompat
79
import androidx.core.content.getSystemService
810
import androidx.hilt.work.HiltWorkerFactory
@@ -14,7 +16,7 @@ import com.eva.worker.UpdateRecordingPathWorker
1416
import dagger.hilt.android.HiltAndroidApp
1517
import javax.inject.Inject
1618

17-
19+
@OptIn(ExperimentalComposeRuntimeApi::class)
1820
@HiltAndroidApp
1921
class RecorderApp : Application(), Configuration.Provider {
2022

@@ -35,6 +37,22 @@ class RecorderApp : Application(), Configuration.Provider {
3537
override fun onCreate() {
3638
super.onCreate()
3739

40+
// enabled compose stack-trace
41+
Composer.setDiagnosticStackTraceEnabled(enabled = BuildConfig.DEBUG)
42+
43+
createNotificationChannels()
44+
45+
//shortcuts
46+
shortcutFacade.createRecordingsShortCut()
47+
48+
//start workers
49+
RemoveTrashRecordingWorker.startRepeatWorker(applicationContext)
50+
// update path worker
51+
UpdateRecordingPathWorker.startWorker(applicationContext)
52+
}
53+
54+
55+
private fun createNotificationChannels() {
3856
val channel1 = NotificationChannel(
3957
NotificationConstants.RECORDER_CHANNEL_ID,
4058
NotificationConstants.RECORDER_CHANNEL_NAME,
@@ -67,13 +85,5 @@ class RecorderApp : Application(), Configuration.Provider {
6785
val channels = listOf(channel1, channel2, channel3)
6886

6987
notificationManager?.createNotificationChannels(channels)
70-
71-
//shortcuts
72-
shortcutFacade.createRecordingsShortCut()
73-
74-
//start workers
75-
RemoveTrashRecordingWorker.startRepeatWorker(applicationContext)
76-
// update path worker
77-
UpdateRecordingPathWorker.startWorker(applicationContext)
7888
}
7989
}

app/src/test/java/com/eva/recorderapp/ExampleUnitTest.kt

Lines changed: 0 additions & 17 deletions
This file was deleted.

build-logic/src/main/kotlin/ConfigureAndroidLibraryPlugin.kt

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,37 +29,57 @@ class ConfigureAndroidLibraryPlugin : Plugin<Project> {
2929

3030
private fun Project.addDependencies() = dependencies.apply {
3131

32-
val dependenciesMap = mapOf(
33-
"implementation" to listOf(
34-
"androidx.core.ktx",
35-
"androidx.lifecycle.runtime.ktx",
36-
"androidx.activity.compose"
37-
),
38-
"testImplementation" to listOf("junit"),
39-
"androidTestImplementation" to listOf("androidx.junit", "androidx.espresso.core")
32+
val implementations = listOf(
33+
"androidx.core.ktx",
34+
"androidx.lifecycle.runtime.ktx",
35+
"androidx.activity.compose"
4036
)
37+
implementations.forEach {
38+
catalog.findLibrary(it).ifPresent { dependency ->
39+
add("implementation", dependency.get())
40+
}
41+
}
42+
43+
val testImplementations = listOf(
44+
"junit",
45+
"kotlin.test",
46+
"kotlinx.coroutines.test",
47+
"turbine"
48+
)
49+
50+
testImplementations.forEach {
51+
catalog.findLibrary(it).ifPresent { dependency ->
52+
add("testImplementation", dependency.get())
53+
}
54+
}
4155

42-
dependenciesMap.forEach { (key, dependencies) ->
43-
dependencies.forEach {
44-
catalog.findLibrary(it).ifPresent { dependency ->
45-
add(key, dependency.get())
46-
}
56+
val androidTestImplementations = listOf(
57+
"androidx.junit",
58+
"androidx.espresso.core",
59+
"kotlin.test",
60+
"kotlinx.coroutines.test",
61+
"turbine"
62+
)
63+
64+
androidTestImplementations.forEach {
65+
catalog.findLibrary(it).ifPresent { dependency ->
66+
add("androidTestImplementation", dependency.get())
4767
}
4868
}
69+
// include the testing runtime module
70+
if (findProject(":testing:runtime") != null) {
71+
add("androidTestImplementation", project(":testing:runtime"))
72+
}
4973
}
5074

5175
private fun Project.configureLibrary() = extensions.configure<LibraryExtension> {
5276

53-
val compilerSdkVersion = catalog.findVersion("compileSdk")
54-
.getOrNull()?.toString()?.toInt() ?: 36
55-
val minSdkVersion = catalog.findVersion("minSdk")
56-
.getOrNull()?.toString()?.toInt() ?: 29
77+
compileSdk = catalog.findVersion("compileSdk").getOrNull()?.toString()?.toInt() ?: 36
5778

58-
compileSdk = compilerSdkVersion
5979
defaultConfig {
60-
minSdk = minSdkVersion
80+
minSdk = catalog.findVersion("minSdk").getOrNull()?.toString()?.toInt() ?: 29
6181

62-
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
82+
testInstrumentationRunner = Constants.TEST_RUNNER_CLASS_NAME
6383
consumerProguardFiles("consumer-rules.pro")
6484
}
6585

0 commit comments

Comments
 (0)