├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── blank.yml
├── .gitignore
├── .idea
├── .name
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── compiler.xml
├── gradle.xml
├── jarRepositories.xml
├── markdown-navigator-enh.xml
├── markdown-navigator.xml
├── misc.xml
└── vcs.xml
├── LICENSE
├── README.md
├── _config.yml
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── technorapper
│ │ └── boiler
│ │ └── ui
│ │ └── onboarding
│ │ └── activity
│ │ ├── MainActivityTest.kt
│ │ └── UiRunner.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── technorapper
│ │ │ └── boiler
│ │ │ ├── application
│ │ │ └── App.kt
│ │ │ ├── constants
│ │ │ ├── DatabaseConstants.kt
│ │ │ ├── GlobalVariables.kt
│ │ │ └── Preferences.java
│ │ │ ├── data
│ │ │ ├── Result.kt
│ │ │ ├── models
│ │ │ │ ├── APIResponse.kt
│ │ │ │ ├── UserTableModel.kt
│ │ │ │ ├── base
│ │ │ │ │ └── BaseDaoModel.kt
│ │ │ │ ├── repo
│ │ │ │ │ ├── License.kt
│ │ │ │ │ ├── Owner.kt
│ │ │ │ │ ├── UserRepo.kt
│ │ │ │ │ └── UserRepoItem.kt
│ │ │ │ └── response
│ │ │ │ │ ├── BasicResponse.kt
│ │ │ │ │ ├── Result.kt
│ │ │ │ │ └── socket
│ │ │ │ │ └── SocketModel.kt
│ │ │ ├── repository
│ │ │ │ ├── BaseRepository.kt
│ │ │ │ └── MainActivityRepository.kt
│ │ │ ├── tunnel
│ │ │ │ ├── database
│ │ │ │ │ ├── TechnorapperDriverDatabase.kt
│ │ │ │ │ └── dao
│ │ │ │ │ │ └── UserMasterDao.kt
│ │ │ │ └── remote
│ │ │ │ │ ├── ASynchronousSocket.kt
│ │ │ │ │ ├── SynchronousApi.kt
│ │ │ │ │ └── utils
│ │ │ │ │ ├── AppSocket.kt
│ │ │ │ │ ├── CheckInternetConnection.kt
│ │ │ │ │ └── CustomObserable.kt
│ │ │ └── utils
│ │ │ │ ├── RoomConverters.kt
│ │ │ │ └── TimestampConverter.kt
│ │ │ ├── di
│ │ │ ├── AppInjector.kt
│ │ │ ├── AppSocketServiceFactory.kt
│ │ │ ├── WDViewModelFactory.kt
│ │ │ ├── builder
│ │ │ │ ├── ActivityBuilder.kt
│ │ │ │ ├── BroadcastBuilder.kt
│ │ │ │ ├── FragmentBuilder.kt
│ │ │ │ └── ServiceBuilder.kt
│ │ │ ├── component
│ │ │ │ ├── AppComponent.kt
│ │ │ │ └── BindingComponent.kt
│ │ │ ├── module
│ │ │ │ ├── AppModule.kt
│ │ │ │ ├── BindingModule.kt
│ │ │ │ ├── DataBaseModule.kt
│ │ │ │ ├── NetworkModule.kt
│ │ │ │ ├── PreferenceModule.kt
│ │ │ │ ├── ViewModelKey.kt
│ │ │ │ └── ViewModelModule.kt
│ │ │ └── scopes
│ │ │ │ ├── ActivityScoped.kt
│ │ │ │ ├── ApplicationScoped.kt
│ │ │ │ ├── BindingScoped.kt
│ │ │ │ └── RandomUserApplicationScope.kt
│ │ │ ├── global
│ │ │ └── CustomBindingAdapter.kt
│ │ │ ├── helpers
│ │ │ └── AppPrefs.kt
│ │ │ └── ui
│ │ │ ├── base
│ │ │ ├── BaseActivity.kt
│ │ │ └── BaseViewModel.kt
│ │ │ └── onboarding
│ │ │ └── activity
│ │ │ ├── MainActivity.kt
│ │ │ └── MainActivityViewModel.kt
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.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
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ └── network_security_config.xml
│ └── test
│ └── java
│ └── com
│ └── technorapper
│ └── boiler
│ └── ui
│ └── onboarding
│ └── activity
│ ├── MainActivityDaggerTest.kt
│ ├── TestApp.kt
│ ├── TestAppComponent.kt
│ ├── TestApplicationModule.kt
│ └── TestPrefModule.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/blank.yml:
--------------------------------------------------------------------------------
1 | name: Android_CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | jobs:
8 | build:
9 |
10 | runs-on: macos-latest
11 | strategy:
12 | matrix:
13 | api-level: [28]
14 | target: [default, google_apis]
15 | steps:
16 | - uses: actions/checkout@v1
17 | - name: set up JDK 1.8
18 | uses: actions/setup-java@v1
19 | with:
20 | java-version: 1.8
21 | - name: Build with Gradle
22 | run: bash ./gradlew assembleDebug --stacktrace
23 |
24 | - name: Upload APK
25 | uses: actions/upload-artifact@v1
26 | with:
27 | name: app
28 | path: app/build/outputs/apk/debug/app-debug.apk
29 |
30 | - name: checkout
31 | uses: actions/checkout@v2
32 |
33 | - uses: reactivecircus/android-emulator-runner@v2
34 | with:
35 | api-level: ${{ matrix.api-level }}
36 | target: ${{ matrix.target }}
37 | arch: x86_64
38 | profile: Nexus 6
39 | script: ./gradlew connectedCheck --stacktrace
40 |
41 | - name: TEST 2
42 | run: ./gradlew test --stacktrace
43 |
44 |
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | exampleForDriver
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | xmlns:android
17 |
18 | ^$
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | xmlns:.*
28 |
29 | ^$
30 |
31 |
32 | BY_NAME
33 |
34 |
35 |
36 |
37 |
38 |
39 | .*:id
40 |
41 | http://schemas.android.com/apk/res/android
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | .*:name
51 |
52 | http://schemas.android.com/apk/res/android
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | name
62 |
63 | ^$
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | style
73 |
74 | ^$
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | .*
84 |
85 | ^$
86 |
87 |
88 | BY_NAME
89 |
90 |
91 |
92 |
93 |
94 |
95 | .*
96 |
97 | http://schemas.android.com/apk/res/android
98 |
99 |
100 | ANDROID_ATTRIBUTE_ORDER
101 |
102 |
103 |
104 |
105 |
106 |
107 | .*
108 |
109 | .*
110 |
111 |
112 | BY_NAME
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator-enh.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Base for Android Application using Kotlin
2 |
3 | An enterprise-level Kotlin MVVM boilerplate to help you start building Android applications in minutes.
4 |
5 | ## Overview
6 |
7 | This repository is designed to provide developers with a clean and scalable base for starting new Android applications using Kotlin. The project utilizes modern architecture patterns and libraries, enabling rapid development while ensuring maintainability and scalability.
8 |
9 | ## Architecture
10 |
11 | This project follows the **MVVM (Model-View-ViewModel)** architecture pattern, offering separation of concerns, easier testing, and the use of Jetpack components.
12 |
13 |
14 |
15 | ---
16 |
17 | ## Technology Stack
18 |
19 | This boilerplate includes an extensive technology stack that allows developers to build robust and scalable Android applications.
20 |
21 | ### Language
22 |
23 | - **Kotlin 1.3.61** - Modern programming language designed to improve productivity, readability, and safety.
24 |
25 | ### Architecture
26 |
27 | - **MVVM** - Ensures separation of business logic from UI components, promoting maintainability and testability.
28 |
29 | ### Database Layer
30 |
31 | - **Room 2.2.2** - A persistence library that provides an abstraction layer over SQLite, making database operations more manageable.
32 |
33 | ### Dependency Injection
34 |
35 | - **Dagger 2.15** - A powerful dependency injection framework to help manage and inject dependencies efficiently.
36 |
37 | ### Flow Management
38 |
39 | - **Coroutines 1.2.1** - Provides asynchronous programming capabilities with a simpler and more efficient API.
40 | - **RxKotlin 2.4.0** - Reactive programming support for Kotlin.
41 | - **RxAndroid 2.1.1** - Reactive Extensions for Android’s main UI thread.
42 | - **Lifecycle 2.1.0** - Android architecture component to handle lifecycle-aware components.
43 |
44 | ### Networking
45 |
46 | - **Retrofit 2.7.0** - A type-safe HTTP client for Android and Java.
47 | - **OkHttp 3.12.0** - An efficient HTTP client that supports HTTP/2, connection pooling, and more.
48 | - **Socket.IO 0.6.0** - Provides real-time, bidirectional communication between the client and server.
49 |
50 | ### Image Loading & Processing
51 |
52 | - **Picasso 2.71828** - A powerful image downloading and caching library for Android, making image handling simple and efficient.
53 |
54 | ### JSON Parsing
55 |
56 | - **Moshi 1.9.0** - A modern JSON library for Android and Java, offering full support for Kotlin.
57 | - **Gson 2.8.6** - A widely used library for converting JSON to Java objects and vice versa.
58 |
59 | ### Logging
60 |
61 | - **Timber 4.7.1** - A flexible logging library, improving upon Android's default `Log` class.
62 |
63 | ### UI Testing
64 |
65 | - **Espresso** - A UI testing framework that allows you to simulate user interactions and test your application's behavior.
66 |
67 | ---
68 |
69 | ## Getting Started
70 |
71 | Follow these instructions to get a copy of the project up and running on your local machine for development and testing purposes.
72 |
73 | ### Prerequisites
74 |
75 | - Android Studio (latest version)
76 | - Gradle (as per Android Studio configuration)
77 | - Android SDK (API 21 or higher)
78 |
79 | ### Setup
80 |
81 | 1. **Clone the repository:**
82 | ```bash
83 | git clone https://github.com/HaneetGH/KotlinAndroidBase.git
84 | ```
85 |
86 | 2. **Open in Android Studio:**
87 | Open the project in Android Studio, then allow it to sync the Gradle files.
88 |
89 | 3. **Build the project:**
90 | Build the project to download dependencies and set up the development environment.
91 |
92 | 4. **Run the app:**
93 | Use an emulator or a physical device to run the app directly from Android Studio.
94 |
95 | ---
96 |
97 | ## Contributing
98 |
99 | We welcome contributions from the community! Here's how you can get involved:
100 |
101 | 1. **Fork the repository** by clicking the "Fork" button at the top of the page.
102 | 2. **Create a new branch** for your feature or bug fix:
103 | ```bash
104 | git checkout -b feature-branch
105 | ```
106 | 3. **Make your changes** and commit them:
107 | ```bash
108 | git commit -m "Description of the feature or fix"
109 | ```
110 | 4. **Push your branch** to GitHub:
111 | ```bash
112 | git push origin feature-branch
113 | ```
114 | 5. **Create a Pull Request** to the `main` branch of this repository.
115 |
116 | Please ensure that your code follows the project's standards and includes appropriate tests.
117 |
118 | ---
119 |
120 | ## License
121 |
122 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
123 |
124 | ---
125 |
126 | ## Contact
127 |
128 | For any questions or support, feel free to open an issue on GitHub.
129 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | apply plugin: 'kotlin-kapt'
8 | android {
9 | dataBinding {
10 | enabled = true
11 | }
12 | testOptions {
13 | unitTests.returnDefaultValues = true
14 | }
15 | compileSdkVersion 29
16 | buildToolsVersion "29.0.2"
17 | defaultConfig {
18 | // Enabling multidex support.
19 | multiDexEnabled true
20 | applicationId "com.technorapper.boiler"
21 | minSdkVersion 15
22 | targetSdkVersion 29
23 | versionCode 1
24 | versionName "1.0"
25 | testInstrumentationRunner "com.technorapper.boiler.ui.onboarding.activity.UiRunner"
26 | }
27 | buildTypes {
28 | release {
29 | minifyEnabled false
30 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
31 | }
32 | }
33 |
34 | /* I use Data Binding and Java8 in all my projects */
35 | dataBinding {
36 | enabled true
37 | }
38 | compileOptions {
39 | sourceCompatibility JavaVersion.VERSION_1_8
40 | targetCompatibility JavaVersion.VERSION_1_8
41 | }
42 | }
43 |
44 | kapt {
45 | generateStubs = true
46 | }
47 | dependencies {
48 | implementation fileTree(dir: 'libs', include: ['*.jar'])
49 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
50 | implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.61"
51 | implementation 'androidx.appcompat:appcompat:1.1.0'
52 | implementation 'androidx.core:core-ktx:1.1.0'
53 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
54 | testImplementation 'junit:junit:4.12'
55 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
56 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
57 |
58 |
59 | kapt 'com.android.databinding:compiler:3.1.4'
60 | implementation("io.reactivex.rxjava2:rxkotlin:2.4.0")
61 |
62 | //dagger
63 |
64 | kapt "com.google.dagger:dagger-compiler:$daggerVersion"
65 | kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
66 | implementation "com.google.dagger:dagger:$daggerVersion"
67 | implementation "com.google.dagger:dagger-android:$daggerVersion"
68 | implementation "com.google.dagger:dagger-android-support:$daggerVersion"
69 | kapt "com.google.dagger:dagger-compiler:$daggerVersion"
70 | kaptTest "com.google.dagger:dagger-compiler: $daggerVersion"
71 |
72 |
73 |
74 | implementation 'com.squareup.picasso:picasso:2.71828'
75 | implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2'
76 | //room
77 | implementation "androidx.room:room-runtime:$room_version"
78 | implementation "androidx.legacy:legacy-support-v4:1.0.0"
79 | implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle"
80 | implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle"
81 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle"
82 |
83 | // mockk
84 | testImplementation 'io.mockk:mockk:' + mockKVersion
85 | // mockito
86 | testImplementation 'org.mockito:mockito-core:2.19.0'
87 | kapt "androidx.room:room-compiler:$room_version"
88 |
89 | implementation 'com.google.code.gson:gson:2.8.6'
90 |
91 | //Moshi
92 | implementation "com.squareup.moshi:moshi-kotlin:$moshiVersion"
93 | kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion"
94 | implementation "com.squareup.retrofit2:converter-moshi:$retrofit2_version"
95 |
96 | //Retrofit2
97 | implementation "com.squareup.retrofit2:retrofit:$retrofit2_version"
98 | implementation "com.squareup.retrofit2:converter-gson:$retrofit2_version"
99 | implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit2_version"
100 |
101 | implementation "com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2"
102 |
103 | //Okhttp3
104 | implementation "com.squareup.okhttp3:okhttp:$okhttp3_version"
105 | implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
106 |
107 | //Picasso for Image Loading
108 | implementation ("com.squareup.picasso:picasso:$picassoVersion"){
109 | exclude group: "com.android.support"
110 | }
111 |
112 | //Kotlin Coroutines
113 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutineVersion"
114 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutineVersion"
115 |
116 | implementation 'com.jakewharton.timber:timber:4.7.1'
117 |
118 | implementation 'com.github.franmontiel:PersistentCookieJar:v1.0.1'
119 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
120 | implementation('com.github.nkzawa:socket.io-client:0.6.0', {
121 | exclude group: 'org.json', module: 'json'
122 | })
123 | implementation 'com.android.support:multidex:1.0.0'
124 | androidTestImplementation('com.squareup.okhttp3:mockwebserver:' + rootProject.mockWebServerVersion) {
125 | exclude group: "com.squareup.okhttp3"
126 | }
127 | implementation "com.squareup.retrofit2:converter-scalars:$retrofit2_version"
128 | androidTestImplementation 'androidx.test.ext:junit:1.1.0' ,
129 | 'androidx.test:rules:1.1.0',
130 | 'androidx.test.espresso:espresso-core:3.1.1'
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/technorapper/boiler/ui/onboarding/activity/MainActivityTest.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.ui.onboarding.activity
2 |
3 | import androidx.test.core.app.ActivityScenario
4 | import androidx.test.espresso.Espresso
5 | import androidx.test.espresso.assertion.ViewAssertions
6 | import androidx.test.espresso.matcher.ViewMatchers
7 | import androidx.test.espresso.matcher.ViewMatchers.withId
8 | import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner
9 | import com.technorapper.boiler.R
10 | import org.junit.Assert.*
11 | import org.junit.Test
12 | import org.junit.runner.RunWith
13 |
14 | @RunWith(AndroidJUnit4ClassRunner::class)
15 | class MainActivityTest{
16 |
17 | @Test
18 | fun testActivity_inView() {
19 | val activityScenario = ActivityScenario.launch(MainActivity::class.java)
20 |
21 | Espresso.onView(withId(R.id.main)).check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
22 | Espresso.onView(withId(R.id.button)).check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/technorapper/boiler/ui/onboarding/activity/UiRunner.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.ui.onboarding.activity
2 |
3 | import android.app.Application
4 | import android.content.Context
5 | import android.os.Bundle
6 | import androidx.test.runner.AndroidJUnitRunner
7 | import android.os.StrictMode
8 | import com.technorapper.boiler.application.App
9 |
10 | open class UiRunner : AndroidJUnitRunner() {
11 |
12 | override fun onCreate(arguments: Bundle?) {
13 | StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().permitAll().build())
14 | super.onCreate(arguments)
15 | }
16 |
17 | override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
18 | return super.newApplication(cl, App::class.java.name, context)
19 | }
20 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/application/App.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("DEPRECATION")
2 |
3 | package com.technorapper.boiler.application
4 |
5 | import android.app.Activity
6 | import android.app.Application
7 | import androidx.databinding.DataBindingUtil
8 | import androidx.fragment.app.Fragment
9 | import androidx.multidex.MultiDexApplication
10 | import com.technorapper.boiler.di.applyAutoInjector
11 | import com.technorapper.boiler.data.tunnel.remote.utils.AppSocket
12 | import com.technorapper.boiler.di.component.AppComponent
13 | import com.technorapper.boiler.di.component.BindingComponent
14 | import com.technorapper.boiler.di.component.DaggerAppComponent
15 | import com.technorapper.boiler.di.component.DaggerBindingComponent
16 | import com.technorapper.boiler.di.module.AppModule
17 | import com.technorapper.boiler.di.module.BindingModule
18 | import com.github.nkzawa.socketio.client.Socket
19 | import com.squareup.picasso.Picasso
20 | import dagger.android.AndroidInjector
21 | import dagger.android.DispatchingAndroidInjector
22 | import dagger.android.HasActivityInjector
23 | import dagger.android.support.HasSupportFragmentInjector
24 | import javax.inject.Inject
25 |
26 | open class App : Application(), HasActivityInjector, HasSupportFragmentInjector {
27 | @Inject
28 | lateinit var appComponent: AppComponent
29 |
30 | @Inject
31 | lateinit var picasso: Picasso
32 |
33 | @Inject
34 | lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector
35 |
36 | @Inject
37 | lateinit var dispatchingFragmentInjector: DispatchingAndroidInjector
38 | @Inject
39 | lateinit var socket: AppSocket
40 |
41 | override fun onCreate() {
42 | super.onCreate()
43 | INSTANCE = this
44 | initDagger()
45 | socket.connect()
46 | val bindingComponent: BindingComponent? = DaggerBindingComponent.builder()
47 | ?.bindingModule(BindingModule())
48 | ?.picasso(picasso)
49 | ?.build()
50 | DataBindingUtil.setDefaultComponent(bindingComponent)
51 | applyAutoInjector()
52 | }
53 |
54 | open fun initDagger() {
55 | appComponent = DaggerAppComponent.builder()
56 | .application(this)
57 | .appModule(AppModule(this))
58 | .build()
59 | appComponent.inject(this)
60 | }
61 |
62 | override fun activityInjector(): DispatchingAndroidInjector? {
63 | return dispatchingAndroidInjector
64 | }
65 |
66 | override fun supportFragmentInjector(): AndroidInjector? {
67 | return dispatchingFragmentInjector
68 | }
69 |
70 | companion object {
71 | lateinit var INSTANCE: App
72 | }
73 |
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/constants/DatabaseConstants.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.constants
2 |
3 | class DatabaseConstants {
4 | companion object {
5 | val DB_NAME = "example_driver.db"
6 | }
7 |
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/constants/GlobalVariables.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.constants
2 |
3 | class GlobalVariables {
4 | companion object {
5 | const val TIME_STAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSS"
6 | const val SOCKET_URL = "http://b03f8515.ngrok.io"
7 | }
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/constants/Preferences.java:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.constants;
2 |
3 | public interface Preferences {
4 | String APP_NAME = "app_name";
5 | String IS_LOGIN = "is_login";
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/Result.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data
2 |
3 | sealed class Result {
4 | data class Success(val data: T) : Result()
5 | data class Error(val exception: Exception) : Result()
6 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/APIResponse.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.models
2 |
3 | import com.google.gson.annotations.SerializedName
4 |
5 | data class APIResponse(
6 | @SerializedName("current")
7 | val current: Current? = null,
8 | @SerializedName("location")
9 | val location: LocationResponse? = null,
10 | @SerializedName("forecast")
11 | val forecast: ForecastResponse? = null
12 | ) {
13 | override fun toString(): String {
14 | return "APIResponse(current=$current, location=$location, forecast=$forecast)"
15 | }
16 | }
17 |
18 | data class Current(
19 | @SerializedName("temp_c")
20 | val tempC: String? = null,
21 | @SerializedName("temp_f")
22 | val tempF: String? = null,
23 | @SerializedName("humidity")
24 | val humidity: String? = null
25 | ) {
26 | override fun toString(): String {
27 | return "Current(tempC=$tempC, tempF=$tempF, humidity=$humidity)"
28 | }
29 | }
30 |
31 | data class LocationResponse(
32 | @SerializedName("region")
33 | val region: String? = null,
34 | @SerializedName("country")
35 | val country: String? = null,
36 | @SerializedName("localtime")
37 | val localtime: String? = null,
38 | @SerializedName("lon")
39 | val lng: String? = null,
40 | @SerializedName("lat")
41 | val lat: String? = null,
42 | @SerializedName("tz_id")
43 | val tzId: String? = null,
44 | @SerializedName("name")
45 | val name: String? = null
46 | ) {
47 | override fun toString(): String {
48 | return "LocationResponse(region=$region, country=$country, localtime=$localtime, lng=$lng, lat=$lat, tzId=$tzId, name=$name)"
49 | }
50 | }
51 |
52 | data class ForecastResponse(
53 | @SerializedName("forecastday")
54 | val forecastdayArray: ArrayList? = null
55 | ) {
56 | override fun toString(): String {
57 | return "ForecastResponse(forecastdayArray=$forecastdayArray)"
58 | }
59 | }
60 |
61 | data class ForecastDay(
62 | @SerializedName("day")
63 | val day: Day? = null,
64 | @SerializedName("date")
65 | val date: String? = null
66 | ) {
67 | override fun toString(): String {
68 | return "ForecastDay(day=$day, date=$date)"
69 | }
70 | }
71 |
72 | data class Day(
73 | @SerializedName("avgtemp_c")
74 | val avgTempC: Double? = null,
75 | @SerializedName("avghumidity")
76 | val avgHumidity: Int? = null,
77 | @SerializedName("avgtemp_f")
78 | val avgTempF: Double? = null
79 | ) {
80 | override fun toString(): String {
81 | return "Day(avgTempC=$avgTempC, avgHumidity=$avgHumidity, avgTempF=$avgTempF)"
82 | }
83 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/UserTableModel.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.models
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 | import com.technorapper.boiler.data.models.base.BaseDaoModel
7 | import com.google.gson.annotations.Expose
8 | import com.google.gson.annotations.SerializedName
9 |
10 | @Entity(tableName = "userMaster" + "")
11 | data class UserTableModel(
12 | @SerializedName("userMaster_id")
13 | @Expose
14 | @PrimaryKey
15 | @ColumnInfo(name = "userMaster_id")
16 | var userMaster_id: String,
17 |
18 | @SerializedName("lat")
19 | @Expose
20 | @ColumnInfo(name = "lat")
21 | val lat: String,
22 |
23 | @SerializedName("lng")
24 | @Expose
25 | @ColumnInfo(name = "lng")
26 | val lng: String,
27 |
28 | @SerializedName("name")
29 | @Expose
30 | @ColumnInfo(name = "name")
31 | var name: String
32 | ) : BaseDaoModel() {
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/base/BaseDaoModel.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.models.base
2 |
3 | import androidx.databinding.BaseObservable
4 | import androidx.room.ColumnInfo
5 | import androidx.room.TypeConverters
6 | import com.technorapper.boiler.data.utils.TimestampConverter
7 | import com.google.gson.annotations.Expose
8 | import java.io.Serializable
9 | import java.util.*
10 |
11 | open class BaseDaoModel() : BaseObservable(), Serializable {
12 |
13 | @Expose
14 | @TypeConverters(TimestampConverter::class)
15 | @ColumnInfo(name = "createdOn")
16 | var createdOn = Date()
17 | @Expose
18 | @TypeConverters(TimestampConverter::class)
19 | @ColumnInfo(name = "updatedOn")
20 | var updatedOn = Date()
21 | @Expose
22 | @ColumnInfo(name = "updatedBy")
23 | var updatedBy = ""
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/repo/License.kt:
--------------------------------------------------------------------------------
1 | package com.bt.technorapper.driver.data.models.github.repo
2 |
3 | data class License(
4 | val key: String,
5 | val name: String,
6 | val node_id: String,
7 | val spdx_id: String,
8 | val url: Any
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/repo/Owner.kt:
--------------------------------------------------------------------------------
1 | package com.bt.technorapper.driver.data.models.github.repo
2 |
3 | data class Owner(
4 | val avatar_url: String,
5 | val events_url: String,
6 | val followers_url: String,
7 | val following_url: String,
8 | val gists_url: String,
9 | val gravatar_id: String,
10 | val html_url: String,
11 | val id: Int,
12 | val login: String,
13 | val node_id: String,
14 | val organizations_url: String,
15 | val received_events_url: String,
16 | val repos_url: String,
17 | val site_admin: Boolean,
18 | val starred_url: String,
19 | val subscriptions_url: String,
20 | val type: String,
21 | val url: String
22 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/repo/UserRepo.kt:
--------------------------------------------------------------------------------
1 | package com.bt.technorapper.driver.data.models.github.repo
2 |
3 | class UserRepo : ArrayList()
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/repo/UserRepoItem.kt:
--------------------------------------------------------------------------------
1 | package com.bt.technorapper.driver.data.models.github.repo
2 |
3 | data class UserRepoItem(
4 | val archive_url: String,
5 | val archived: Boolean,
6 | val assignees_url: String,
7 | val blobs_url: String,
8 | val branches_url: String,
9 | val clone_url: String,
10 | val collaborators_url: String,
11 | val comments_url: String,
12 | val commits_url: String,
13 | val compare_url: String,
14 | val contents_url: String,
15 | val contributors_url: String,
16 | val created_at: String,
17 | val default_branch: String,
18 | val deployments_url: String,
19 | val description: String,
20 | val disabled: Boolean,
21 | val downloads_url: String,
22 | val events_url: String,
23 | val fork: Boolean,
24 | val forks: Int,
25 | val forks_count: Int,
26 | val forks_url: String,
27 | val full_name: String,
28 | val git_commits_url: String,
29 | val git_refs_url: String,
30 | val git_tags_url: String,
31 | val git_url: String,
32 | val has_downloads: Boolean,
33 | val has_issues: Boolean,
34 | val has_pages: Boolean,
35 | val has_projects: Boolean,
36 | val has_wiki: Boolean,
37 | val homepage: String,
38 | val hooks_url: String,
39 | val html_url: String,
40 | val id: Int,
41 | val issue_comment_url: String,
42 | val issue_events_url: String,
43 | val issues_url: String,
44 | val keys_url: String,
45 | val labels_url: String,
46 | val language: String,
47 | val languages_url: String,
48 | val license: License,
49 | val merges_url: String,
50 | val milestones_url: String,
51 | val mirror_url: Any,
52 | val name: String,
53 | val node_id: String,
54 | val notifications_url: String,
55 | val open_issues: Int,
56 | val open_issues_count: Int,
57 | val owner: Owner,
58 | val `private`: Boolean,
59 | val pulls_url: String,
60 | val pushed_at: String,
61 | val releases_url: String,
62 | val size: Int,
63 | val ssh_url: String,
64 | val stargazers_count: Int,
65 | val stargazers_url: String,
66 | val statuses_url: String,
67 | val subscribers_url: String,
68 | val subscription_url: String,
69 | val svn_url: String,
70 | val tags_url: String,
71 | val teams_url: String,
72 | val trees_url: String,
73 | val updated_at: String,
74 | val url: String,
75 | val watchers: Int,
76 | val watchers_count: Int
77 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/response/BasicResponse.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.models.response
2 |
3 | import com.google.gson.annotations.Expose
4 | import com.google.gson.annotations.SerializedName
5 | import com.squareup.moshi.Json
6 | import com.squareup.moshi.JsonClass
7 |
8 | @JsonClass(generateAdapter = true)
9 | data class BasicResponse(
10 | val result: Result
11 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/response/Result.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.models.response
2 |
3 | import com.google.gson.annotations.Expose
4 | import com.google.gson.annotations.SerializedName
5 | import com.squareup.moshi.Json
6 | import com.squareup.moshi.JsonClass
7 |
8 | @JsonClass(generateAdapter = true)
9 | data class Result(val code: Int, val msg: String)
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/models/response/socket/SocketModel.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.models.response.socket
2 |
3 | class SocketModel {
4 | var type = 0
5 |
6 | var message: String? = null}
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/repository/BaseRepository.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.repository
2 |
3 |
4 | import android.util.Log
5 | import com.squareup.picasso.Picasso
6 | import retrofit2.Response
7 | import java.io.IOException
8 |
9 | open class BaseRepository {
10 |
11 | suspend fun safeApiCall(call: suspend () -> Response, errorMessage: String): T? {
12 |
13 | val result: com.technorapper.boiler.data.Result = safeApiResult(call, errorMessage)
14 | var data: T? = null
15 |
16 | when (result) {
17 | is com.technorapper.boiler.data.Result.Success ->
18 | data = result.data
19 | is com.technorapper.boiler.data.Result.Error -> {
20 | Log.d("1.DataRepository", "$errorMessage & Exception - ${result.exception}")
21 | }
22 | }
23 |
24 |
25 | return data
26 |
27 | }
28 |
29 | private suspend fun safeApiResult(
30 | call: suspend () -> Response,
31 | errorMessage: String
32 | ): com.technorapper.boiler.data.Result {
33 | val response = call.invoke()
34 | if (response.isSuccessful) return com.technorapper.boiler.data.Result.Success(response.body()!!)
35 |
36 | return com.technorapper.boiler.data.Result.Error(IOException("Error Occurred during getting safe Api result, Custom ERROR - $errorMessage"))
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/repository/MainActivityRepository.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.repository
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.util.Log
6 | import androidx.lifecycle.MutableLiveData
7 | import com.bt.technorapper.driver.data.models.github.repo.UserRepo
8 | import com.google.gson.JsonObject
9 | import com.technorapper.boiler.data.models.response.BasicResponse
10 | import com.technorapper.boiler.data.tunnel.remote.SynchronousApi
11 | import com.technorapper.boiler.di.scopes.ApplicationScoped
12 | import io.reactivex.Flowable
13 | import retrofit2.await
14 | import javax.inject.Inject
15 |
16 |
17 | @ApplicationScoped
18 | class MainActivityRepository @Inject internal constructor(
19 | private val asyncApi: SynchronousApi,
20 | context: Context
21 | ) : BaseRepository() {
22 |
23 | @SuppressLint("TimberArgCount")
24 | suspend fun getAllApi(): MutableLiveData? {
25 | val response = asyncApi.getPosts("782323523", 7)/*safeApiCall(
26 | call = { asyncApi.getPosts("782323523", 7) },
27 | errorMessage = "Error Fetching Popular Movies")*/
28 |
29 | if (response != null) {
30 | Log.d("JSON", response.result.toString())
31 | }
32 | return null
33 | /*withContext(Dispatchers.Main) {
34 | try {
35 | if (response != null) {
36 |
37 |
38 | *//* var json = response.string().toString();
39 | val moshi = Moshi.Builder().build()
40 | val jsonAdapter: JsonAdapter =
41 | moshi.adapter(
42 | BasicResponse::class.java
43 | )
44 |
45 | val blackjackHand: BasicResponse? = jsonAdapter.fromJson(json)
46 | System.out.println(blackjackHand)*//*
47 |
48 | //Do something with response e.g show to the UI.
49 | } else {
50 | Timber.d("Error: ${response}")
51 | }
52 | } catch (e: HttpException) {
53 | Timber.e("Exception ${e.message}")
54 | } catch (e: Throwable) {
55 | Timber.e("Ooops: Something else went wrong")
56 | }
57 |
58 | }
59 | }*/
60 |
61 |
62 | }
63 |
64 | suspend fun getUserRepo(url: String): UserRepo {
65 | return asyncApi.getUserRepo(url)
66 |
67 |
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/tunnel/database/TechnorapperDriverDatabase.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.tunnel.database
2 |
3 | import androidx.room.Database
4 | import androidx.room.RoomDatabase
5 | import androidx.room.TypeConverters
6 | import com.technorapper.boiler.data.tunnel.database.dao.UserMasterDao
7 | import com.technorapper.boiler.data.models.UserTableModel
8 | import com.technorapper.boiler.data.utils.RoomConverters
9 |
10 | @Database(
11 | entities = arrayOf(UserTableModel::class),
12 | version = 1,
13 | exportSchema = false
14 | )
15 | @TypeConverters(
16 | RoomConverters::class
17 | )
18 | abstract class exampleDatabase : RoomDatabase() {
19 | // private static TechnorapperDatabase TechnorapperDB;
20 |
21 | abstract fun getUserMasterDao(): UserMasterDao
22 |
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/tunnel/database/dao/UserMasterDao.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.tunnel.database.dao
2 |
3 | import androidx.room.*
4 | import com.technorapper.boiler.data.models.UserTableModel
5 |
6 | @Dao
7 | abstract class UserMasterDao {
8 |
9 | @Query("SELECT * FROM userMaster")
10 | abstract fun getAll(): List
11 |
12 |
13 |
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/tunnel/remote/ASynchronousSocket.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.tunnel.remote
2 |
3 | interface ASynchronousSocket {
4 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/tunnel/remote/SynchronousApi.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.tunnel.remote
2 |
3 | import com.bt.technorapper.driver.data.models.github.repo.UserRepo
4 | import com.technorapper.boiler.data.models.response.BasicResponse
5 | import com.google.gson.JsonObject
6 | import com.technorapper.boiler.data.models.APIResponse
7 | import io.reactivex.Flowable
8 | import kotlinx.coroutines.Deferred
9 | import okhttp3.ResponseBody
10 | import retrofit2.Response
11 |
12 | import retrofit2.http.GET
13 | import retrofit2.http.Path
14 | import retrofit2.http.Query
15 | import retrofit2.http.Url
16 |
17 | interface SynchronousApi {
18 | @GET("GetMonitorNotification")
19 | suspend fun getPosts(
20 | @Query("customer_id") id: String?, @Query(
21 | "job_type"
22 | ) job_type: Int
23 | ): BasicResponse
24 |
25 | @GET
26 | fun getForecastTempWithUrl(
27 | @Url
28 | url: String
29 | ): Flowable
30 |
31 | @GET("users/{name}/repos")
32 | suspend fun getUserRepo(
33 | @Path(
34 | "name"
35 | ) name: String?
36 | ): UserRepo
37 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/tunnel/remote/utils/AppSocket.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.tunnel.remote.utils
2 |
3 | import com.github.nkzawa.emitter.Emitter
4 | import com.github.nkzawa.socketio.client.Socket
5 | import io.reactivex.Completable
6 |
7 | class AppSocket(private val socket: Socket) {
8 |
9 | private val listeners: MutableList = mutableListOf()
10 |
11 | val isConnected: Boolean get() = socket.connected()
12 |
13 | init {
14 | socket.on(Socket.EVENT_CONNECT, {
15 | listeners.forEach {
16 | it.onConnect(socket)
17 | }
18 | })
19 | }
20 |
21 | fun connect() {
22 | socket.open()
23 | }
24 |
25 | fun disconnect() {
26 | socket.close()
27 | }
28 |
29 | fun request(name: String, any: Any) {
30 | if (isConnected)
31 | socket.emit(name, any)
32 |
33 | }
34 |
35 | fun on(name: String, listener: Emitter.Listener) {
36 | socket.on(name, listener)
37 | }
38 |
39 |
40 | fun addListener(listener: CommonListener) {
41 | listeners.add(listener)
42 | }
43 |
44 | fun removeListener(listener: CommonListener) {
45 | listeners.iterator().run {
46 | while (hasNext())
47 | if (next() == listener)
48 | remove()
49 | }
50 | }
51 |
52 | interface CommonListener {
53 | fun onConnect(socket: Socket)
54 | }
55 | }
56 |
57 |
58 | class SocketNotConnectedException : Throwable()
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/tunnel/remote/utils/CheckInternetConnection.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.tunnel.remote.utils
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.net.ConnectivityManager
6 | import java.net.InetAddress
7 |
8 | class CheckInternetConnection(private val _context: Context) {
9 |
10 | fun isNetworkAvailable(): Boolean { /*ConnectivityManager connectivityManager
11 | = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
12 | NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();*/
13 | return isOnline()
14 | }
15 |
16 | companion object {
17 | fun isInternetConnected(context: Context): Boolean {
18 | val connectivityManager =
19 | context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
20 | val activeNetworkInfo = connectivityManager.activeNetworkInfo
21 | return activeNetworkInfo != null && activeNetworkInfo.isConnected
22 | }
23 | }
24 |
25 | fun isOnline(): Boolean {
26 | try {
27 | val p1 =
28 | Runtime.getRuntime().exec("ping -c 1 www.google.com")
29 | val returnVal = p1.waitFor()
30 | return returnVal == 0
31 | } catch (e: Exception) {
32 | e.printStackTrace()
33 | }
34 | return false
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/tunnel/remote/utils/CustomObserable.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.tunnel.remote.utils
2 |
3 | import com.technorapper.boiler.data.models.response.socket.SocketModel
4 | import com.github.nkzawa.socketio.client.IO
5 | import com.github.nkzawa.socketio.client.Socket
6 | import io.reactivex.Observable
7 | import io.reactivex.Observer
8 | import io.reactivex.android.MainThreadDisposable
9 | import java.net.URISyntaxException
10 | import javax.inject.Inject
11 |
12 | class CustomObserable : Observable() {
13 | @Inject
14 | lateinit var socket: AppSocket
15 |
16 | override fun subscribeActual(observer: Observer) {
17 | val listener = Listener(socket, observer)
18 | observer.onSubscribe(listener)
19 | doSocketIoThing(observer)
20 | observer.onComplete()
21 | doSocketIoThing(observer)
22 | }
23 |
24 | private fun doSocketIoThing(observer: Observer) {
25 |
26 | if (socket.isConnected) {
27 | socket.request("news", "example CONNECTED");
28 | }
29 | }
30 |
31 | internal class Listener( val socket: AppSocket, bserver: Observer?) : MainThreadDisposable() {
32 |
33 | override fun onDispose() {
34 | socket.disconnect()
35 | }
36 |
37 | }
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/utils/RoomConverters.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.utils
2 |
3 | import androidx.room.TypeConverter
4 | import java.util.*
5 |
6 | class RoomConverters {
7 | @TypeConverter
8 |
9 | fun toDate(timestamp: Long?): Date? {
10 | return timestamp?.let { Date(it) }
11 | }
12 |
13 | @TypeConverter
14 | fun toTimestamp(date: Date?): Long? {
15 | return date?.time
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/data/utils/TimestampConverter.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.data.utils
2 |
3 | import androidx.room.TypeConverter
4 | import com.technorapper.boiler.constants.GlobalVariables
5 | import java.text.DateFormat
6 | import java.text.ParseException
7 | import java.text.SimpleDateFormat
8 | import java.util.*
9 |
10 | object TimestampConverter {
11 | var df: DateFormat = SimpleDateFormat(GlobalVariables.TIME_STAMP_FORMAT)
12 | @TypeConverter
13 | fun fromTimestamp(value: String?): Date? {
14 | return if (value != null) {
15 | try {
16 | return df.parse(value)
17 | } catch (e: ParseException) {
18 | e.printStackTrace()
19 | }
20 | null
21 | } else {
22 | null
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/AppInjector.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di
2 |
3 | import android.app.Activity
4 | import android.app.Application
5 | import android.os.Bundle
6 | import androidx.fragment.app.Fragment
7 | import androidx.fragment.app.FragmentActivity
8 | import androidx.fragment.app.FragmentManager
9 |
10 | import dagger.android.AndroidInjection
11 | import dagger.android.support.AndroidSupportInjection
12 | import dagger.android.support.HasSupportFragmentInjector
13 |
14 |
15 | interface Injectable
16 |
17 | fun Application.applyAutoInjector() = registerActivityLifecycleCallbacks(
18 | object : Application.ActivityLifecycleCallbacks {
19 |
20 | override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
21 | handleActivity(activity)
22 | }
23 |
24 | override fun onActivityStarted(activity: Activity) {
25 |
26 | }
27 |
28 | override fun onActivityResumed(activity: Activity) {
29 |
30 | }
31 |
32 | override fun onActivityPaused(activity: Activity) {
33 |
34 | }
35 |
36 | override fun onActivityStopped(activity: Activity) {
37 |
38 | }
39 |
40 | override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) {
41 |
42 | }
43 |
44 | override fun onActivityDestroyed(activity: Activity) {
45 |
46 | }
47 | })
48 |
49 | private fun handleActivity(activity: Activity) {
50 | if (activity is Injectable || activity is HasSupportFragmentInjector) {
51 | AndroidInjection.inject(activity)
52 | }
53 | if (activity is FragmentActivity) {
54 | activity.supportFragmentManager.registerFragmentLifecycleCallbacks(
55 | object : FragmentManager.FragmentLifecycleCallbacks() {
56 | override fun onFragmentCreated(fm: FragmentManager, f: Fragment, s: Bundle?) {
57 | if (f is Injectable) {
58 | AndroidSupportInjection.inject(f)
59 | }
60 | }
61 | }, true
62 | )
63 | }
64 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/AppSocketServiceFactory.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di
2 |
3 | import com.technorapper.boiler.data.tunnel.remote.utils.AppSocket
4 | import com.github.nkzawa.socketio.client.Manager
5 | import java.net.URI
6 |
7 | object AppSocketServiceFactory {
8 |
9 | private val baseSocketUrl: String = "http://b03f8515.ngrok.io"
10 |
11 | private enum class SocketNameSpace(val value: String) {
12 | CARD("/")
13 | }
14 |
15 | private val socketManager: Manager by lazy {
16 | Manager(URI(baseSocketUrl))
17 | }
18 |
19 | fun exampleSocket() = AppSocket(socketManager.socket(SocketNameSpace.CARD.value))
20 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/WDViewModelFactory.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.ViewModelProvider
5 | import com.technorapper.boiler.di.scopes.ApplicationScoped
6 | import javax.inject.Inject
7 | import javax.inject.Provider
8 |
9 |
10 | class WDViewModelFactory @Inject constructor(
11 | private val creators: Map, @JvmSuppressWildcards Provider>
12 | ) : ViewModelProvider.Factory {
13 |
14 | @Suppress("UNCHECKED_CAST")
15 | override fun create(modelClass: Class): T {
16 | var creator: Provider? = creators[modelClass]
17 | if (creator == null) {
18 | for ((key, value) in creators) {
19 | if (modelClass.isAssignableFrom(key)) {
20 | creator = value
21 | break
22 | }
23 | }
24 | }
25 | if (creator == null) throw IllegalArgumentException("unknown model class " + modelClass)
26 | try {
27 | return creator.get() as T
28 | } catch (e: Exception) {
29 | throw RuntimeException(e)
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/builder/ActivityBuilder.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.builder
2 |
3 | import com.technorapper.boiler.ui.onboarding.activity.MainActivity
4 | import com.technorapper.boiler.di.scopes.ActivityScoped
5 | import dagger.Module
6 |
7 | import dagger.android.ContributesAndroidInjector
8 |
9 | @Module
10 | internal abstract class ActivityBuilder {
11 |
12 | @ActivityScoped
13 | @ContributesAndroidInjector
14 | abstract fun bindMainActivity(): MainActivity?
15 |
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/builder/BroadcastBuilder.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.builder
2 |
3 | import dagger.Module
4 |
5 | @Module
6 | public abstract class BroadcastBuilder {}
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/builder/FragmentBuilder.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.builder
2 |
3 | import dagger.Module
4 |
5 | @Module
6 | public abstract class FragmentBuilder {}
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/builder/ServiceBuilder.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.builder
2 |
3 | import dagger.Module
4 |
5 |
6 | @Module
7 | public abstract class ServiceBuilder {}
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/component/AppComponent.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.component
2 |
3 |
4 | import com.technorapper.boiler.application.App
5 | import com.technorapper.boiler.di.builder.ActivityBuilder
6 | import com.technorapper.boiler.di.builder.FragmentBuilder
7 | import com.technorapper.boiler.di.module.*
8 | import com.technorapper.boiler.di.scopes.ApplicationScoped
9 | import dagger.BindsInstance
10 | import dagger.Component
11 | import dagger.android.support.AndroidSupportInjectionModule
12 |
13 | @ApplicationScoped
14 | @Component(
15 | modules =
16 | arrayOf(
17 | AndroidSupportInjectionModule::class,
18 | AppModule::class,
19 | PreferenceModule::class,
20 | DataBaseModule::class,
21 | NetworkModule::class,
22 | ActivityBuilder::class,
23 | FragmentBuilder::class
24 | )
25 | )
26 | interface AppComponent {
27 | fun inject(app: App)
28 |
29 | @Component.Builder
30 | interface Builder {
31 | @BindsInstance
32 | fun application(application: App): Builder
33 |
34 | fun appModule(appModule: AppModule): Builder
35 |
36 | fun build(): AppComponent
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/component/BindingComponent.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.component
2 | import androidx.databinding.DataBindingComponent
3 | import com.technorapper.boiler.di.module.BindingModule
4 | import com.technorapper.boiler.di.scopes.BindingScoped
5 | import com.technorapper.boiler.global.CustomBindingAdapter
6 | import com.squareup.picasso.Picasso
7 | import dagger.BindsInstance
8 | import dagger.Component
9 |
10 | @BindingScoped
11 | @Component(modules = arrayOf(BindingModule::class))
12 | interface BindingComponent : DataBindingComponent {
13 | fun getImageBindingAdapter(): CustomBindingAdapter?
14 |
15 | @Component.Builder
16 | interface Builder {
17 | @BindsInstance
18 | fun picasso(picasso: Picasso): Builder
19 | fun bindingModule(bindingModule: BindingModule): Builder
20 | fun build(): BindingComponent
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/module/AppModule.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.module
2 |
3 | import android.app.Application
4 | import android.content.Context
5 |
6 | import com.technorapper.boiler.constants.GlobalVariables
7 | import com.technorapper.boiler.data.tunnel.remote.utils.AppSocket
8 | import com.technorapper.boiler.di.AppSocketServiceFactory
9 | import com.technorapper.boiler.di.scopes.ApplicationScoped
10 | import com.github.nkzawa.socketio.client.IO
11 | import com.github.nkzawa.socketio.client.Socket
12 | import com.squareup.picasso.OkHttp3Downloader
13 | import com.squareup.picasso.Picasso
14 | import com.technorapper.boiler.application.App
15 | import com.technorapper.boiler.data.tunnel.remote.utils.CheckInternetConnection
16 | import dagger.Module
17 | import dagger.Provides
18 | import okhttp3.OkHttpClient
19 | import java.net.URISyntaxException
20 |
21 | @Module(includes = [ViewModelModule::class])
22 | open class AppModule(val application: App) {
23 |
24 |
25 | @Provides
26 | @ApplicationScoped
27 | open fun picasso(
28 | app: App
29 | ): Picasso {
30 | return Picasso.Builder(app.applicationContext).loggingEnabled(true).build()
31 | }
32 |
33 | @Provides
34 | open fun okHttp3Downloader(okHttpClient: OkHttpClient?): OkHttp3Downloader? {
35 | return OkHttp3Downloader(okHttpClient)
36 | }
37 |
38 |
39 | @Provides
40 | @ApplicationScoped
41 | open fun context(): Context {
42 | return application
43 | }
44 |
45 | @Provides
46 | @ApplicationScoped
47 | open fun provideExampleSocket(app: App): AppSocket {
48 | return AppSocketServiceFactory.exampleSocket()
49 | }
50 |
51 | @Provides
52 | @ApplicationScoped
53 | open fun provideInternetConnection(application: Context): CheckInternetConnection? {
54 | return CheckInternetConnection(application)
55 | }
56 |
57 | @Provides
58 | @ApplicationScoped
59 | open fun provideApplication(): Application {
60 | return application
61 | }
62 |
63 |
64 |
65 |
66 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/module/BindingModule.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.module
2 |
3 | import com.technorapper.boiler.di.scopes.BindingScoped
4 | import com.technorapper.boiler.global.CustomBindingAdapter
5 | import com.squareup.picasso.Picasso
6 |
7 | import dagger.Module
8 | import dagger.Provides
9 |
10 | @Module
11 | class BindingModule {
12 | @Provides
13 | @BindingScoped
14 | fun provideImageBindingAdapter(picasso: Picasso): CustomBindingAdapter {
15 | return CustomBindingAdapter(picasso)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/module/DataBaseModule.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.module
2 |
3 | import androidx.room.Room
4 | import com.technorapper.boiler.constants.DatabaseConstants
5 | import com.technorapper.boiler.data.tunnel.database.exampleDatabase
6 | import com.technorapper.boiler.data.tunnel.database.dao.UserMasterDao
7 |
8 | import com.technorapper.boiler.application.App
9 | import com.technorapper.boiler.di.scopes.ApplicationScoped
10 | import dagger.Module
11 | import dagger.Provides
12 |
13 | @Module
14 | class DataBaseModule {
15 |
16 |
17 | @Provides
18 | @ApplicationScoped
19 | fun provideWDDatabase(context: App): exampleDatabase {
20 | return Room.databaseBuilder(
21 | context,
22 | exampleDatabase::class.java, DatabaseConstants.DB_NAME
23 | ).fallbackToDestructiveMigration() /*.allowMainThreadQueries()*/
24 | .build()
25 | }
26 |
27 |
28 | @ApplicationScoped
29 | @Provides
30 |
31 | fun provideUserMasterDao(exampleDatabase: exampleDatabase): UserMasterDao {
32 | return exampleDatabase.getUserMasterDao()
33 | }
34 |
35 |
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/module/NetworkModule.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.module
2 |
3 | import android.app.Application
4 | import android.os.Build
5 | import androidx.annotation.RequiresApi
6 | import com.franmontiel.persistentcookiejar.PersistentCookieJar
7 | import com.franmontiel.persistentcookiejar.cache.SetCookieCache
8 | import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor
9 | import com.google.gson.FieldNamingPolicy
10 | import com.google.gson.Gson
11 | import com.google.gson.GsonBuilder
12 | import com.squareup.moshi.Moshi
13 | import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
14 | import com.technorapper.boiler.data.tunnel.remote.SynchronousApi
15 | import com.technorapper.boiler.data.tunnel.remote.utils.CheckInternetConnection
16 | import com.technorapper.boiler.di.scopes.ApplicationScoped
17 | import com.technorapper.boiler.helpers.AppPrefs
18 | import dagger.Module
19 | import dagger.Provides
20 | import io.reactivex.schedulers.Schedulers
21 | import okhttp3.*
22 | import okhttp3.logging.HttpLoggingInterceptor
23 | import retrofit2.Retrofit
24 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
25 | import retrofit2.converter.gson.GsonConverterFactory
26 | import retrofit2.converter.moshi.MoshiConverterFactory
27 | import retrofit2.converter.scalars.ScalarsConverterFactory
28 | import java.net.CookieHandler
29 | import java.net.CookieManager
30 | import java.net.CookiePolicy
31 | import java.security.SecureRandom
32 | import java.security.cert.CertificateException
33 | import java.security.cert.X509Certificate
34 | import java.util.concurrent.TimeUnit
35 | import javax.inject.Named
36 | import javax.net.ssl.SSLContext
37 | import javax.net.ssl.TrustManager
38 | import javax.net.ssl.X509TrustManager
39 |
40 | @Module
41 | class NetworkModule {
42 | companion object {
43 |
44 | private const val TIMEOUT_IN_MS = 30000
45 | private const val LT_BASE_URL = "lt_base_url"
46 | private const val TOKEN = "token"
47 |
48 | private val BASE_URL = "https://api.github.com/"
49 | }
50 |
51 | @Provides
52 | @ApplicationScoped
53 | fun provideAuthorizationInterceptor(
54 | @Named(TOKEN) token: String, connection: CheckInternetConnection
55 | ): Interceptor {
56 | return Interceptor { chain ->
57 |
58 |
59 | var request = chain.request()
60 |
61 | val requestBuilder = request.newBuilder()
62 | // .addHeader("Authorization", "Bearer " + token);
63 | val cacheControl = CacheControl.Builder()
64 | .maxAge(40, TimeUnit.SECONDS)
65 | .build()
66 |
67 | if (connection.isNetworkAvailable()) {
68 | val maxAge = 20 // read from cache for 1 minute
69 | //request.newBuilder()
70 | requestBuilder
71 | // .addHeader("Authorization", "Bearer$token")
72 |
73 | .addHeader(
74 | "Authorization",
75 | "Bearer $token"
76 | )
77 | .addHeader("Content-Type", "application/json")
78 | .header("Cache-Control", "public, max-age=$maxAge")
79 | .cacheControl(cacheControl)
80 | .build()
81 | } else {
82 | val maxStale = 60 * 60 * 24 * 28 // tolerate 4-weeks stale
83 | // request.newBuilder()
84 | requestBuilder
85 | .header("Cache-Control", "public, only-if-cached, max-stale=$maxStale")
86 | .build()
87 | }
88 |
89 | request = requestBuilder.build()
90 |
91 | val response = chain.proceed(request)
92 | if (response.code() == 401) {
93 |
94 | // Expire Token
95 | return@Interceptor response
96 | }
97 | response
98 | }
99 | }
100 |
101 | @Provides
102 | @Named(LT_BASE_URL)
103 | fun provideBaseUrlString(): String {
104 | return BASE_URL
105 |
106 | }
107 |
108 |
109 | @Provides
110 | @ApplicationScoped
111 | internal fun provideRetrofitInterface(
112 | okHttpClient: OkHttpClient
113 | ): Retrofit {
114 |
115 | return Retrofit.Builder()
116 | .baseUrl(BASE_URL)
117 | .addConverterFactory(MoshiConverterFactory.create())
118 |
119 | .build()
120 |
121 | }
122 |
123 |
124 | @Provides
125 | @Named(TOKEN)
126 | fun provideToken(preference: AppPrefs): String? {
127 | return preference.TOKEN
128 | }
129 |
130 | @RequiresApi(Build.VERSION_CODES.GINGERBREAD)
131 | @Provides
132 | @ApplicationScoped
133 | fun provideCookieManager(): CookieManager? {
134 | val cookieManager = CookieManager()
135 | cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL)
136 | CookieHandler.setDefault(cookieManager)
137 | return cookieManager
138 | }
139 |
140 | @Provides
141 | @ApplicationScoped
142 | fun provideLoggingInterceptor(): HttpLoggingInterceptor? {
143 | return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
144 | }
145 |
146 | @Provides
147 | @ApplicationScoped
148 | fun provideOKHttpClient(
149 | loggingInterceptor: HttpLoggingInterceptor,
150 | authInterceptor: Interceptor,
151 | cookieJar: CookieJar,
152 | cache: Cache
153 | ): OkHttpClient {
154 |
155 | // Create a trust manager that does not validate certificate chains
156 | val trustAllCerts =
157 | arrayOf(
158 | object : X509TrustManager {
159 | @Throws(CertificateException::class)
160 | override fun checkClientTrusted(
161 | chain: Array,
162 | authType: String
163 | ) {
164 | }
165 |
166 | @Throws(CertificateException::class)
167 | override fun checkServerTrusted(
168 | chain: Array,
169 | authType: String
170 | ) {
171 | }
172 |
173 | override fun getAcceptedIssuers(): Array {
174 | return arrayOf()
175 | }
176 | }
177 | )
178 |
179 | // Install the all-trusting trust manager
180 |
181 | // Install the all-trusting trust manager
182 | val sslContext = SSLContext.getInstance("SSL")
183 | sslContext.init(null, trustAllCerts, SecureRandom())
184 |
185 | // Create an ssl socket factory with our all-trusting manager
186 |
187 | // Create an ssl socket factory with our all-trusting manager
188 | val sslSocketFactory = sslContext.socketFactory
189 |
190 | val builder = OkHttpClient.Builder()
191 | builder.sslSocketFactory(
192 | sslSocketFactory,
193 | trustAllCerts[0] as X509TrustManager
194 | )
195 | builder.hostnameVerifier { hostname, session -> true }
196 | return OkHttpClient.Builder()
197 |
198 | .connectTimeout(1, TimeUnit.MINUTES)
199 | .writeTimeout(1, TimeUnit.MINUTES) // write timeout
200 | .readTimeout(1, TimeUnit.MINUTES) // read timeout
201 | .addInterceptor(authInterceptor)
202 | .addInterceptor(loggingInterceptor)
203 | .cookieJar(cookieJar)
204 | .cache(cache)
205 | .build()
206 |
207 | }
208 |
209 | @Provides
210 | @ApplicationScoped
211 | fun provideMoshi(): MoshiConverterFactory {
212 | return MoshiConverterFactory.create(Moshi.Builder().add(KotlinJsonAdapterFactory()).build())
213 | }
214 |
215 | @Provides
216 | @ApplicationScoped
217 | fun provideRxAdapter(): RxJava2CallAdapterFactory {
218 | return RxJava2CallAdapterFactory
219 | .createWithScheduler(Schedulers.io())
220 | }
221 |
222 | @Provides
223 | @ApplicationScoped
224 | fun provideexampleService(@Named(LT_BASE_URL) baseUrl: String): SynchronousApi {
225 | return Retrofit.Builder().baseUrl(baseUrl)
226 | .addConverterFactory(GsonConverterFactory.create())
227 | .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
228 | .addConverterFactory(ScalarsConverterFactory.create())
229 | .build().create(SynchronousApi::class.java)
230 | }
231 |
232 | @Provides
233 | @ApplicationScoped
234 | fun provideGson(): Gson? {
235 | return GsonBuilder() /* .registerTypeAdapterFactory(tvMazeTypeAdaptorFactory)*/
236 | .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
237 | .setLenient()
238 | .create()
239 | }
240 |
241 | @Provides
242 | @ApplicationScoped
243 | fun provideCookieJar(context: Application?): CookieJar? {
244 | return PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(context))
245 | }
246 |
247 |
248 | @Provides
249 | @ApplicationScoped
250 | fun provideCache(context: Application): Cache? {
251 | val cacheSize = 5 * 1024 * 1024 // 5 MB
252 | val cacheDir = context.cacheDir
253 | return Cache(cacheDir, cacheSize.toLong())
254 | }
255 |
256 | @Provides
257 | @ApplicationScoped
258 | fun provideRxJavaCallAdapterFactory(): RxJava2CallAdapterFactory? {
259 | return RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io())
260 | }
261 | }
262 |
263 |
264 |
265 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/module/PreferenceModule.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.module
2 |
3 | import android.content.Context
4 | import android.content.SharedPreferences
5 | import com.technorapper.boiler.constants.Preferences
6 |
7 | import com.technorapper.boiler.application.App
8 | import com.technorapper.boiler.di.scopes.ApplicationScoped
9 |
10 | import com.technorapper.boiler.helpers.AppPrefs
11 | import dagger.Module
12 | import dagger.Provides
13 |
14 | @Module
15 | open class PreferenceModule {
16 |
17 | @Provides
18 | @ApplicationScoped
19 | open fun provideTechnorapperPreference(preferences: SharedPreferences?): AppPrefs {
20 | return AppPrefs(preferences)
21 | }
22 |
23 | @Provides
24 | @ApplicationScoped
25 | open fun providePreferences(context: App): SharedPreferences {
26 | return context.getSharedPreferences(Preferences.APP_NAME, Context.MODE_PRIVATE)
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/module/ViewModelKey.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.module
2 |
3 | import androidx.lifecycle.ViewModel
4 | import dagger.MapKey
5 | import kotlin.reflect.KClass
6 |
7 |
8 | @MustBeDocumented
9 | @Target(AnnotationTarget.FUNCTION)
10 | @Retention(AnnotationRetention.RUNTIME)
11 | @MapKey
12 | internal annotation class ViewModelKey(val value: KClass)
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/module/ViewModelModule.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.module
2 |
3 | import androidx.lifecycle.ViewModel
4 | import androidx.lifecycle.ViewModelProvider
5 |
6 | import com.technorapper.boiler.di.WDViewModelFactory
7 | import com.technorapper.boiler.ui.onboarding.activity.MainActivityViewModel
8 | import dagger.Binds
9 | import dagger.Module
10 | import dagger.multibindings.IntoMap
11 |
12 | @Module
13 | abstract class ViewModelModule {
14 |
15 | @Binds
16 | @IntoMap
17 | @ViewModelKey(MainActivityViewModel::class)
18 | abstract fun bindMyViewModel(mainActivityViewModel: MainActivityViewModel): ViewModel
19 |
20 | @Binds
21 | abstract fun bindViewModelFactory(viewModelFactory: WDViewModelFactory): ViewModelProvider.Factory
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/scopes/ActivityScoped.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.scopes
2 |
3 | import java.lang.annotation.Documented
4 | import java.lang.annotation.Retention
5 | import java.lang.annotation.RetentionPolicy
6 | import javax.inject.Scope
7 |
8 | @kotlin.annotation.MustBeDocumented
9 | @Scope
10 | @kotlin.annotation.Retention
11 | annotation class ActivityScoped
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/scopes/ApplicationScoped.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.scopes
2 |
3 | import java.lang.annotation.Documented
4 | import java.lang.annotation.Retention
5 | import java.lang.annotation.RetentionPolicy
6 | import javax.inject.Scope
7 |
8 | @kotlin.annotation.MustBeDocumented
9 | @Scope
10 | @kotlin.annotation.Retention
11 | annotation class ApplicationScoped
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/scopes/BindingScoped.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.scopes
2 |
3 | import java.lang.annotation.Retention
4 | import java.lang.annotation.RetentionPolicy
5 | import javax.inject.Scope
6 |
7 | @Scope
8 | @kotlin.annotation.Retention
9 | @Target(
10 | AnnotationTarget.ANNOTATION_CLASS,
11 | AnnotationTarget.CLASS,
12 | AnnotationTarget.FUNCTION,
13 | AnnotationTarget.PROPERTY_GETTER,
14 | AnnotationTarget.PROPERTY_SETTER
15 | )
16 | annotation class BindingScoped
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/di/scopes/RandomUserApplicationScope.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.di.scopes
2 |
3 | import java.lang.annotation.RetentionPolicy
4 | import javax.inject.Scope
5 |
6 | @Scope
7 | @kotlin.annotation.Retention
8 | annotation class RandomUserApplicationScope
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/global/CustomBindingAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.global
2 |
3 | import android.widget.ImageView
4 | import androidx.databinding.BindingAdapter
5 | import com.technorapper.boiler.R
6 | import com.squareup.picasso.Picasso
7 |
8 |
9 | class CustomBindingAdapter(private val picasso: Picasso) {
10 |
11 | /* @BindingAdapter("android:src_url")
12 | fun loadImage(view: ImageView, url: String?) {
13 | if (url == null || url.equals("", ignoreCase = true)) {
14 | view.setImageResource(R.mipmap.ic_launcher)
15 | return
16 | }
17 | picasso.load(url).error(R.mipmap.ic_launcher).fit().into(view)
18 | }*/
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/helpers/AppPrefs.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.helpers
2 |
3 | import android.content.SharedPreferences
4 | import javax.inject.Inject
5 |
6 | class AppPrefs @Inject constructor(private val pref: SharedPreferences?) {
7 | var IS_LOGIN = "is_login"
8 | var TOKEN_ = "user_token"
9 |
10 | var isLogin: Boolean
11 | get() = pref!!.getBoolean(IS_LOGIN, false)
12 | set(value) {
13 | pref?.edit()?.putBoolean(IS_LOGIN, value)?.apply()
14 | }
15 |
16 | var TOKEN: String?
17 | get() = pref!!.getString(TOKEN_, "")
18 | set(value) {
19 | pref?.edit()?.putString(TOKEN_, value)?.apply()
20 | }
21 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/ui/base/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.ui.base
2 |
3 | import android.os.Bundle
4 | import androidx.fragment.app.Fragment
5 | import androidx.lifecycle.ViewModelProvider
6 | import com.technorapper.boiler.di.Injectable
7 | import dagger.android.DispatchingAndroidInjector
8 | import dagger.android.support.DaggerAppCompatActivity
9 | import dagger.android.support.HasSupportFragmentInjector
10 | import javax.inject.Inject
11 |
12 | abstract class BaseActivity : DaggerAppCompatActivity(), Injectable, HasSupportFragmentInjector{
13 |
14 | @Inject lateinit var viewModelFactory: ViewModelProvider.Factory
15 | @Inject
16 | lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector
17 |
18 | override fun onCreate(savedInstanceState: Bundle?) {
19 | super.onCreate(savedInstanceState)
20 | setBinding()
21 | attachViewModel()
22 |
23 | }
24 |
25 | protected abstract fun setBinding()
26 |
27 | protected abstract fun attachViewModel()
28 |
29 | override fun supportFragmentInjector() = fragmentDispatchingAndroidInjector
30 |
31 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/ui/base/BaseViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.ui.base
2 |
3 | import androidx.lifecycle.ViewModel
4 | import io.reactivex.disposables.CompositeDisposable
5 | import io.reactivex.disposables.Disposable
6 |
7 | open class BaseViewModel : ViewModel() {
8 | val compositeDisposable = CompositeDisposable()
9 |
10 | protected fun addToDisposable(disposable: Disposable?) {
11 | compositeDisposable.add(disposable!!)
12 | }
13 |
14 | fun onStop() {
15 | compositeDisposable.dispose()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/technorapper/boiler/ui/onboarding/activity/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.technorapper.boiler.ui.onboarding.activity
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.util.Log
6 | import android.widget.Button
7 | import androidx.lifecycle.ViewModelProvider
8 | import androidx.lifecycle.ViewModelProviders
9 | import com.technorapper.boiler.R
10 | import com.technorapper.boiler.data.tunnel.database.dao.UserMasterDao
11 | import com.technorapper.boiler.data.tunnel.remote.utils.AppSocket
12 | import com.technorapper.boiler.helpers.AppPrefs
13 | import com.technorapper.boiler.ui.base.BaseActivity
14 | import com.github.nkzawa.emitter.Emitter
15 | import kotlinx.android.synthetic.main.activity_main.*
16 | import timber.log.Timber
17 | import javax.inject.Inject
18 |
19 | class MainActivity : BaseActivity() {
20 |
21 |
22 | private lateinit var viewModel: MainActivityViewModel
23 | @Inject
24 | lateinit var socket: AppSocket
25 | @Inject
26 | lateinit var context: Context
27 | @Inject
28 | lateinit var sharedPreferences: AppPrefs
29 |
30 | @Inject
31 | lateinit var userMasterDao: UserMasterDao
32 |
33 | override fun onCreate(savedInstanceState: Bundle?) {
34 | super.onCreate(savedInstanceState)
35 | setContentView(R.layout.activity_main)
36 | if (sharedPreferences.isLogin) {
37 | Log.d("dff", userMasterDao.getAll().toString());
38 | }
39 |
40 | // val button = findViewById