├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── art └── example.png ├── cookiecutter.json ├── hooks └── post_gen_project.py ├── requirements.txt └── {{cookiecutter.repo_name}} ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── kotlin │ │ ├── Application.kt │ │ ├── base │ │ │ ├── BaseActivity.kt │ │ │ └── IBaseView.kt │ │ ├── di │ │ │ ├── component │ │ │ │ └── ApplicationComponent.kt │ │ │ ├── module │ │ │ │ ├── ApplicationModule.kt │ │ │ │ ├── DatabaseModule.kt │ │ │ │ └── NetModule.kt │ │ │ └── scope │ │ │ │ └── ActivityScope.kt │ │ ├── main │ │ │ ├── IMainView.kt │ │ │ ├── MainActivity.kt │ │ │ ├── MainComponent.kt │ │ │ ├── MainModule.kt │ │ │ └── MainPresenter.kt │ │ ├── splash │ │ │ └── SplashActivity.kt │ │ └── utils │ │ │ ├── RxBus.kt │ │ │ └── timber │ │ │ └── CrashReportTree.kt │ └── res │ │ ├── drawable │ │ ├── android_starter.png │ │ └── splash_logo.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── menu │ │ └── menu_main.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 │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | *~ 4 | 5 | # Android Studio 6 | .idea/ 7 | .gradle 8 | local.properties 9 | /*/out 10 | build 11 | *.iml 12 | *.iws 13 | *.ipr 14 | *.swp 15 | 16 | # built application files 17 | *.apk 18 | *.ap_ 19 | 20 | # files for the dex VM 21 | *.dex 22 | 23 | # Java class files 24 | *.class 25 | 26 | # generated files 27 | bin/ 28 | gen/ 29 | 30 | # Eclipse project files 31 | .classpath 32 | .project 33 | 34 | # Proguard folder generated by Eclipse 35 | proguard/s 36 | 37 | /local.properties 38 | /.idea/workspace.xml 39 | /.idea/libraries 40 | /build 41 | /captures 42 | .externalNativeBuild 43 | /apk 44 | .idea/encodings.xml 45 | /gradle.properties -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 General Mobile 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Kotlin MVP Starter 2 | 3 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/master/LICENSE) 4 | [![Platform](https://img.shields.io/badge/platform-Android-green.svg)](http://developer.android.com/index.html) 5 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Android%20Kotlin%20MVP%20Starter-brightgreen.svg?style=flat)](https://android-arsenal.com/details/3/5791) 6 | 7 | Android Kotlin Starter is a starter project which implements MVP Pattern. 8 | 9 | ## Thanks 10 | This project extends from [Deniz Tunç Tuncer](https://github.com/dtunctuncer)'s [Android Starter](https://github.com/dtunctuncer/android-mvp-starter) project 11 | 12 | ## Libraries 13 | It includes libraries 14 | - [RxJava2](https://github.com/ReactiveX/RxJava) and [RxAndroid](https://github.com/ReactiveX/RxAndroid) and [RxKotlin](https://github.com/ReactiveX/RxKotlin) 15 | - [Retrofit](http://square.github.io/retrofit/) / [OkHttp](http://square.github.io/okhttp/) 16 | - [Gson](https://github.com/google/gson) 17 | - [Dagger 2](http://google.github.io/dagger/) 18 | - [Butterknife](https://github.com/JakeWharton/butterknife) 19 | - [Timber](https://github.com/JakeWharton/timber) 20 | - [Espresso](https://google.github.io/android-testing-support-library/) for UI tests 21 | - [Crashlytics](https://try.crashlytics.com/) 22 | - [Realm](https://realm.io/) 23 | - [Picasso](http://square.github.io/picasso/) 24 | 25 | **You can choose which library you want to include in your project** 26 | 27 | ![Terminal](art/example.png) 28 | 29 | #### Requirements 30 | 31 | [python](https://www.python.org/) 32 | [pip](https://pypi.python.org/pypi/pip) 33 | [cookiecutter](https://github.com/audreyr/cookiecutter) 34 | 35 | #### Install 36 | ``` 37 | 1. Install python 38 | 2. Install pip 39 | 3. pip install cookiecutter 40 | ``` 41 | 42 | Scaffold your project: 43 | ``` 44 | cookiecutter https://github.com/general-mobile/kotlin-android-mvp-starter.git 45 | ``` 46 | 47 | 48 | ##### Project Tree After Scaffold 49 | ```bash 50 | . 51 | ├── app 52 | │ ├── app.iml 53 | │ ├── build.gradle 54 | │ ├── proguard-rules.pro 55 | │ └── src 56 | │ ├── androidTest 57 | │ │ └── java 58 | │ │ └── com 59 | │ │ └── generalmobile 60 | │ │ └── app 61 | │ │ └── test 62 | │ │ └── ApplicationTest.java 63 | │ ├── main 64 | │ │ ├── AndroidManifest.xml 65 | │ │ ├── kotlin 66 | │ │ │ └── com 67 | │ │ │ └── generalmobile 68 | │ │ │ └── app 69 | │ │ │ └── test 70 | │ │ │ ├── Application.kt 71 | │ │ │ ├── base 72 | │ │ │ │ ├── BaseActivity.kt 73 | │ │ │ │ └── IBaseView.kt 74 | │ │ │ ├── di 75 | │ │ │ │ ├── component 76 | │ │ │ │ │ └── ApplicationComponent.kt 77 | │ │ │ │ ├── module 78 | │ │ │ │ │ ├── ApplicationModule.kt 79 | │ │ │ │ │ ├── DatabaseModule.kt 80 | │ │ │ │ │ └── NetModule.kt 81 | │ │ │ │ └── scope 82 | │ │ │ │ └── ActivityScope.kt 83 | │ │ │ ├── main 84 | │ │ │ │ ├── IMainView.kt 85 | │ │ │ │ ├── MainActivity.kt 86 | │ │ │ │ ├── MainComponent.kt 87 | │ │ │ │ ├── MainModule.kt 88 | │ │ │ │ └── MainPresenter.kt 89 | │ │ │ ├── splash 90 | │ │ │ │ └── SplashActivity.kt 91 | │ │ │ └── utils 92 | │ │ │ ├── RxBus.kt 93 | │ │ │ └── timber 94 | │ │ │ └── CrashReportTree.kt 95 | │ │ └── res 96 | │ │ ├── drawable 97 | │ │ │ ├── android_starter.png 98 | │ │ │ └── splash_logo.xml 99 | │ │ ├── layout 100 | │ │ │ └── activity_main.xml 101 | │ │ ├── menu 102 | │ │ │ └── menu_main.xml 103 | │ │ ├── mipmap-hdpi 104 | │ │ │ ├── ic_launcher.png 105 | │ │ │ └── ic_launcher_round.png 106 | │ │ ├── mipmap-mdpi 107 | │ │ │ ├── ic_launcher.png 108 | │ │ │ └── ic_launcher_round.png 109 | │ │ ├── mipmap-xhdpi 110 | │ │ │ ├── ic_launcher.png 111 | │ │ │ └── ic_launcher_round.png 112 | │ │ ├── mipmap-xxhdpi 113 | │ │ │ ├── ic_launcher.png 114 | │ │ │ └── ic_launcher_round.png 115 | │ │ ├── mipmap-xxxhdpi 116 | │ │ │ ├── ic_launcher.png 117 | │ │ │ └── ic_launcher_round.png 118 | │ │ ├── values 119 | │ │ │ ├── colors.xml 120 | │ │ │ ├── dimens.xml 121 | │ │ │ ├── strings.xml 122 | │ │ │ └── styles.xml 123 | │ │ ├── values-v21 124 | │ │ │ └── styles.xml 125 | │ │ └── values-w820dp 126 | │ │ └── dimens.xml 127 | │ └── test 128 | │ └── java 129 | │ └── com 130 | │ └── generalmobile 131 | │ └── app 132 | │ └── test 133 | │ └── ExampleUnitTest.java 134 | ├── build.gradle 135 | ├── gradle 136 | │ └── wrapper 137 | │ ├── gradle-wrapper.jar 138 | │ └── gradle-wrapper.properties 139 | ├── gradle.properties 140 | ├── gradlew 141 | ├── gradlew.bat 142 | ├── local.properties 143 | ├── settings.gradle 144 | └── test.iml 145 | 146 | 43 directories, 51 files 147 | ``` 148 | 149 | 150 | ## License 151 | 152 | The MIT License (MIT) 153 | 154 | Copyright (c) 2017 General Mobile 155 | 156 | Permission is hereby granted, free of charge, to any person obtaining a copy 157 | of this software and associated documentation files (the "Software"), to deal 158 | in the Software without restriction, including without limitation the rights 159 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 160 | copies of the Software, and to permit persons to whom the Software is 161 | furnished to do so, subject to the following conditions: 162 | 163 | The above copyright notice and this permission notice shall be included in all 164 | copies or substantial portions of the Software. 165 | 166 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 169 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 170 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 171 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 172 | SOFTWARE. 173 | -------------------------------------------------------------------------------- /art/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/art/example.png -------------------------------------------------------------------------------- /cookiecutter.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_name": "kotlin-starter-project", 3 | "repo_name": "{{ cookiecutter.project_name|lower|replace(' ', '-') }}", 4 | "min_sdk": 16, 5 | "target_sdk": 25, 6 | "package_name": "com.generalmobile.app.{{ cookiecutter.project_name|lower|replace(' ', '')|replace('-', '') }}", 7 | "description": "A short description of the project.", 8 | "author": "General Mobile", 9 | "email": "generalmobiledev@gmail.com", 10 | "version": "1.0.0", 11 | "splash_screen": "n", 12 | "retrofit": "n", 13 | "realm": "n", 14 | "picasso": "n", 15 | "kotlin_android_extensions": "n" 16 | } 17 | -------------------------------------------------------------------------------- /hooks/post_gen_project.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import shutil 6 | 7 | project_dir = os.getcwd() 8 | 9 | package_dir = '{{ cookiecutter.package_name }}'.replace('.', '/') 10 | 11 | os.chdir(os.path.join("app","src","androidTest","java")) 12 | os.makedirs(package_dir) 13 | shutil.move('ApplicationTest.java', package_dir + '/ApplicationTest.java') 14 | 15 | os.chdir(os.path.join(project_dir,"app","src","main","kotlin")) 16 | os.makedirs(package_dir) 17 | 18 | 19 | os.chdir(os.path.join(project_dir,"app","src","test","java")) 20 | os.makedirs(package_dir) 21 | shutil.move('ExampleUnitTest.java', package_dir + '/ExampleUnitTest.java') 22 | 23 | os.chdir(os.path.join(project_dir,"app","src","main","kotlin",package_dir)) 24 | os.chdir(os.path.join(project_dir,"app","src","main","kotlin")) 25 | 26 | root_dst_dir = os.path.join(project_dir,"app","src","main","kotlin",package_dir) 27 | root_src_dir = os.path.join(project_dir,"app","src","main","kotlin") 28 | 29 | if '{{ cookiecutter.splash_screen }}' != 'y': 30 | shutil.rmtree('splash') 31 | 32 | if '{{ cookiecutter.retrofit }}' != 'y': 33 | os.remove('di/module/NetModule.kt') 34 | 35 | if '{{ cookiecutter.realm }}' != 'y': 36 | os.remove('di/module/DatabaseModule.kt') 37 | 38 | 39 | base = os.path.join(root_src_dir,"base") 40 | di = os.path.join(root_src_dir,"di") 41 | splash = os.path.join(root_src_dir,"splash") 42 | utils = os.path.join(root_src_dir,"utils") 43 | main = os.path.join(root_src_dir,"main") 44 | 45 | shutil.move('Application.kt',os.path.join(project_dir,"app","src","main","kotlin",package_dir,"Application.kt")) 46 | 47 | def moverecursively(source_folder, destination_folder): 48 | basename = os.path.basename(source_folder) 49 | dest_dir = os.path.join(destination_folder, basename) 50 | if not os.path.exists(dest_dir): 51 | shutil.move(source_folder, destination_folder) 52 | else: 53 | dst_path = os.path.join(destination_folder, basename) 54 | for root, dirs, files in os.walk(source_folder): 55 | for item in files: 56 | src_path = os.path.join(root, item) 57 | if os.path.exists(dst_file): 58 | os.remove(dst_file) 59 | shutil.move(src_path, dst_path) 60 | for item in dirs: 61 | src_path = os.path.join(root, item) 62 | moverecursively(src_path, dst_path) 63 | 64 | moverecursively(base,root_dst_dir) 65 | moverecursively(di,root_dst_dir) 66 | moverecursively(utils,root_dst_dir) 67 | moverecursively(main,root_dst_dir) 68 | 69 | if '{{ cookiecutter.splash_screen }}' == 'y': 70 | moverecursively(splash,root_dst_dir) 71 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | cookiecutter==1.3.0 2 | python==2.7.13 3 | pip==1.5.4 -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url 'https://maven.fabric.io/public' } 4 | } 5 | 6 | dependencies { 7 | classpath 'io.fabric.tools:gradle:1.+' 8 | } 9 | } 10 | 11 | apply plugin: 'com.android.application' 12 | apply plugin: 'kotlin-android' 13 | apply plugin: 'kotlin-kapt' 14 | {% if cookiecutter.kotlin_android_extensions == "y" %} 15 | apply plugin: 'kotlin-android-extensions' 16 | {% endif %} 17 | {% if cookiecutter.realm == "y" %} 18 | apply plugin: 'realm-android' 19 | {% endif %} 20 | 21 | def STRING = 'String' 22 | def BUILD_TIME = 'BUILD_TIME' 23 | 24 | apply plugin: 'io.fabric' 25 | 26 | repositories { 27 | maven { url 'https://maven.fabric.io/public' } 28 | } 29 | 30 | android { 31 | compileSdkVersion rootProject.ext.compileSdkVersion 32 | buildToolsVersion "25.0.3" 33 | 34 | defaultConfig { 35 | applicationId "{{ cookiecutter.package_name }}" 36 | minSdkVersion rootProject.ext.minSdkVersion 37 | targetSdkVersion rootProject.ext.targetSdkVersion 38 | versionCode 1 39 | versionName "{{ cookiecutter.version }}" 40 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 41 | buildConfigField STRING, BUILD_TIME, "\"${rootProject.ext.buildTime}\"" 42 | } 43 | buildTypes { 44 | release { 45 | minifyEnabled true 46 | zipAlignEnabled true 47 | shrinkResources true 48 | debuggable false 49 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 50 | } 51 | } 52 | sourceSets{ 53 | main.java.srcDirs += 'src/main/kotlin' 54 | } 55 | packagingOptions { 56 | exclude 'META-INF/rxjava.properties' 57 | } 58 | } 59 | 60 | dependencies { 61 | compile fileTree(dir: 'libs', include: ['*.jar']) 62 | 63 | //supportLib 64 | compile rootProject.ext.supportLib 65 | compile rootProject.ext.supportLibAppCompat 66 | compile rootProject.ext.supportLibDesign 67 | compile rootProject.ext.supportLibRecyclerview 68 | compile rootProject.ext.supportLibCardview 69 | 70 | //timber 71 | compile rootProject.ext.timber 72 | 73 | //crashlytics 74 | compile (rootProject.ext.crashlytics){ 75 | transitive = true; 76 | } 77 | 78 | //di 79 | compile rootProject.ext.dagger 80 | kapt rootProject.ext.daggerApt 81 | //compile rootProject.ext.daggerSupport 82 | //annotationProcessor rootProject.ext.daggerAnnotation 83 | 84 | //rx 85 | compile rootProject.ext.rxJava 86 | compile rootProject.ext.rxAndroid 87 | compile rootProject.ext.rxKotlin 88 | 89 | {% if cookiecutter.retrofit == "y" %} 90 | //net 91 | compile rootProject.ext.retrofit 92 | compile rootProject.ext.okHttp 93 | compile rootProject.ext.gson 94 | compile rootProject.ext.rxJavaAdapter 95 | compile rootProject.ext.gsonConverter 96 | {% endif %} 97 | 98 | {% if cookiecutter.picasso == "y" %} 99 | //picasso 100 | compile rootProject.ext.picasso 101 | {% endif %} 102 | 103 | //test 104 | testCompile 'junit:junit:4.12' 105 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 106 | exclude group: 'com.android.support', module: 'support-annotations' 107 | exclude group: 'com.google.code.findbugs' 108 | }) 109 | compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 110 | } 111 | repositories { 112 | mavenCentral() 113 | } 114 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/volkan/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/androidTest/java/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | {% if cookiecutter.splash_screen == "y" %} 13 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {% endif %} 27 | {% if cookiecutter.splash_screen == "n" %} 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {% endif %} 39 | 40 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/Application.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }} 2 | 3 | import {{ cookiecutter.package_name }}.utils.timber.CrashReportTree 4 | import timber.log.Timber 5 | import com.crashlytics.android.Crashlytics 6 | import io.fabric.sdk.android.Fabric 7 | import com.crashlytics.android.core.CrashlyticsCore 8 | import {{ cookiecutter.package_name }}.di.module.ApplicationModule 9 | import {{ cookiecutter.package_name }}.di.component.ApplicationComponent 10 | import {{ cookiecutter.package_name }}.di.component.DaggerApplicationComponent 11 | 12 | 13 | class Application : android.app.Application() { 14 | 15 | override fun onCreate() { 16 | super.onCreate() 17 | 18 | //di 19 | component = DaggerApplicationComponent.builder().applicationModule(ApplicationModule(this)).build() 20 | 21 | //Crashlytics 22 | val core = CrashlyticsCore.Builder() 23 | .disabled(BuildConfig.DEBUG) 24 | .build() 25 | 26 | Fabric.with(this, Crashlytics.Builder().core(core).build()) 27 | 28 | if (BuildConfig.DEBUG) { 29 | Timber.plant(Timber.DebugTree()) 30 | } else { 31 | Timber.plant(CrashReportTree()) 32 | } 33 | } 34 | 35 | companion object { 36 | 37 | var component: ApplicationComponent? = null 38 | private set 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/base/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.base 2 | 3 | import android.os.Bundle 4 | import android.os.PersistableBundle 5 | import android.support.v7.app.AppCompatActivity 6 | 7 | open class BaseActivity : AppCompatActivity(), IBaseView { 8 | 9 | override fun onCreate(savedInstanceState: Bundle?) { 10 | super.onCreate(savedInstanceState) 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/base/IBaseView.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.base 2 | 3 | interface IBaseView{ 4 | 5 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/di/component/ApplicationComponent.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.di.component 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import {{ cookiecutter.package_name }}.Application 6 | import {{ cookiecutter.package_name }}.di.module.ApplicationModule 7 | {% if cookiecutter.realm == "y" %} 8 | import {{ cookiecutter.package_name }}.di.module.DatabaseModule 9 | {% endif %} 10 | {% if cookiecutter.retrofit == "y" %} 11 | import {{ cookiecutter.package_name }}.di.module.NetModule 12 | {% endif %} 13 | import dagger.Component 14 | import javax.inject.Singleton 15 | 16 | @Singleton 17 | {% if cookiecutter.retrofit == "n" and cookiecutter.realm == "n" %} 18 | @Component(modules = arrayOf(ApplicationModule::class)) 19 | {% endif %} 20 | {% if cookiecutter.retrofit == "y" and cookiecutter.realm == "y" %} 21 | @Component(modules = arrayOf(ApplicationModule::class,NetModule::class,DatabaseModule::class)) 22 | {% endif %} 23 | {% if cookiecutter.realm == "y" and cookiecutter.retrofit == "n" %} 24 | @Component(modules = arrayOf(ApplicationModule::class,DatabaseModule::class)) 25 | {% endif %} 26 | {% if cookiecutter.realm == "n" and cookiecutter.retrofit == "y" %} 27 | @Component(modules = arrayOf(ApplicationModule::class,NetModule::class)) 28 | {% endif %} 29 | 30 | interface ApplicationComponent { 31 | fun app(): Application 32 | 33 | fun context(): Context 34 | 35 | fun preferences(): SharedPreferences 36 | } 37 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/di/module/ApplicationModule.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.di.module 2 | 3 | import android.content.Context 4 | import android.content.SharedPreferences 5 | import android.preference.PreferenceManager 6 | import {{ cookiecutter.package_name }}.Application 7 | import {{ cookiecutter.package_name }}.utils.RxBus 8 | import dagger.Module 9 | import dagger.Provides 10 | import javax.inject.Singleton 11 | 12 | @Module 13 | class ApplicationModule(var app: Application) { 14 | 15 | 16 | @Provides 17 | @Singleton 18 | fun provideApp(): Application = app 19 | 20 | @Provides 21 | @Singleton 22 | fun provideContext(): Context = app.applicationContext 23 | 24 | @Provides 25 | @Singleton 26 | fun provideSharedPreferences(): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(app) 27 | 28 | @Provides 29 | @Singleton 30 | fun provideBus(): RxBus = RxBus() 31 | } 32 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/di/module/DatabaseModule.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.di.module 2 | 3 | import android.content.Context 4 | import dagger.Module 5 | import dagger.Provides 6 | import io.realm.Realm 7 | import javax.inject.Singleton 8 | 9 | @Module 10 | class DatabaseModule { 11 | 12 | @Provides 13 | @Singleton 14 | fun provideRealm(context: Context): Realm { 15 | Realm.init(context) 16 | return Realm.getDefaultInstance() 17 | } 18 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/di/module/NetModule.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.di.module 2 | 3 | import android.os.Environment 4 | import dagger.Module 5 | import dagger.Provides 6 | import okhttp3.OkHttpClient 7 | import javax.inject.Named 8 | import javax.inject.Singleton 9 | import javax.xml.datatype.DatatypeConstants.MINUTES 10 | import android.os.Environment.getDownloadCacheDirectory 11 | import okhttp3.Cache 12 | import java.util.concurrent.TimeUnit 13 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory 14 | import retrofit2.converter.gson.GsonConverterFactory 15 | import retrofit2.Retrofit 16 | import com.google.gson.Gson 17 | import com.google.gson.FieldNamingPolicy 18 | import com.google.gson.GsonBuilder 19 | 20 | 21 | @Module 22 | class NetModule { 23 | @Singleton 24 | @Provides 25 | @Named("cached") 26 | fun provideOkHttpClient(): OkHttpClient { 27 | val cache = Cache(Environment.getDownloadCacheDirectory(), 10 * 1024 * 1024) 28 | return OkHttpClient.Builder() 29 | .readTimeout(1, TimeUnit.MINUTES) 30 | .writeTimeout(1, TimeUnit.MINUTES) 31 | .cache(cache) 32 | .build() 33 | } 34 | 35 | @Singleton 36 | @Provides 37 | @Named("non_cached") 38 | fun provideNonCachedOkHttpClient(): OkHttpClient { 39 | return OkHttpClient.Builder() 40 | .readTimeout(1, TimeUnit.MINUTES) 41 | .writeTimeout(1, TimeUnit.MINUTES) 42 | .build() 43 | } 44 | 45 | @Provides 46 | @Singleton 47 | fun provideGson(): Gson { 48 | val gsonBuilder = GsonBuilder() 49 | gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) 50 | return gsonBuilder.create() 51 | } 52 | 53 | @Singleton 54 | @Provides 55 | fun provideRetrofit(gson: Gson, @Named("cached") client: OkHttpClient): Retrofit.Builder { 56 | return Retrofit.Builder() 57 | .client(client) 58 | .addConverterFactory(GsonConverterFactory.create(gson)) 59 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 60 | } 61 | 62 | /** 63 | * Example service 64 | */ 65 | /*@Provides 66 | @Singleton 67 | WordpressService provideService(Retrofit.Builder builder) { 68 | return builder.baseUrl(BuildConfig.API_URL) 69 | .build() 70 | .create(WordpressService.class); 71 | } 72 | */ 73 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/di/scope/ActivityScope.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.di.scope 2 | 3 | import javax.inject.Scope 4 | import kotlin.annotation.Retention; 5 | 6 | 7 | @Scope 8 | @Retention(AnnotationRetention.RUNTIME) 9 | annotation class ActivityScope -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/main/IMainView.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.main 2 | 3 | interface IMainView { 4 | 5 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/main/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.main 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import android.os.Bundle 5 | import {{ cookiecutter.package_name }}.R 6 | import {{ cookiecutter.package_name }}.Application 7 | import javax.inject.Inject 8 | 9 | class MainActivity : AppCompatActivity(), IMainView { 10 | 11 | @Inject 12 | lateinit var presenter : MainPresenter 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | setContentView(R.layout.activity_main) 17 | DaggerMainComponent.builder().applicationComponent(Application.component).mainModule(MainModule(this)).build().inject(this) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/main/MainComponent.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.main 2 | 3 | import {{ cookiecutter.package_name }}.di.component.ApplicationComponent 4 | import {{ cookiecutter.package_name }}.di.scope.ActivityScope 5 | import dagger.Component 6 | 7 | 8 | @ActivityScope 9 | @Component(modules = arrayOf(MainModule::class), dependencies = arrayOf(ApplicationComponent::class)) 10 | interface MainComponent { 11 | fun inject(activity: MainActivity) 12 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/main/MainModule.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.main 2 | 3 | import {{ cookiecutter.package_name }}.di.scope.ActivityScope 4 | import dagger.Module 5 | import dagger.Provides 6 | 7 | 8 | @Module 9 | class MainModule(private val view: IMainView) { 10 | 11 | @Provides 12 | @ActivityScope 13 | internal fun provideView(): IMainView { 14 | return view 15 | } 16 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/main/MainPresenter.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.main 2 | 3 | import javax.inject.Inject 4 | 5 | 6 | class MainPresenter @Inject 7 | constructor(private val view: IMainView) -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/splash/SplashActivity.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.splash 2 | 3 | import {{ cookiecutter.package_name }}.main.MainActivity 4 | import android.content.Intent 5 | import android.support.v4.content.ContextCompat.startActivity 6 | import android.os.Bundle 7 | import {{ cookiecutter.package_name }}.base.BaseActivity 8 | 9 | 10 | class SplashActivity : BaseActivity() { 11 | 12 | override fun onCreate(savedInstanceState: Bundle?) { 13 | super.onCreate(savedInstanceState) 14 | startActivity(Intent(this, MainActivity::class.java)) 15 | finish() 16 | } 17 | } -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/utils/RxBus.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.utils 2 | 3 | import io.reactivex.Observable 4 | import io.reactivex.subjects.PublishSubject 5 | 6 | 7 | class RxBus { 8 | private val bus = PublishSubject.create() 9 | 10 | fun send(o: Any) { 11 | bus.onNext(o) 12 | } 13 | 14 | fun toObservable(): Observable { 15 | return bus 16 | } 17 | 18 | fun hasObservers(): Boolean { 19 | return bus.hasObservers() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/kotlin/utils/timber/CrashReportTree.kt: -------------------------------------------------------------------------------- 1 | package {{ cookiecutter.package_name }}.utils.timber 2 | 3 | import android.util.Log 4 | import com.crashlytics.android.Crashlytics 5 | import timber.log.Timber 6 | 7 | 8 | class CrashReportTree : Timber.Tree() { 9 | 10 | private val CRASHLYTICS_KEY_PRIORITY = "priority" 11 | private val CRASHLYTICS_KEY_TAG = "tag" 12 | private val CRASHLYTICS_KEY_MESSAGE = "message" 13 | 14 | override fun log(priority: Int, tag: String, message: String, t: Throwable?) { 15 | if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) { 16 | return 17 | } 18 | 19 | Crashlytics.setInt(CRASHLYTICS_KEY_PRIORITY, priority) 20 | Crashlytics.setString(CRASHLYTICS_KEY_TAG, tag) 21 | Crashlytics.setString(CRASHLYTICS_KEY_MESSAGE, message) 22 | 23 | if (t == null) { 24 | Crashlytics.logException(Exception(message)) 25 | } else { 26 | Crashlytics.logException(t) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/drawable/android_starter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/drawable/android_starter.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/drawable/splash_logo.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 10 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/general-mobile/kotlin-android-mvp-starter/ea33c498950d36ef6285609258d59a49d823af46/{{cookiecutter.repo_name}}/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 64dp 7 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | 8 | #FFFFFF 9 | 10 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | {{ cookiecutter.project_name|replace('-', '')|replace('_', '')|title }} 3 | Settings 4 | Ana Sayfa 5 | Hakkında 6 | Çıkış 7 | Open 8 | Close 9 | 10 | -------------------------------------------------------------------------------- /{{cookiecutter.repo_name}}/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | {% if cookiecutter.splash_screen == "y" %} 16 | 19 | {% endif %} 20 | 21 |