Browse Source

refactor: Migrate to build.gradle.kts

...and rework the original "helper.gradle" into proper plugins. This
also allows the signing configuration code to be shared, and now
keystore.properties is no longer mandatory.
Peter Cai 2 years ago
parent
commit
50c7b4a3be

+ 1 - 0
.gitignore

@@ -15,3 +15,4 @@
 .cxx
 local.properties
 /libs/**/build
+/buildSrc/build

+ 3 - 0
.idea/compiler.xml

@@ -5,6 +5,9 @@
       <module name="OpenEUICC.app" target="17" />
       <module name="OpenEUICC.app-common" target="17" />
       <module name="OpenEUICC.app-unpriv" target="17" />
+      <module name="OpenEUICC.buildSrc" target="17" />
+      <module name="OpenEUICC.buildSrc.main" target="17" />
+      <module name="OpenEUICC.buildSrc.test" target="17" />
       <module name="OpenEUICC.libs.hidden-apis-shim" target="17" />
       <module name="OpenEUICC.libs.lpac-jni" target="17" />
     </bytecodeTargetLevel>

+ 1 - 0
.idea/gradle.xml

@@ -15,6 +15,7 @@
             <option value="$PROJECT_DIR$/app" />
             <option value="$PROJECT_DIR$/app-common" />
             <option value="$PROJECT_DIR$/app-unpriv" />
+            <option value="$PROJECT_DIR$/buildSrc" />
             <option value="$PROJECT_DIR$/libs" />
             <option value="$PROJECT_DIR$/libs/hidden-apis-shim" />
             <option value="$PROJECT_DIR$/libs/hidden-apis-stub" />

+ 0 - 48
app-common/build.gradle

@@ -1,48 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'org.jetbrains.kotlin.android'
-}
-
-android {
-    namespace 'im.angry.openeuicc.common'
-    compileSdk 34
-
-    defaultConfig {
-        minSdk 30
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        consumerProguardFiles "consumer-rules.pro"
-    }
-
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-}
-
-dependencies {
-    implementation project(":libs:lpac-jni")
-    implementation 'androidx.core:core-ktx:1.12.0'
-    implementation 'androidx.appcompat:appcompat:1.6.1'
-    implementation 'com.google.android.material:material:1.10.0'
-    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
-    //noinspection KtxExtensionAvailable
-    implementation "androidx.preference:preference:1.2.1"
-    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
-    implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
-    implementation "androidx.cardview:cardview:1.0.0"
-    implementation "androidx.datastore:datastore-preferences:1.0.0"
-    implementation 'com.journeyapps:zxing-android-embedded:4.3.0'
-    testImplementation 'junit:junit:4.13.2'
-    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
-    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
-}

+ 47 - 0
app-common/build.gradle.kts

@@ -0,0 +1,47 @@
+plugins {
+    id("com.android.library")
+    id("org.jetbrains.kotlin.android")
+}
+
+android {
+    namespace = "im.angry.openeuicc.common"
+    compileSdk = 34
+
+    defaultConfig {
+        minSdk = 30
+
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            isMinifyEnabled = false
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+        }
+    }
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
+
+dependencies {
+    implementation(project(":libs:lpac-jni"))
+    implementation("androidx.core:core-ktx:1.12.0")
+    implementation("androidx.appcompat:appcompat:1.6.1")
+    implementation("com.google.android.material:material:1.10.0")
+    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
+    //noinspection KtxExtensionAvailable
+    implementation("androidx.preference:preference:1.2.1")
+    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
+    implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
+    implementation("androidx.cardview:cardview:1.0.0")
+    implementation("androidx.datastore:datastore-preferences:1.0.0")
+    implementation("com.journeyapps:zxing-android-embedded:4.3.0")
+    testImplementation("junit:junit:4.13.2")
+    androidTestImplementation("androidx.test.ext:junit:1.1.5")
+    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
+}

+ 0 - 62
app-unpriv/build.gradle

@@ -1,62 +0,0 @@
-plugins {
-    id 'com.android.application'
-    id 'org.jetbrains.kotlin.android'
-}
-
-apply from: '../helpers.gradle'
-
-def keystorePropertiesFile = rootProject.file("keystore.properties");
-def keystoreProperties = new Properties()
-keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
-
-android {
-    namespace 'im.angry.easyeuicc'
-    compileSdk 34
-
-    defaultConfig {
-        applicationId "im.angry.easyeuicc"
-        minSdk 30
-        targetSdk 34
-        versionCode getGitVersionCode()
-        versionName getGitVersionName()
-    }
-
-    signingConfigs {
-        config {
-            storeFile file(keystoreProperties['storeFile'])
-            storePassword keystoreProperties['storePassword']
-            keyAlias keystoreProperties['unprivKeyAlias']
-            keyPassword keystoreProperties['unprivKeyPassword']
-        }
-    }
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-            signingConfig signingConfigs.config
-        }
-        debug {
-            debuggable false
-            signingConfig signingConfigs.config
-        }
-    }
-    applicationVariants.configureEach { variant ->
-        if (variant.name == "debug") {
-            variant.outputs.each { o -> o.versionCodeOverride = System.currentTimeSeconds() }
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-}
-
-dependencies {
-    implementation project(":app-common")
-    implementation 'androidx.core:core-ktx:1.9.0'
-    implementation 'androidx.appcompat:appcompat:1.6.1'
-    implementation 'com.google.android.material:material:1.11.0'
-}

+ 48 - 0
app-unpriv/build.gradle.kts

@@ -0,0 +1,48 @@
+import im.angry.openeuicc.build.*
+
+plugins {
+    id("com.android.application")
+    id("org.jetbrains.kotlin.android")
+}
+
+signingKeystoreProperties {
+    keyAliasField = "unprivKeyAlias"
+    keyPasswordField = "unprivKeyPassword"
+}
+
+apply {
+    plugin<MyVersioningPlugin>()
+    plugin<MySigningPlugin>()
+}
+
+android {
+    namespace = "im.angry.easyeuicc"
+    compileSdk = 34
+
+    defaultConfig {
+        applicationId = "im.angry.easyeuicc"
+        minSdk = 30
+        targetSdk = 34
+    }
+
+    buildTypes {
+        release {
+            isMinifyEnabled = false
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+        }
+    }
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
+
+dependencies {
+    implementation(project(":app-common"))
+    implementation("androidx.core:core-ktx:1.9.0")
+    implementation("androidx.appcompat:appcompat:1.6.1")
+    implementation("com.google.android.material:material:1.11.0")
+}

+ 0 - 70
app/build.gradle

@@ -1,70 +0,0 @@
-plugins {
-    id 'com.android.application'
-    id 'org.jetbrains.kotlin.android'
-}
-
-apply from: '../helpers.gradle'
-
-// Signing config, mainly intended for debug builds
-def keystorePropertiesFile = rootProject.file("keystore.properties");
-def keystoreProperties = new Properties()
-keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
-
-android {
-    compileSdk 34
-
-    defaultConfig {
-        applicationId "im.angry.openeuicc"
-        minSdk 30
-        targetSdk 34
-        versionCode getGitVersionCode()
-        versionName getGitVersionName()
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-    }
-
-    signingConfigs {
-        config {
-            storeFile file(keystoreProperties['storeFile'])
-            storePassword keystoreProperties['storePassword']
-            keyAlias keystoreProperties['keyAlias']
-            keyPassword keystoreProperties['keyPassword']
-        }
-    }
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-            signingConfig signingConfigs.config
-        }
-        debug {
-            signingConfig signingConfigs.config
-        }
-    }
-    applicationVariants.configureEach { variant ->
-        if (variant.name == "debug") {
-            variant.outputs.each { o -> o.versionCodeOverride = System.currentTimeSeconds() }
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-    namespace 'im.angry.openeuicc'
-}
-
-dependencies {
-    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
-    implementation 'androidx.recyclerview:recyclerview:1.3.2'
-    compileOnly project(':libs:hidden-apis-stub')
-    implementation project(':libs:hidden-apis-shim')
-    implementation project(':libs:lpac-jni')
-    implementation project(":app-common")
-    implementation 'androidx.appcompat:appcompat:1.6.1'
-    testImplementation 'junit:junit:4.13.2'
-    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
-    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
-}

+ 51 - 0
app/build.gradle.kts

@@ -0,0 +1,51 @@
+import im.angry.openeuicc.build.*
+
+plugins {
+    id("com.android.application")
+    id("org.jetbrains.kotlin.android")
+}
+
+apply {
+    plugin<MyVersioningPlugin>()
+    plugin<MySigningPlugin>()
+}
+
+android {
+    namespace = "im.angry.openeuicc"
+    compileSdk = 34
+
+    defaultConfig {
+        applicationId = "im.angry.openeuicc"
+        minSdk = 30
+        targetSdk = 34
+
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            isMinifyEnabled = false
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+        }
+    }
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
+
+dependencies {
+    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
+    implementation("androidx.recyclerview:recyclerview:1.3.2")
+    compileOnly(project(":libs:hidden-apis-stub"))
+    implementation(project(":libs:hidden-apis-shim"))
+    implementation(project(":libs:lpac-jni"))
+    implementation(project(":app-common"))
+    implementation("androidx.appcompat:appcompat:1.6.1")
+    testImplementation("junit:junit:4.13.2")
+    androidTestImplementation("androidx.test.ext:junit:1.1.3")
+    androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
+}

+ 0 - 11
build.gradle

@@ -1,11 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-plugins {
-    id 'com.android.application' version '8.1.2' apply false
-    id 'com.android.library' version '8.1.2' apply false
-    id 'org.jetbrains.kotlin.android' version '1.9.20' apply false
-    id 'org.jetbrains.kotlin.multiplatform' version '1.9.20' apply false
-}
-
-task clean(type: Delete) {
-    delete rootProject.buildDir
-}

+ 12 - 0
build.gradle.kts

@@ -0,0 +1,12 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+    // The following Android-related plugins are already depended upon by buildSrc, hence unnecessary.
+    // id("com.android.application") version "8.1.2" apply false
+    // id("com.android.library") version "8.1.2" apply false
+    id("org.jetbrains.kotlin.android") version "1.9.20" apply false
+    id("org.jetbrains.kotlin.multiplatform") version "1.9.20" apply false
+}
+
+tasks.create<Delete>("clean") {
+    delete = setOf(rootProject.buildDir)
+}

+ 12 - 0
buildSrc/build.gradle.kts

@@ -0,0 +1,12 @@
+repositories {
+    google()
+    gradlePluginPortal()
+}
+
+plugins {
+    `kotlin-dsl`
+}
+
+dependencies {
+    implementation("com.android.tools.build:gradle:8.1.2")
+}

+ 61 - 0
buildSrc/src/main/kotlin/im/angry/openeuicc/build/Signing.kt

@@ -0,0 +1,61 @@
+package im.angry.openeuicc.build
+
+import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
+import org.gradle.api.Action
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.*
+import java.io.FileInputStream
+import java.io.FileNotFoundException
+import java.util.Properties
+
+val Project.keystoreProperties: Properties?
+    get() {
+        try {
+            val keystorePropertiesFile = rootProject.file("keystore.properties")
+            return Properties().apply { load(FileInputStream(keystorePropertiesFile)) }
+        } catch (e: FileNotFoundException) {
+            return null
+        }
+    }
+
+interface KeystorePropertiesExtension {
+    var storeFileField: String?
+    var storePasswordField: String?
+    var keyAliasField: String?
+    var keyPasswordField: String?
+}
+
+fun Project.signingKeystoreProperties(_configure: Action<KeystorePropertiesExtension>) {
+    extensions.create<KeystorePropertiesExtension>("keystoreProperties")
+    configure<KeystorePropertiesExtension> {
+        _configure(this)
+    }
+}
+
+class MySigningPlugin: Plugin<Project> {
+    override fun apply(target: Project) {
+        val ext = target.extensions.findByType(KeystorePropertiesExtension::class.java)
+        target.configure<BaseAppModuleExtension> {
+            target.keystoreProperties?.let { keystore ->
+                signingConfigs {
+                    create("config") {
+                        storeFile = target.file(keystore[ext?.storeFileField ?: "storeFile"]!!)
+                        storePassword = keystore[ext?.storePasswordField ?: "storePassword"] as String?
+                        keyAlias = keystore[ext?.keyAliasField ?: "keyAlias"] as String?
+                        keyPassword = keystore[ext?.keyPasswordField ?: "keyPassword"] as String?
+                    }
+                }
+
+                buildTypes {
+                    debug {
+                        signingConfig = signingConfigs.getByName("config")
+                    }
+                    release {
+                        signingConfig = signingConfigs.getByName("config")
+                    }
+                }
+            }
+        }
+    }
+}

+ 54 - 0
buildSrc/src/main/kotlin/im/angry/openeuicc/build/Versioning.kt

@@ -0,0 +1,54 @@
+package im.angry.openeuicc.build
+
+import com.android.build.gradle.internal.api.ApkVariantOutputImpl
+import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.kotlin.dsl.configure
+import java.io.ByteArrayOutputStream
+
+val Project.gitVersionCode: Int
+    get() =
+        try {
+            val stdout = ByteArrayOutputStream()
+            exec {
+                commandLine("git", "rev-list", "--first-parent", "--count", "master")
+                standardOutput = stdout
+            }
+            stdout.toString("utf-8").trim('\n').toInt()
+        } catch (e: Exception) {
+            0
+        }
+
+val Project.gitVersionName: String
+    get() =
+        try {
+            val stdout = ByteArrayOutputStream()
+            exec {
+                commandLine("git", "describe", "--always", "--tags", "--dirty")
+                standardOutput = stdout
+            }
+            stdout.toString("utf-8").trim('\n')
+        } catch (e: Exception) {
+            "Unknown"
+        }
+
+class MyVersioningPlugin: Plugin<Project> {
+    override fun apply(target: Project) {
+        target.configure<BaseAppModuleExtension> {
+            defaultConfig {
+                versionCode = target.gitVersionCode
+                versionName = target.gitVersionName
+            }
+
+            applicationVariants.all {
+                if (name == "debug") {
+                    outputs.forEach {
+                        (it as ApkVariantOutputImpl).versionCodeOverride =
+                            (System.currentTimeMillis() / 1000).toInt()
+                    }
+                }
+            }
+        }
+    }
+}

+ 0 - 27
helpers.gradle

@@ -1,27 +0,0 @@
-ext.getGitVersionCode = { ->
-    try {
-        def stdout = new ByteArrayOutputStream()
-        exec {
-            commandLine 'git', 'rev-list', '--first-parent', '--count', 'master'
-            standardOutput = stdout
-        }
-        return Integer.parseInt(stdout.toString().trim())
-    }
-    catch (ignored) {
-        return -1;
-    }
-}
-
-ext.getGitVersionName = { ->
-    try {
-        def stdout = new ByteArrayOutputStream()
-        exec {
-            commandLine 'git', 'describe', '--always', '--tags', '--dirty'
-            standardOutput = stdout
-        }
-        return stdout.toString().trim()
-    }
-    catch (ignored) {
-        return null;
-    }
-}

+ 0 - 41
libs/hidden-apis-shim/build.gradle

@@ -1,41 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'org.jetbrains.kotlin.android'
-}
-
-android {
-    compileSdk 32
-
-    defaultConfig {
-        minSdk 30
-        targetSdk 32
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        consumerProguardFiles "consumer-rules.pro"
-    }
-
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-    namespace 'im.angry.openeuicc.hidden_apis_shim'
-}
-
-dependencies {
-    compileOnly project(':libs:hidden-apis-stub')
-    implementation 'androidx.core:core-ktx:1.7.0'
-    implementation 'androidx.appcompat:appcompat:1.4.2'
-    implementation 'com.google.android.material:material:1.6.1'
-    testImplementation 'junit:junit:4.13.2'
-    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
-    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
-}

+ 40 - 0
libs/hidden-apis-shim/build.gradle.kts

@@ -0,0 +1,40 @@
+plugins {
+    id("com.android.library")
+    id("org.jetbrains.kotlin.android")
+}
+
+android {
+    compileSdk = 32
+
+    defaultConfig {
+        minSdk = 30
+        targetSdk = 32
+
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            isMinifyEnabled = false
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+        }
+    }
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+    namespace = "im.angry.openeuicc.hidden_apis_shim"
+}
+
+dependencies {
+    compileOnly(project(":libs:hidden-apis-stub"))
+    implementation("androidx.core:core-ktx:1.7.0")
+    implementation("androidx.appcompat:appcompat:1.4.2")
+    implementation("com.google.android.material:material:1.6.1")
+    testImplementation("junit:junit:4.13.2")
+    androidTestImplementation("androidx.test.ext:junit:1.1.3")
+    androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
+}

+ 4 - 4
libs/hidden-apis-stub/build.gradle → libs/hidden-apis-stub/build.gradle.kts

@@ -1,10 +1,10 @@
 plugins {
-    id 'com.android.library'
+    id("com.android.library")
 }
 
 android {
-    compileSdk 31
-    namespace 'im.angry.hidden.apis'
+    compileSdk = 31
+    namespace = "im.angry.hidden.apis"
 }
 
 java {
@@ -13,5 +13,5 @@ java {
 }
 
 dependencies {
-    implementation 'org.jetbrains:annotations:15.0'
+    implementation("org.jetbrains:annotations:15.0")
 }

+ 0 - 52
libs/lpac-jni/build.gradle

@@ -1,52 +0,0 @@
-plugins {
-    id 'com.android.library'
-    id 'org.jetbrains.kotlin.android'
-}
-
-android {
-    namespace 'net.typeblog.lpac_jni'
-    compileSdk 33
-
-    defaultConfig {
-        minSdk 27
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        consumerProguardFiles "consumer-rules.pro"
-
-        externalNativeBuild {
-            ndkBuild {
-                arguments '-j4'
-            }
-        }
-    }
-
-    buildTypes {
-        release {
-            minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
-        }
-    }
-    externalNativeBuild {
-        ndkBuild {
-            path "src/main/jni/Android.mk"
-        }
-    }
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-    kotlinOptions {
-        jvmTarget = '1.8'
-    }
-}
-
-dependencies {
-
-    implementation 'androidx.core:core-ktx:1.12.0'
-    implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
-    implementation 'androidx.appcompat:appcompat:1.6.1'
-    implementation 'com.google.android.material:material:1.10.0'
-    testImplementation 'junit:junit:4.13.2'
-    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
-    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
-}

+ 50 - 0
libs/lpac-jni/build.gradle.kts

@@ -0,0 +1,50 @@
+plugins {
+    id("com.android.library")
+    id("org.jetbrains.kotlin.android")
+}
+
+android {
+    namespace = "net.typeblog.lpac_jni"
+    compileSdk = 33
+
+    defaultConfig {
+        minSdk = 27
+
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+
+        externalNativeBuild {
+            ndkBuild {
+                arguments("-j4")
+            }
+        }
+    }
+
+    buildTypes {
+        release {
+            isMinifyEnabled = false
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+        }
+    }
+    externalNativeBuild {
+        ndkBuild {
+            path("src/main/jni/Android.mk")
+        }
+    }
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
+
+dependencies {
+    implementation("androidx.core:core-ktx:1.12.0")
+    implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
+    implementation("androidx.appcompat:appcompat:1.6.1")
+    implementation("com.google.android.material:material:1.10.0")
+    testImplementation("junit:junit:4.13.2")
+    androidTestImplementation("androidx.test.ext:junit:1.1.5")
+    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
+}