├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── styles.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── drawable │ │ │ ├── item_background.xml │ │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ │ ├── activity_main.xml │ │ │ └── view_feature_item.xml │ │ └── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ ├── java │ │ └── com │ │ │ └── wisnu │ │ │ └── ordertiket │ │ │ ├── recyclerview │ │ │ ├── FeatureUiModel.kt │ │ │ ├── FeatureViewHolder.kt │ │ │ └── FeatureAdapter.kt │ │ │ ├── MainApplication.kt │ │ │ ├── MainLauncher.kt │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── core-utils ├── .gitignore ├── consumer-rules.pro ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── wisnu │ │ │ │ └── kurn │ │ │ │ └── core_utils │ │ │ │ └── Constant.kt │ │ └── AndroidManifest.xml │ └── test │ │ └── java │ │ └── com │ │ └── wisnu │ │ └── kurn │ │ └── core_utils │ │ └── ExampleUnitTest.kt ├── build.gradle └── proguard-rules.pro ├── launcher ├── main │ ├── consumer-rules.pro │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── com │ │ │ └── wisnu │ │ │ └── launcher │ │ │ └── main │ │ │ ├── Application.kt │ │ │ ├── Launchable.kt │ │ │ ├── Launcher.kt │ │ │ ├── Constant.kt │ │ │ └── BaseLauncher.kt │ ├── build.gradle │ └── proguard-rules.pro ├── compiler │ ├── consumer-rules.pro │ ├── .gitignore │ ├── src │ │ └── main │ │ │ ├── res │ │ │ └── values │ │ │ │ └── strings.xml │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── javax.annotation.processing.Processor │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── com │ │ │ └── wisnu │ │ │ └── launcher │ │ │ └── compiler │ │ │ ├── ClassExtensions.kt │ │ │ ├── FeatureAnnotatedClass.kt │ │ │ ├── FeatureListWriter.kt │ │ │ └── FeatureProcessor.kt │ ├── build.gradle │ └── proguard-rules.pro └── annotations │ ├── .gitignore │ ├── build.gradle │ └── src │ └── main │ └── java │ └── com │ └── wisnu │ └── launcher │ └── annotations │ └── RegisterFeature.java ├── feature-order-bus ├── consumer-rules.pro ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ └── strings.xml │ │ ├── drawable │ │ │ └── ic_bus.xml │ │ └── layout │ │ │ └── activity_order_bus.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── wisnu │ │ └── feature │ │ └── orderbus │ │ ├── OrderBusApplication.kt │ │ ├── OrderBusActivity.kt │ │ └── OrderBusFeature.kt ├── build.gradle └── proguard-rules.pro ├── feature-order-hotel ├── consumer-rules.pro ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ └── strings.xml │ │ ├── drawable │ │ │ └── ic_hotel.xml │ │ └── layout │ │ │ └── activity_order_hotel.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── wisnu │ │ └── feature │ │ └── order │ │ └── hotel │ │ ├── OrderHotelApplication.kt │ │ ├── OrderHotelActivity.kt │ │ └── OrderHotelFeature.kt ├── build.gradle └── proguard-rules.pro ├── feature-order-train ├── consumer-rules.pro ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ └── strings.xml │ │ ├── drawable │ │ │ └── ic_train.xml │ │ └── layout │ │ │ └── activity_order_train.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── wisnu │ │ └── feature │ │ └── order │ │ └── train │ │ ├── OrderTrainApplication.kt │ │ ├── OrderTrainActivity.kt │ │ └── OrderTrainFeature.kt ├── build.gradle └── proguard-rules.pro ├── feature-setting ├── .gitignore ├── consumer-rules.pro ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ └── strings.xml │ │ ├── layout │ │ │ └── activity_setting.xml │ │ └── drawable │ │ │ └── ic_settings.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── wisnu │ │ └── feature │ │ └── setting │ │ ├── SettingApplication.kt │ │ ├── SettingActivity.kt │ │ └── SettingFeature.kt ├── build.gradle └── proguard-rules.pro ├── feature-transaction ├── consumer-rules.pro ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ └── strings.xml │ │ │ ├── drawable │ │ │ │ └── ic_transaction.xml │ │ │ └── layout │ │ │ │ └── activity_transaction.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── wisnu │ │ │ └── feature │ │ │ └── transaction │ │ │ ├── TransactionApplication.kt │ │ │ ├── TransactionActivity.kt │ │ │ └── TransactionFeature.kt │ └── test │ │ └── java │ │ └── com │ │ └── wisnu │ │ └── feature │ │ └── AdditionTest.kt ├── build.gradle └── proguard-rules.pro ├── feature-order-flight ├── .gitignore ├── consumer-rules.pro ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ └── strings.xml │ │ ├── drawable │ │ │ └── ic_flight.xml │ │ └── layout │ │ │ └── activity_order_flight.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── wisnu │ │ └── feature │ │ └── order │ │ └── flight │ │ ├── OrderFlightApplication.kt │ │ ├── OrderFlightActivity.kt │ │ └── OrderFlightFeature.kt ├── build.gradle └── proguard-rules.pro ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── preview ├── Screenshot_1579834646.png ├── Screenshot_1579872360.png └── Screenshot_1579872361.png ├── settings.gradle ├── .gitignore ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /core-utils/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /core-utils/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /launcher/main/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /feature-order-bus/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /feature-order-hotel/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /feature-order-train/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /feature-setting/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /feature-setting/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /feature-transaction/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /launcher/compiler/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /launcher/main/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /feature-order-bus/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /feature-order-flight/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /feature-order-flight/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /feature-order-hotel/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /feature-order-train/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /feature-transaction/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /launcher/annotations/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /launcher/compiler/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Order Ticket 3 | 4 | -------------------------------------------------------------------------------- /launcher/main/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | main 3 | 4 | -------------------------------------------------------------------------------- /launcher/compiler/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | compiler 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /launcher/compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | com.wisnu.launcher.compiler.FeatureProcessor -------------------------------------------------------------------------------- /preview/Screenshot_1579834646.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/preview/Screenshot_1579834646.png -------------------------------------------------------------------------------- /preview/Screenshot_1579872360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/preview/Screenshot_1579872360.png -------------------------------------------------------------------------------- /preview/Screenshot_1579872361.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/preview/Screenshot_1579872361.png -------------------------------------------------------------------------------- /feature-setting/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Setting 3 | 4 | -------------------------------------------------------------------------------- /feature-order-bus/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Order Bus 3 | 4 | -------------------------------------------------------------------------------- /core-utils/src/main/java/com/wisnu/kurn/core_utils/Constant.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.kurn.core_utils 2 | 3 | object Constant { 4 | val RANDOM = 2 5 | } -------------------------------------------------------------------------------- /feature-order-hotel/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Order Hotel 3 | 4 | -------------------------------------------------------------------------------- /feature-order-train/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Order Train 3 | 4 | -------------------------------------------------------------------------------- /feature-transaction/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Transaction 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /feature-order-flight/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Order Flight 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /launcher/main/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /launcher/compiler/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wisnukurniawan/Composable-Module/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /core-utils/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | / 5 | -------------------------------------------------------------------------------- /launcher/main/src/main/java/com/wisnu/launcher/main/Application.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.main 2 | 3 | interface Application { 4 | fun onCreate(launcher: Launcher) 5 | } 6 | -------------------------------------------------------------------------------- /launcher/annotations/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java-library' 2 | 3 | dependencies { 4 | implementation fileTree(dir: 'libs', include: ['*.jar']) 5 | } 6 | 7 | sourceCompatibility = "7" 8 | targetCompatibility = "7" 9 | -------------------------------------------------------------------------------- /launcher/main/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | 3 | dependencies { 4 | implementation 'androidx.appcompat:appcompat:1.0.2' 5 | implementation 'androidx.core:core-ktx:1.0.2' 6 | } 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jan 23 21:33:13 WIB 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/wisnu/ordertiket/recyclerview/FeatureUiModel.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.ordertiket.recyclerview 2 | 3 | import android.content.Intent 4 | 5 | data class FeatureUiModel( 6 | val type: Int, 7 | val title: String, 8 | val icon: Int, 9 | val intent: Intent? 10 | ) -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':core-utils' 2 | include ':app', ':launcher:main', ':launcher:compiler', ':launcher:annotations', ':feature-setting', ':feature-transaction', ':feature-order-train', ':feature-order-flight', ':feature-order-hotel', ':feature-order-bus' 3 | rootProject.name='Order Ticket' 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #24272B 4 | #24272B 5 | #121212 6 | #FFFFFF 7 | 8 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /launcher/main/src/main/java/com/wisnu/launcher/main/Launchable.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.main 2 | 3 | import android.content.Intent 4 | 5 | interface Launchable { 6 | val type: Int 7 | fun title(): Int 8 | } 9 | 10 | interface FeatureLaunchable : Launchable { 11 | fun intent(): Intent? 12 | fun icon(): Int 13 | } -------------------------------------------------------------------------------- /feature-setting/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /feature-order-bus/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /feature-order-hotel/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /feature-order-train/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /feature-order-flight/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /feature-transaction/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /feature-setting/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | 3 | dependencies { 4 | implementation project(':launcher:main') 5 | 6 | implementation 'androidx.appcompat:appcompat:1.0.2' 7 | implementation 'androidx.core:core-ktx:1.0.2' 8 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 9 | } 10 | -------------------------------------------------------------------------------- /feature-order-flight/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | 3 | dependencies { 4 | implementation project(':launcher:main') 5 | 6 | implementation 'androidx.appcompat:appcompat:1.0.2' 7 | implementation 'androidx.core:core-ktx:1.0.2' 8 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 9 | } 10 | -------------------------------------------------------------------------------- /feature-order-hotel/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | 3 | dependencies { 4 | implementation project(':launcher:main') 5 | 6 | implementation 'androidx.appcompat:appcompat:1.0.2' 7 | implementation 'androidx.core:core-ktx:1.0.2' 8 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 9 | } 10 | -------------------------------------------------------------------------------- /feature-order-train/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | 3 | dependencies { 4 | implementation project(':launcher:main') 5 | 6 | implementation 'androidx.appcompat:appcompat:1.0.2' 7 | implementation 'androidx.core:core-ktx:1.0.2' 8 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 9 | } 10 | -------------------------------------------------------------------------------- /launcher/compiler/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'kotlin' 2 | 3 | dependencies { 4 | implementation project(':launcher:annotations') 5 | implementation "com.squareup:javapoet:1.11.1" 6 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 7 | } 8 | 9 | sourceCompatibility = JavaVersion.VERSION_1_8 10 | targetCompatibility = JavaVersion.VERSION_1_8 11 | -------------------------------------------------------------------------------- /feature-transaction/src/test/java/com/wisnu/feature/AdditionTest.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature 2 | 3 | import com.wisnu.kurn.core_utils.Constant 4 | import junit.framework.Assert.assertEquals 5 | import org.junit.Test 6 | 7 | class AdditionTest { 8 | 9 | @Test 10 | fun add() { 11 | assertEquals(2, 1 + 1) 12 | assertEquals(2, Constant.RANDOM) 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/item_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /feature-transaction/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | 3 | dependencies { 4 | implementation project(':launcher:main') 5 | implementation project(':core-utils') 6 | 7 | implementation 'androidx.appcompat:appcompat:1.0.2' 8 | implementation 'androidx.core:core-ktx:1.0.2' 9 | 10 | testImplementation 'junit:junit:4.12' 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea 4 | /local.properties 5 | /.idea/caches 6 | /.idea/libraries 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | /.idea/navEditor.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /buildSrc/build 14 | /captures 15 | .externalNativeBuild 16 | .cxx 17 | affected_module_detector_log.txt 18 | 19 | build-system/dependencies-feature-develop.gradle -------------------------------------------------------------------------------- /feature-setting/src/main/java/com/wisnu/feature/setting/SettingApplication.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.setting 2 | 3 | import com.wisnu.launcher.main.Application 4 | import com.wisnu.launcher.main.Launcher 5 | 6 | class SettingApplication : Application { 7 | override fun onCreate(launcher: Launcher) { 8 | launcher.registerFeature(SettingFeature(launcher.application)) 9 | } 10 | } -------------------------------------------------------------------------------- /feature-order-bus/src/main/java/com/wisnu/feature/orderbus/OrderBusApplication.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.orderbus 2 | 3 | import com.wisnu.launcher.main.Application 4 | import com.wisnu.launcher.main.Launcher 5 | 6 | class OrderBusApplication : Application { 7 | override fun onCreate(launcher: Launcher) { 8 | launcher.registerFeature(OrderBusFeature(launcher.application)) 9 | } 10 | } -------------------------------------------------------------------------------- /feature-order-hotel/src/main/java/com/wisnu/feature/order/hotel/OrderHotelApplication.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.hotel 2 | 3 | import com.wisnu.launcher.main.Application 4 | import com.wisnu.launcher.main.Launcher 5 | 6 | class OrderHotelApplication : Application { 7 | override fun onCreate(launcher: Launcher) { 8 | launcher.registerFeature(OrderHotelFeature(launcher.application)) 9 | } 10 | } -------------------------------------------------------------------------------- /feature-order-train/src/main/java/com/wisnu/feature/order/train/OrderTrainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.train 2 | 3 | import com.wisnu.launcher.main.Application 4 | import com.wisnu.launcher.main.Launcher 5 | 6 | class OrderTrainApplication : Application { 7 | override fun onCreate(launcher: Launcher) { 8 | launcher.registerFeature(OrderTrainFeature(launcher.application)) 9 | } 10 | } -------------------------------------------------------------------------------- /feature-transaction/src/main/java/com/wisnu/feature/transaction/TransactionApplication.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.transaction 2 | 3 | import com.wisnu.launcher.main.Application 4 | import com.wisnu.launcher.main.Launcher 5 | 6 | class TransactionApplication : Application { 7 | override fun onCreate(launcher: Launcher) { 8 | launcher.registerFeature(TransactionFeature(launcher.application)) 9 | } 10 | } -------------------------------------------------------------------------------- /feature-order-flight/src/main/java/com/wisnu/feature/order/flight/OrderFlightApplication.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.flight 2 | 3 | import com.wisnu.launcher.main.Application 4 | import com.wisnu.launcher.main.Launcher 5 | 6 | class OrderFlightApplication : Application { 7 | override fun onCreate(launcher: Launcher) { 8 | launcher.registerFeature(OrderFlightFeature(launcher.application)) 9 | } 10 | } -------------------------------------------------------------------------------- /core-utils/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | dependencies { 6 | implementation 'androidx.appcompat:appcompat:1.0.2' 7 | implementation 'androidx.core:core-ktx:1.0.2' 8 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 9 | testImplementation 'junit:junit:4.12' 10 | } 11 | -------------------------------------------------------------------------------- /feature-setting/src/main/java/com/wisnu/feature/setting/SettingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.setting 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | 6 | class SettingActivity : AppCompatActivity() { 7 | 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_setting) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/wisnu/ordertiket/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.ordertiket 2 | 3 | import android.app.Application 4 | import com.wisnu.launcher.main.Launcher 5 | 6 | class MainApplication : Application(), Launcher.Provider { 7 | override lateinit var launcher: Launcher 8 | 9 | override fun onCreate() { 10 | super.onCreate() 11 | launcher = MainLauncher(this) 12 | launcher.onCreate() 13 | } 14 | } -------------------------------------------------------------------------------- /feature-order-bus/build.gradle: -------------------------------------------------------------------------------- 1 | apply from: "$rootDir/build-system/dependencies-module.gradle" 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | dependencies { 6 | implementation project(':launcher:main') 7 | 8 | implementation 'androidx.appcompat:appcompat:1.0.2' 9 | implementation 'androidx.core:core-ktx:1.0.2' 10 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 11 | } 12 | -------------------------------------------------------------------------------- /feature-order-hotel/src/main/java/com/wisnu/feature/order/hotel/OrderHotelActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.hotel 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | 6 | class OrderHotelActivity : AppCompatActivity() { 7 | 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_order_hotel) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /launcher/annotations/src/main/java/com/wisnu/launcher/annotations/RegisterFeature.java: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.annotations; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.CLASS) 10 | public @interface RegisterFeature { 11 | String[] value(); 12 | } 13 | -------------------------------------------------------------------------------- /feature-order-flight/src/main/java/com/wisnu/feature/order/flight/OrderFlightActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.flight 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | 6 | class OrderFlightActivity : AppCompatActivity() { 7 | 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_order_flight) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /feature-order-bus/src/main/java/com/wisnu/feature/orderbus/OrderBusActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.orderbus 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | 6 | class OrderBusActivity : AppCompatActivity() { 7 | 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_order_bus) 11 | // put comment 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /feature-transaction/src/main/res/drawable/ic_transaction.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /feature-order-hotel/src/main/res/drawable/ic_hotel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /core-utils/src/test/java/com/wisnu/kurn/core_utils/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.kurn.core_utils 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /feature-order-train/src/main/java/com/wisnu/feature/order/train/OrderTrainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.train 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | 6 | class OrderTrainActivity : AppCompatActivity() { 7 | 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_order_train) 11 | // Made changes here 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /feature-transaction/src/main/java/com/wisnu/feature/transaction/TransactionActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.transaction 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | 6 | class TransactionActivity : AppCompatActivity() { 7 | 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_transaction) 11 | 12 | // update comment here 2 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /launcher/compiler/src/main/java/com/wisnu/launcher/compiler/ClassExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.compiler 2 | 3 | private val classMap = mutableMapOf>() 4 | 5 | private inline fun Any.castOrNull() = this as? T 6 | 7 | internal fun String.loadClassOrNull(): Class? = 8 | classMap.getOrPut(this) { 9 | try { 10 | Class.forName(this) 11 | } catch (e: ClassNotFoundException) { 12 | return null 13 | } 14 | }.castOrNull() 15 | -------------------------------------------------------------------------------- /feature-order-flight/src/main/res/drawable/ic_flight.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /feature-setting/src/main/java/com/wisnu/feature/setting/SettingFeature.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.setting 2 | 3 | import android.app.Application 4 | import android.content.Intent 5 | import com.wisnu.launcher.main.FeatureLaunchable 6 | import com.wisnu.launcher.main.FeatureType 7 | 8 | class SettingFeature(private val application: Application) : FeatureLaunchable { 9 | override val type: Int = FeatureType.SETTING 10 | 11 | override fun title(): Int = R.string.feature_setting_name 12 | 13 | override fun intent(): Intent? = Intent(application, SettingActivity::class.java) 14 | 15 | override fun icon(): Int = R.drawable.ic_settings 16 | } -------------------------------------------------------------------------------- /feature-order-bus/src/main/java/com/wisnu/feature/orderbus/OrderBusFeature.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.orderbus 2 | 3 | import android.app.Application 4 | import android.content.Intent 5 | import com.wisnu.launcher.main.FeatureLaunchable 6 | import com.wisnu.launcher.main.FeatureType 7 | 8 | class OrderBusFeature(private val application: Application) : FeatureLaunchable { 9 | override val type: Int = FeatureType.ORDER_FLIGHT 10 | 11 | override fun title(): Int = R.string.feature_order_bus_name 12 | 13 | override fun intent(): Intent? = Intent(application, OrderBusActivity::class.java) 14 | 15 | override fun icon(): Int = R.drawable.ic_bus 16 | } -------------------------------------------------------------------------------- /feature-order-hotel/src/main/java/com/wisnu/feature/order/hotel/OrderHotelFeature.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.hotel 2 | 3 | import android.app.Application 4 | import android.content.Intent 5 | import com.wisnu.launcher.main.FeatureLaunchable 6 | import com.wisnu.launcher.main.FeatureType 7 | 8 | class OrderHotelFeature(private val application: Application) : FeatureLaunchable { 9 | override val type: Int = FeatureType.ORDER_HOTEL 10 | 11 | override fun title(): Int = R.string.feature_order_hotel_name 12 | 13 | override fun intent(): Intent? = Intent(application, OrderHotelActivity::class.java) 14 | 15 | override fun icon(): Int = R.drawable.ic_hotel 16 | } -------------------------------------------------------------------------------- /feature-order-train/src/main/java/com/wisnu/feature/order/train/OrderTrainFeature.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.train 2 | 3 | import android.app.Application 4 | import android.content.Intent 5 | import com.wisnu.launcher.main.FeatureLaunchable 6 | import com.wisnu.launcher.main.FeatureType 7 | 8 | class OrderTrainFeature(private val application: Application) : FeatureLaunchable { 9 | override val type: Int = FeatureType.ORDER_TRAIN 10 | 11 | override fun title(): Int = R.string.feature_order_train_name 12 | 13 | override fun intent(): Intent? = Intent(application, OrderTrainActivity::class.java) 14 | 15 | override fun icon(): Int = R.drawable.ic_train 16 | } -------------------------------------------------------------------------------- /launcher/main/src/main/java/com/wisnu/launcher/main/Launcher.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.main 2 | 3 | import android.app.Application as AndroidApplication 4 | 5 | interface Launcher : ApplicationRegistry, FeatureRegistry { 6 | val application: AndroidApplication 7 | 8 | interface Provider { 9 | val launcher: Launcher 10 | } 11 | } 12 | 13 | interface ApplicationRegistry { 14 | val applications: List 15 | fun registerApplication(application: Application?) 16 | fun onCreate() 17 | } 18 | 19 | interface FeatureRegistry { 20 | val features: List 21 | fun registerFeature(featureLaunchable: FeatureLaunchable?) 22 | } -------------------------------------------------------------------------------- /feature-order-flight/src/main/java/com/wisnu/feature/order/flight/OrderFlightFeature.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.order.flight 2 | 3 | import android.app.Application 4 | import android.content.Intent 5 | import com.wisnu.launcher.main.FeatureLaunchable 6 | import com.wisnu.launcher.main.FeatureType 7 | 8 | class OrderFlightFeature(private val application: Application) : FeatureLaunchable { 9 | override val type: Int = FeatureType.ORDER_FLIGHT 10 | 11 | override fun title(): Int = R.string.feature_order_flight_name 12 | 13 | override fun intent(): Intent? = Intent(application, OrderFlightActivity::class.java) 14 | 15 | override fun icon(): Int = R.drawable.ic_flight 16 | } -------------------------------------------------------------------------------- /feature-transaction/src/main/java/com/wisnu/feature/transaction/TransactionFeature.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.feature.transaction 2 | 3 | import android.app.Application 4 | import android.content.Intent 5 | import com.wisnu.launcher.main.FeatureLaunchable 6 | import com.wisnu.launcher.main.FeatureType 7 | 8 | class TransactionFeature(private val application: Application) : FeatureLaunchable { 9 | override val type: Int = FeatureType.TRANSACTION 10 | 11 | override fun title(): Int = R.string.feature_transaction_name 12 | 13 | override fun intent(): Intent? = Intent(application, TransactionActivity::class.java) 14 | 15 | override fun icon(): Int = R.drawable.ic_transaction 16 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | -------------------------------------------------------------------------------- /feature-order-train/src/main/res/drawable/ic_train.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /feature-setting/src/main/res/layout/activity_setting.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /feature-order-bus/src/main/res/drawable/ic_bus.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /feature-order-bus/src/main/res/layout/activity_order_bus.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /feature-order-hotel/src/main/res/layout/activity_order_hotel.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /feature-order-train/src/main/res/layout/activity_order_train.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /feature-transaction/src/main/res/layout/activity_transaction.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /feature-order-flight/src/main/res/layout/activity_order_flight.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/wisnu/ordertiket/MainLauncher.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.ordertiket 2 | 3 | import android.app.Application 4 | import com.wisnu.launcher.annotations.RegisterFeature 5 | import com.wisnu.launcher.main.BaseLauncher 6 | import com.wisnu.launcher.main.ApplicationClassName 7 | 8 | @RegisterFeature( 9 | ApplicationClassName.ORDER_FLIGHT, 10 | ApplicationClassName.ORDER_HOTEL, 11 | ApplicationClassName.ORDER_TRAIN, 12 | ApplicationClassName.ORDER_BUS, 13 | ApplicationClassName.TRANSACTION, 14 | ApplicationClassName.SETTING 15 | ) 16 | class MainLauncher(application: Application) : BaseLauncher(application) { 17 | init { 18 | MainLauncherUtils.buildFeatures() 19 | .forEach { registerApplication(it) } 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wisnu/ordertiket/recyclerview/FeatureViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.ordertiket.recyclerview 2 | 3 | import android.content.Intent 4 | import android.view.View 5 | import androidx.recyclerview.widget.RecyclerView 6 | import kotlinx.android.synthetic.main.view_feature_item.view.* 7 | 8 | class FeatureViewHolder( 9 | itemView: View, 10 | private val onClick: (Intent) -> Unit 11 | ) : RecyclerView.ViewHolder(itemView) { 12 | fun bindData(data: FeatureUiModel) { 13 | itemView.setOnClickListener { 14 | if (adapterPosition != RecyclerView.NO_POSITION && data.intent != null) { 15 | onClick(data.intent) 16 | } 17 | } 18 | itemView.tv_title.text = data.title 19 | itemView.iv_feature.setImageResource(data.icon) 20 | } 21 | } -------------------------------------------------------------------------------- /launcher/main/src/main/java/com/wisnu/launcher/main/Constant.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.main 2 | 3 | object FeatureType { 4 | const val SETTING = 0 5 | const val TRANSACTION = 1 6 | const val ORDER_FLIGHT = 2 7 | const val ORDER_TRAIN = 3 8 | const val ORDER_HOTEL = 4 9 | } 10 | 11 | object ApplicationClassName { 12 | const val ORDER_FLIGHT = "com.wisnu.feature.order.flight.OrderFlightApplication" 13 | const val ORDER_HOTEL = "com.wisnu.feature.order.hotel.OrderHotelApplication" 14 | const val ORDER_TRAIN = "com.wisnu.feature.order.train.OrderTrainApplication" 15 | const val ORDER_BUS = "com.wisnu.feature.orderbus.OrderBusApplication" 16 | const val TRANSACTION = "com.wisnu.feature.transaction.TransactionApplication" 17 | const val SETTING = "com.wisnu.feature.setting.SettingApplication" 18 | } -------------------------------------------------------------------------------- /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. 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 22 | -------------------------------------------------------------------------------- /core-utils/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. 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 -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /feature-order-bus/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. 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 22 | -------------------------------------------------------------------------------- /feature-setting/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. 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 22 | -------------------------------------------------------------------------------- /launcher/compiler/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. 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 22 | -------------------------------------------------------------------------------- /launcher/main/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. 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 22 | -------------------------------------------------------------------------------- /feature-order-flight/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. 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 22 | -------------------------------------------------------------------------------- /feature-order-hotel/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. 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 22 | -------------------------------------------------------------------------------- /feature-order-train/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. 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 22 | -------------------------------------------------------------------------------- /feature-transaction/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. 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 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/wisnu/ordertiket/recyclerview/FeatureAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.ordertiket.recyclerview 2 | 3 | import android.content.Intent 4 | import android.view.LayoutInflater 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.wisnu.ordertiket.R 8 | 9 | class FeatureAdapter( 10 | private val items: List, 11 | private val onClick: (Intent) -> Unit 12 | ) : RecyclerView.Adapter() { 13 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FeatureViewHolder { 14 | val itemView = LayoutInflater.from(parent.context).inflate(R.layout.view_feature_item, parent, false) 15 | return FeatureViewHolder(itemView, onClick) 16 | } 17 | 18 | override fun getItemCount(): Int { 19 | return items.size 20 | } 21 | 22 | override fun onBindViewHolder(holder: FeatureViewHolder, position: Int) { 23 | holder.bindData(items[position]) 24 | } 25 | } -------------------------------------------------------------------------------- /feature-setting/src/main/res/drawable/ic_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/wisnu/ordertiket/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.ordertiket 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.recyclerview.widget.GridLayoutManager 7 | import com.wisnu.launcher.main.Launcher 8 | import com.wisnu.ordertiket.recyclerview.FeatureAdapter 9 | import com.wisnu.ordertiket.recyclerview.FeatureUiModel 10 | import kotlinx.android.synthetic.main.activity_main.* 11 | 12 | 13 | class MainActivity : AppCompatActivity() { 14 | 15 | override fun onCreate(savedInstanceState: Bundle?) { 16 | super.onCreate(savedInstanceState) 17 | setContentView(R.layout.activity_main) 18 | 19 | val features = (applicationContext as? Launcher.Provider)?.launcher?.features 20 | val featureUiModels = features?.map { FeatureUiModel(it.type, getString(it.title()), it.icon(), it.intent()) } ?: listOf() 21 | val adapter = FeatureAdapter(featureUiModels) { 22 | startActivity(it) 23 | } 24 | val layoutManager = GridLayoutManager(this, 3) 25 | rv_feature.layoutManager = layoutManager 26 | rv_feature.adapter = adapter 27 | rv_feature.setHasFixedSize(true) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /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=-Xmx1536m 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 22 | kapt.incremental.apt=true 23 | -------------------------------------------------------------------------------- /launcher/compiler/src/main/java/com/wisnu/launcher/compiler/FeatureAnnotatedClass.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.compiler 2 | 3 | import com.squareup.javapoet.ClassName 4 | import com.wisnu.launcher.annotations.RegisterFeature 5 | import javax.lang.model.element.TypeElement 6 | import javax.lang.model.util.Elements 7 | 8 | class FeatureAnnotatedClass(element: TypeElement, elementUtils: Elements) { 9 | 10 | val className: ClassName 11 | val features: Array 12 | 13 | init { 14 | val packageName = getPackageName(elementUtils, element) 15 | val originalClassName = getClassName(element, packageName) 16 | this.className = ClassName.get(packageName, originalClassName) 17 | this.features = element.getAnnotation(RegisterFeature::class.java).value 18 | } 19 | 20 | private fun getPackageName(elementUtils: Elements, type: TypeElement): String { 21 | return elementUtils.getPackageOf(type).qualifiedName.toString() 22 | } 23 | 24 | private fun getClassName(element: TypeElement, packageName: String): String { 25 | return element.qualifiedName.toString().substring(packageName.length + 1).replace('.', '$') 26 | } 27 | 28 | override fun toString(): String { 29 | return className.toString() 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /launcher/main/src/main/java/com/wisnu/launcher/main/BaseLauncher.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.main 2 | 3 | import android.app.Application as AndroidApplication 4 | 5 | abstract class BaseLauncher(final override val application: AndroidApplication) : Launcher { 6 | private val _applications: MutableList = mutableListOf() 7 | private val _features: MutableList = mutableListOf() 8 | 9 | override val applications: List 10 | get() = _applications 11 | override val features: List 12 | get() = _features 13 | 14 | override fun registerApplication(application: Application?) { 15 | if (application != null && isNotAdded(_applications, application)) { 16 | _applications.add(application) 17 | } 18 | } 19 | 20 | override fun registerFeature(featureLaunchable: FeatureLaunchable?) { 21 | if (featureLaunchable != null && isNotAdded(_features, featureLaunchable)) { 22 | _features.add(featureLaunchable) 23 | } 24 | } 25 | 26 | private fun isNotAdded(list: List, element: T): Boolean { 27 | return !list.contains(element) 28 | } 29 | 30 | override fun onCreate() { 31 | applications.forEach { it.onCreate(this) } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'kotlin-kapt' 5 | apply from: "$rootDir/build-system/dependencies-feature-generator.gradle" 6 | 7 | android { 8 | compileSdkVersion 28 9 | defaultConfig { 10 | applicationId "com.wisnu.ordertiket" 11 | minSdkVersion 19 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | project.config.each { module -> 27 | project.dependencies.add("implementation", project(":${module}")) 28 | } 29 | 30 | implementation project(':launcher:main') 31 | implementation project(':launcher:annotations') 32 | kapt project(':launcher:compiler') 33 | 34 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 35 | implementation 'androidx.appcompat:appcompat:1.0.2' 36 | implementation "androidx.cardview:cardview:1.0.0" 37 | implementation 'androidx.core:core-ktx:1.0.2' 38 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 39 | implementation "androidx.recyclerview:recyclerview:1.1.0" 40 | } 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Composable modular android app project 2 | 3 | #### Dependencies diagram 4 | 5 | 6 | #### Demo 7 | https://youtu.be/bq7rSJuaz7U 8 | 9 | #### Use case order ticket application that has multiple feature 10 | 1. Feature order flight 11 | 2. Feature order hotel 12 | 3. Feature order train 13 | 4. Feature transaction history 14 | 5. Feature setting 15 | 16 | #### Implementation step by step 17 | 1. [Implement abstraction between app module and feature module using launcher module.](https://github.com/wisnukurniawan/Composable-Module/commit/3096f22a766e9dde9fef797a62daf04b5ca5ff6f) This is to make our app module not tightly coupled to feature module. 18 | 2. [Implement dynamic code loading using code generator x reflection.](https://github.com/wisnukurniawan/Composable-Module/commit/ccd5642ad674ecf8f54d2ad21e9bee75c30cfa5c) This is the main part how to make our module can be composable. 19 | 3. How to integrate new feature. Use case, adding order bus feature. 20 | - [Add order bus feature module.](https://github.com/wisnukurniawan/Composable-Module/commit/ea43996b83e1804d88addca5c8c3e3ff103a769c) 21 | - [Register order bus module as feature.](https://github.com/wisnukurniawan/Composable-Module/commit/82e5631bbf223c298f90565e6d4bac72a2095ce9) 22 | 23 | #### Preview before after adding order bus feature 24 | 25 | 26 | #### Reference 27 | Scaling an Android App from 1 to 100 developers with modularization at Airbnb. https://youtube.com/watch?v=jrnhIgFzgns&t=466s -------------------------------------------------------------------------------- /launcher/compiler/src/main/java/com/wisnu/launcher/compiler/FeatureListWriter.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.compiler 2 | 3 | import com.squareup.javapoet.* 4 | import java.io.IOException 5 | import java.util.* 6 | import javax.annotation.processing.Filer 7 | import javax.lang.model.element.Modifier 8 | 9 | class FeatureListWriter(private val featureAnnotatedClass: FeatureAnnotatedClass) { 10 | 11 | @Throws(IOException::class) 12 | fun write(filer: Filer) { 13 | val classBuilder = TypeSpec.classBuilder("${featureAnnotatedClass.className.simpleName()}Utils") 14 | classBuilder.addModifiers(Modifier.PUBLIC, Modifier.FINAL) 15 | classBuilder.addMethod(createBuildFeaturesMethod()) 16 | JavaFile.builder(featureAnnotatedClass.className.packageName(), classBuilder.build()).build().writeTo(filer) 17 | } 18 | 19 | private fun createBuildFeaturesMethod(): MethodSpec { 20 | val methodName = "buildFeatures" 21 | val localVariableName = "features" 22 | val featureType = ClassName.get("com.wisnu.launcher.main", "Application") 23 | val listType = ClassName.get(List::class.java) 24 | val arrayListType = ClassName.get(ArrayList::class.java) 25 | val returnType = ParameterizedTypeName.get(listType, featureType) 26 | 27 | val buildFeatures = MethodSpec.methodBuilder(methodName) 28 | .addModifiers(Modifier.STATIC) 29 | .addModifiers(Modifier.FINAL) 30 | .returns(returnType) 31 | .addStatement("\$T $localVariableName = new \$T<>()", returnType, arrayListType) 32 | 33 | featureAnnotatedClass.features 34 | .filter { it.loadClassOrNull() != null } 35 | .forEach { buildFeatures.addStatement("$localVariableName.add(new $it())") } 36 | 37 | buildFeatures.addStatement("return $localVariableName") 38 | 39 | return buildFeatures.build() 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /launcher/compiler/src/main/java/com/wisnu/launcher/compiler/FeatureProcessor.kt: -------------------------------------------------------------------------------- 1 | package com.wisnu.launcher.compiler 2 | 3 | import com.wisnu.launcher.annotations.RegisterFeature 4 | import java.io.IOException 5 | import javax.annotation.processing.* 6 | import javax.lang.model.SourceVersion 7 | import javax.lang.model.element.TypeElement 8 | import javax.lang.model.util.Elements 9 | import javax.tools.Diagnostic 10 | import kotlin.properties.Delegates 11 | import javax.annotation.processing.ProcessingEnvironment 12 | 13 | class FeatureProcessor : AbstractProcessor() { 14 | private var filer: Filer by Delegates.notNull() 15 | private var messager: Messager by Delegates.notNull() 16 | private var elementUtils: Elements by Delegates.notNull() 17 | 18 | @Synchronized 19 | override fun init(processingEnv: ProcessingEnvironment) { 20 | super.init(processingEnv) 21 | filer = processingEnv.filer 22 | messager = processingEnv.messager 23 | elementUtils = processingEnv.elementUtils 24 | } 25 | 26 | override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latestSupported() 27 | 28 | override fun getSupportedAnnotationTypes(): Set = hashSetOf(RegisterFeature::class.java.canonicalName) 29 | 30 | override fun process(annotations: Set, roundEnv: RoundEnvironment): Boolean { 31 | parseEnv(roundEnv, elementUtils) 32 | .map { FeatureListWriter(it) } 33 | .forEach { 34 | try { 35 | it.write(filer) 36 | } catch (e: IOException) { 37 | messager.printMessage(Diagnostic.Kind.ERROR, e.message) 38 | } 39 | } 40 | return true 41 | } 42 | 43 | private fun parseEnv(roundEnv: RoundEnvironment, elementUtils: Elements): List { 44 | return roundEnv.getElementsAnnotatedWith(RegisterFeature::class.java).map { 45 | FeatureAnnotatedClass(it as TypeElement, elementUtils) 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_feature_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 23 | 24 | 35 | 36 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------