├── .gitignore ├── .idea ├── $CACHE_FILE$ ├── codeStyles │ └── Project.xml └── misc.xml ├── LICENSE ├── README.md └── images ├── best_practice.jpeg ├── build_variants.png ├── layout_structure.png └── modularization.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | # Android Studio 3 in .gitignore file. 48 | .idea/caches 49 | .idea/modules.xml 50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 51 | .idea/navEditor.xml 52 | 53 | # Keystore files 54 | # Uncomment the following lines if you do not want to check your keystore files in. 55 | #*.jks 56 | #*.keystore 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | .cxx/ 61 | 62 | # Google Services (e.g. APIs or Firebase) 63 | # google-services.json 64 | 65 | # Freeline 66 | freeline.py 67 | freeline/ 68 | freeline_project_description.json 69 | 70 | # fastlane 71 | fastlane/report.xml 72 | fastlane/Preview.html 73 | fastlane/screenshots 74 | fastlane/test_output 75 | fastlane/readme.md 76 | 77 | # Version control 78 | vcs.xml 79 | 80 | # lint 81 | lint/intermediates/ 82 | lint/generated/ 83 | lint/outputs/ 84 | lint/tmp/ 85 | # lint/reports/ 86 | -------------------------------------------------------------------------------- /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Android 10 | 11 | 12 | Chrome OSCorrectnessLintAndroid 13 | 14 | 15 | Code style issuesJava 16 | 17 | 18 | CorrectnessLintAndroid 19 | 20 | 21 | Declaration redundancyJava 22 | 23 | 24 | Java 25 | 26 | 27 | LintAndroid 28 | 29 | 30 | Probable bugsJava 31 | 32 | 33 | 34 | 35 | OptionalAssignedToNull 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | ## Title: Android Development | Best Practices 2 | 3 | ![Best Practices](/images/best_practice.jpeg) 4 | 5 | ## Introduction 6 | 7 | Android development continues to dominate the world of mobile development. 8 | Fun projects, great pay, and tons of job prospects are just some of the reasons developers are starting their journeys into the exciting world of the Android operating system. 9 | Some [experts](https://proandroiddev.com/theres-never-been-a-better-time-to-learn-android-development-d1724409bdfc) say that there has never been a better time to learn Android skills, especially since the recent updates, like the addition of Kotlin and improvements to Google’s policies. 10 | 11 | It’s been five years now that I’ve been into Android development and there has been no single day I haven't learned something new. But with these passing years, what I have realized is: 12 |
Just writing the code is not enough, Writing in an efficient way is the real challenge. 13 | 14 | ### Tips and not Tricks 15 | 16 | 1) Choose your App Architecture wisely based on your need, not just what the trend is.

17 | The architecture defines where the application performs its core functionality and how that functionality interacts with things like the database and the user interface. 18 |
We have many architectures like MVC, MVP, MVVM, MVI, Clean Architecture. 19 |
If any of these architectures is fulfilling your project requirements and you are following the standard coding guidelines and keeping your code clean, no architecture is bad. 20 | 21 | 2) Consider using SVGs or WebPs for your image drawables.

22 | Supporting multiple resolutions are a sometimes nightmare to developers. Including multiple images for different resolutions also increases the project size. 23 |
The solution is to use Vector Graphics such as SVG images or use WebP which can make a big difference in solving the image size problem by compressing lossless images. 24 | 25 | 3) Choose your layout wisely and separate out the reusable XML and add it using [include](https://developer.android.com/training/improving-layouts/reusing-layouts) tag.

26 | We have different layouts like [ConstraintLayout](https://developer.android.com/training/constraint-layout), [LinearLayout](https://developer.android.com/reference/android/widget/LinearLayout), 27 | [RelativeLayout](https://developer.android.com/guide/topics/ui/layout/relative), [FrameLayout](https://developer.android.com/reference/android/widget/FrameLayout), 28 | [CoordinatorLayout](https://developer.android.com/reference/androidx/coordinatorlayout/widget/CoordinatorLayout). I did [performance](https://medium.com/1mgofficial/constraintlayout-vs-other-layouts-a-battle-towards-performance-part-1-14d8116e876e) analysis for some of them and found out that one should use layout based on their scenario/requirement only. 29 |
Also, If you have some part of your XML getting reused in different layouts, extract it in a separate layout and use tag to avoid replication of code in different layouts. 30 | 31 | 4) Learn how to use [Build types](https://www.journaldev.com/21533/android-build-types-product-flavors), [Product Flavors](https://levelup.gitconnected.com/simple-guide-to-android-product-flavors-674106455038#:~:text=Simply%20put%2C%20a%20product%20flavor,app%20using%20a%20single%20codebase.) and [Build Variants](https://developer.android.com/studio/build/build-variants) and make most out of it for faster and easier development.

32 | #### Build Type 33 | Decides how our code will be compiled. For instance, If we want to sign our .apk with debug key, we put our debug configuration into debug build type. If we want to have obfuscated code when it is compiled and ready to release, we put that configuration on our release build type. If we want to log our HTTP request in debug mode but we want to disable it on release mode, we put that configuration on build types or call build types in library dependencies. 34 | 35 | ``` 36 | buildTypes 37 | { 38 | release { 39 | minifyEnabled true 40 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 41 | } 42 | debug { 43 | applicationIdSuffix ".debug" 44 | } 45 | } 46 | ``` 47 | 48 | Here is the simplest example:
49 | When you run your app in debug mode, your application package name will be packagename.debug and if you run your app in release mode, your application package name will be packagename. 50 | 51 | ### Product Flavor
52 | Let’s say we have are developing your app for your customer users. Everything is going fine for customer app. Then your product owner said that you need to develop that app for admin users. Admin user app should have all functionalities that customer app has. But also admin user can have access to statistics page and admin user should see the app in different colours and resources. And also your admin app’s analytics should not be mixed with customer app.What will you do? The answer is Product Flavor. Same app, different behaviour. 53 | 54 | Edit your Gradle file: 55 | 56 | ``` 57 | android 58 | { 59 | ... 60 | defaultConfig {...} 61 | buildTypes {...} 62 | productFlavors { 63 | admin { 64 | .. 65 | } 66 | customer { 67 | .. 68 | } 69 | } 70 | } 71 | ``` 72 | 73 | ### Build Variants 74 | Combines your build types and product flavors. Sync your project after you update your build.gradle. Then you will see all your build variants. 75 | 76 | ![Build Variants](/images/build_variants.png) 77 | 78 | 5) Learn & Use [Android Debug Bridge (ADB)](https://developer.android.com/studio/command-line/adb#:~:text=Android%20Debug%20Bridge%20(adb)%20is,of%20commands%20on%20a%20device.) to debug your application.

79 | Android Debug Bridge (ADB) is a versatile command-line tool that lets you communicate with a device. 80 | It allows you to do things on an Android device that may not be suitable for everyday use, yet can greatly benefit your user or developer experience. For example, you can install apps outside of the Play Store, debug apps, access hidden features, and bring up a Unix shell so you can issue commands directly on the device. 81 | ADB provides you with more details than your Android Studio Logcat. Just try it once and you can thank me later :-) 82 | 83 | 6) Configure your gradle.properties to increase your build speed.

84 | Long build times have always been a problem in the developer’s life. 85 | 86 | ``` 87 | org.gradle.daemon=true 88 | org.gradle.parallel=true 89 | org.gradle.configureondemand=true 90 | android.enableBuildCache=true 91 | org.gradle.jvmargs=-Xmx3072m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 92 | org.gradle.caching= true 93 | android.useAndroidX=true 94 | android.enableJetifier=true 95 | kapt.incremental.apt=true 96 | kapt.use.worker.api=true 97 | ``` 98 | 99 | Showing you a sample of enhancements I did. You can read more about speeding up [here](https://developer.android.com/studio/build/optimize-your-build). 100 | 101 | 7) Keep a check on structural problems in your App code through [Lint](https://developer.android.com/studio/write/lint).

102 | The lint tool helps find poorly structured code that can impact the reliability and efficiency of your Android apps. 103 | The command for MAC: 104 | ``` 105 | ./gradlew lint 106 | ``` 107 | For Windows: 108 | ``` 109 | gradlew lint 110 | ``` 111 | 112 | 8) Log everything in DEBUG mode only.

113 | We use logs to display useful information, errors, workflows or even to debug something. 114 |
But, Every information that we log can be a potential source of security issues! So make sure you remove before the code goes live. 115 |
And If you really want to keep these logs, you can either use [Timber](https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d) library which can log your messages and gives you the control over the flow of logs or you can create your own [custom class](https://gist.github.com/niharika2810/eaf5b35b65b73883ef7714c57b3dffae) to print logs in debug mode. 116 | 117 | 9) Never add whole third party library if it’s possible for you to extract specific methods or small no. of classes for your functionality.
118 |
Just add those classes to your project and modify them accordingly. 119 | 120 | 10) Detect and Fix memory leaks in Android App time to time.

121 | “A small leak will sink a great ship.” — Benjamin Franklin 122 |
Use memory tools like [Leak canary](https://square.github.io/leakcanary/) to detect the cause for the memory leak. 123 | 124 | Its knowledge of the internals of the Android Framework gives it a unique ability to narrow down the cause of each leak, helping developers dramatically reduce OutOfMemoryError crashes. 125 | 126 | 11) Handle [Configuration changes](https://developer.android.com/guide/topics/resources/runtime-changes) for your App.

127 | Sometimes handling the orientation changes for your Activity, Fragment or AsyncTasks becomes most frustrating things to deal. If orientation changes are not handled properly then it results in unexpected behaviour of the application. 128 | When such changes occur, Android restarts the running Activity means it destroys and again created. 129 |
There are different options to handle the orientation changes:
130 | 1. Lock screen orientation
131 | 2. Prevent Activity to recreated
132 | 3. Save basic state
133 | 4. Save complex objects
134 | 135 | 12) Perform validations in screens like input form on Client end only.

136 | Do we really need to hit backend for the validations like Is users email valid or Is user’s contact number is of the required length? 137 |
Consider this kind of cases and write your logic accordingly. 138 | 139 | 13) Don’t create references to activities that will prevent them from being garbage collected when they are done.

140 | Consider a very simple scenario — you need to register a local broadcast receiver in your activity. If you don’t unregister the broadcast receiver, then it still holds a reference to the activity, even if you close the activity. 141 | 142 | How to solve this?
Always remember to call unregister receiver in onStop() of the activity. 143 | 144 | Like this, Find more scenarios and fix them. 145 | 146 | 14) Use App Chooser for your implicit intents and always handle NoActivityFound Exception.

147 | If multiple apps can respond to the intent and the user might want to use a different app each time, you should explicitly show a chooser dialog. 148 |
Also, if for some reason no app is available, your app shouldn’t crash. Please handle it through try /catch with showing some toast message to the user. 149 | 150 | 15) Put all your sensitive information in gradle.properties and never push it to your version control system.

151 | Don’t do this. This would appear in the version control system. 152 | 153 | 154 | ``` 155 | signingConfigs 156 | { 157 | release { 158 | // DON'T DO THIS!! 159 | storeFile file("myapp.keystore") 160 | storePassword "password123" 161 | keyAlias "thekey" 162 | keyPassword "password789" 163 | } 164 | } 165 | ``` 166 | 167 | Instead, make a gradle.properties file : 168 | 169 | ``` 170 | KEYSTORE_PASSWORD=password123 171 | KEY_PASSWORD=password789 172 | ``` 173 | 174 | That file is automatically imported by Gradle, so you can use it in build.gradle as such: 175 | 176 | ``` 177 | signingConfigs 178 | { 179 | release 180 | { 181 | try 182 | { 183 | storeFile file("myapp.keystore") 184 | storePassword KEYSTORE_PASSWORD 185 | keyAlias "thekey" 186 | keyPassword KEY_PASSWORD 187 | } 188 | catch (ex) { 189 | throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.") 190 | } 191 | } 192 | } 193 | ``` 194 | 195 | 16) Implement SSL certificate pinning to prevent [Man-in-the-middle Attack (MITM)](https://ieeexplore.ieee.org/document/4768661/?part=1).

196 | To intercept any request, we mostly use a proxy tool. The proxy tool installs its own certificate on the device and application trust that certificate as a valid certificate and allow proxy tool to intercept application traffic. This way we can help hackers to tamper or know our data stuff. 197 |
With SSL Pinning implementation, the application does not trust custom certificates and does not allow proxy tools to intercept the traffic. 198 |
It’s a method that depends on server certificate verification on the client-side. Read more [here](https://www.nowsecure.com/blog/2017/06/15/certificate-pinning-for-android-and-ios-mobile-man-in-the-middle-attack-prevention/). 199 | 200 | 17) Use [SafetyNet Attestation API](https://developer.android.com/training/safetynet/attestation) to help determine whether your servers are interacting with your genuine app running on a genuine Android device.

201 | The API verifies the following: 202 | 1) Whether the device is rooted or not.
203 | 2) Whether the device is monitored.
204 | 3) Whether the device has recognized hardware parameters.
205 | 4) Whether the software is Android compatible.
206 | 5) Whether the device is free form malicious apps.
207 | But before implementing it, please check the [Dos and Don’ts](https://developer.android.com/training/safetynet/attestation-checklist). 208 | 209 | 18) Use [EncryptedSharedPreferences](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences) instead of SharedPreferences for storing sensitive information like your auth tokens etc.

210 | 211 | 19) Use the [Android Keystore system](https://medium.com/@josiassena/using-the-android-keystore-system-to-store-sensitive-information-3a56175a454b) to store and retrieve sensitive information from your storage like databases etc.

212 | 213 | The [Android keystore](https://developer.android.com/training/articles/keystore.html) provides a secure system level credential storage. With the keystore, an app can create a new Private/Public key pair, and use this to encrypt application secrets before saving it in the private storage folders. 214 | While developing AarogyaSetu, I learnt about using Keystore for encrypting and decrypting highly sensitive information. You can check the implementation [here](https://github.com/nic-delhi/AarogyaSetu_Android).
215 | 216 | >Note: We have an [Android Backup](https://developer.android.com/guide/topics/data/autobackup) mechanism which is turned on by default. Android preserves app data by uploading it to the user’s Google Drive — where it’s protected by the user’s Google Account credentials and can be easily downloaded for the same credentials on other devices. 217 | >But, When you have encrypted something with Android Keystore, you won’t be able to restore it because the cypher key is only for that specific device. We don’t have a sync mechanism for Keystore like iOS and their keychain. A better way to backup your users’ data is to store them on your backend. 218 | 219 | 20) Call Google Play services methods to ensure that your app is running on a device that has the latest updates to protect against known vulnerabilities found in the default security provider.

220 | For example, a vulnerability was discovered in OpenSSL ([CVE-2014–0224](http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-0224)) that can leave apps open to a “man-in-the-middle” attack that decrypts secure traffic without either side knowing. With Google Play services version 5.0, a fix is available, but apps must ensure that this fix is installed. By using the Google Play services methods, your app can ensure that it’s running on a device that’s secured against that attack.
221 | To protect against these vulnerabilities, [Google Play services](https://developers.google.com/android/guides/overview) provides a way to automatically update a device’s security provider to protect against known exploits. Read more [here](https://developer.android.com/training/articles/security-gms-provider). 222 | 223 | 21) Implement [reCAPTCHA](https://developer.android.com/training/safetynet/recaptcha) to ensure your app is not automated i.e handled by a robot.

224 | reCAPTCHA is a free service that uses an advanced risk analysis engine to protect your app from spam and other abusive actions. If the service suspects that the user interacting with your app might be a bot instead of a human, it serves a CAPTCHA that a human must solve before your app can continue executing. 225 | 226 | 22) Write [Unit tests](https://developer.android.com/training/testing/unit-testing) for your feature.

227 | Listing out some benefits:
228 | * Unit tests help to fix bugs early in the development cycle and save costs.
229 | * It helps the developers to understand the code base and enables them to make changes quickly
230 | * Good unit tests serve as project documentation.
231 | * You become more confident about the stuff you are writing.
232 | There are many more [benefits](https://www.seguetech.com/the-benefits-of-unit-testing/).:-) 233 | 234 | 23) Make security decisions on the server-side whenever possible.

235 | Don’t trust your application’s client-side. Hacker can easily tamper or hack your application’s codebase and can manipulate your code. So, it's better to have checks on the backend side whenever possible. 236 | 237 | 24) Learn how to use [Proguard](https://developer.android.com/studio/build/shrink-code) to the maximum for code Obfuscation and Optimization.

238 | It is quite easy to reverse engineer Android applications, so if you want to prevent this from happening, you should use ProGuard for its main function: obfuscation, a process of creating source code in a form that is hard for a human to understand(changing the name of classes and members).
239 | ProGuard has also two other important functions: shrinking which eliminates unused code and is obviously highly useful and also optimization. 240 |
Optimization operates with Java bytecode, though, and since Android runs on Dalvik bytecode which is converted from Java bytecode, some optimizations won’t work so well. So you should be careful there. 241 | 242 | 25) Use [Network security configuration](https://developer.android.com/training/articles/security-config) to improve your app’s network security.

243 | Security is more about layers of protection than a single iron wall. The Android Network Security Configuration feature provides a simple layer to protect apps from unintentionally transmitting sensitive data in unencrypted cleartext.
244 | If you don’t know what “unencrypted communications” means, think of it this way — let’s say your office has the policy to send all shipments via UPS. A new intern joins the office and is tasked with shipping equipment to an office across the country.
Oblivious to the policy and with all the best intentions, the intern sets up all shipments to be sent through an unknown, less expensive service.
The Android Network Security Configuration feature is like the shipping/receiving manager who examines all inbound and outbound shipments and stops the shipment before the equipment gets into the hands of an unvetted delivery system. It can be used to prevent the accidental use of untrusted, unencrypted connections. 245 |
Read more [here](https://www.nowsecure.com/blog/2018/08/15/a-security-analysts-guide-to-network-security-configuration-in-android-p/). 246 | 247 | 26) Use [In-app review API](https://developer.android.com/guide/playcore/in-app-review) to give users the ability to leave a review from within the app, without heading back to the App Details page. For many developers, ratings and reviews are an important touchpoint with users. Millions of reviews are left on Google Play every day, offering developers valuable insight on what users love and what they want to be improved. Users also rely on ratings and reviews to help them decide which apps and games are right for them. 248 | 249 | Over the past two years, Google Play has launched various features to make it easier for users to leave reviews, as well as for developers to interact and respond to them. For example, users are now able to leave reviews from the Google Play homepage. We also launched the Reviews page under My Apps & Games, which gives users a centralized place to leave and manage reviews.The API lets developers choose when to prompt users to write reviews within the app experience. We believe the best time to prompt your users is when they have used the app enough to be able to provide thorough and useful feedback. However, be sure not to interrupt them in the middle of a task or when their attention is needed, as the review flow will take over the action on the screen. 250 | 251 | 27) Introduce [Modularization](https://medium.com/google-developer-experts/modularizing-android-applications-9e2d18f244a0) in app. 252 | 253 | Split your app module into different small modules, and give those modules as dependency to required modules like ```implementation project(":network-module")``` , you will get benefit of faster builds while developing your app and reusable code. Later you can extend this to provide dynamic delivery module.

254 | ![Build Variants](/images/modularization.png) 255 | 256 |
Read more [here](https://medium.com/swlh/modularization-by-feature-and-layer-with-android-architecture-components-80bf317d737). 257 | 258 | 28) Avoid using too many base classes. Using base class everywhere creates a tight web in your code, which later makes it hard to refactor things. If still it's a necessity, create and use a standalone function (kotline file). 259 | Lets understand this with an example : 260 | You have 2 fragments namely ProfileFragment and HomeFragment, which extends from BaseFragment. BaseFragment has a function fetchPosts() in the onCreate() method, Now if in future you decide that ProfileFragment should not fetch posts when it is created, rather it should first show a dialogBox if the user is not logged-in. If the codebase is huge, you may have hardtime refactoring it. The other way around is to create a kotlin file as fun fetchPosts() and then use this function in your fragments in the onCreate() method or in a swipeRefresh() method (depending on your use case). Also one must note that a class can extend only one abstract base class. 261 | 262 | Read more [here](https://codeburst.io/inheritance-is-evil-stop-using-it-6c4f1caf5117), [here](https://dev.to/antonholmberg/the-baseclass-anti-pattern-16il), [here](https://proandroiddev.com/say-no-to-baseactivity-and-basefragment-83b156ed8998). 263 | 264 | 29) If you are using FirebaseFireStore in your application then don't directly write 'true' on the read and write rules to decrease security issues as it can help hackers to penetrate through your application.To clear this out lets see the default rules written in fireStore - 265 | 266 |
267 |
rules_version = '2'; 268 | service cloud.firestore { 269 | match /databases/{database}/documents { 270 | match /{document=**} { 271 | allow read, write: if false; 272 | } 273 | } 274 | }
275 |
276 | If we directly change false --> true it will no doubt work fine but its not secure because here acc to the rules everyperson has the permission to read and write the database so instead we use --> 277 |
278 |
rules_version = '2'; 279 | service cloud.firestore { 280 | match /databases/{database}/documents { 281 | match /{document=**} { 282 | allow read, write: if request.auth!=null; 283 | } 284 | } 285 | }
286 |
287 | This will allow only logged users to write over db. For more about writing rules check this out : https://firebase.google.com/docs/rules 288 | 289 |
290 | 291 | Read more [here](https://codeburst.io/inheritance-is-evil-stop-using-it-6c4f1caf5117) and [here](https://dev.to/antonholmberg/the-baseclass-anti-pattern-16il). 292 | 293 | 30) Create sourceSets for your main layout folder by adding following snippet in app level build.gradle file as follows 294 | 295 | ``` 296 | android { 297 | ... 298 | 299 | sourceSets { 300 | main { 301 | res.srcDirs = [ 302 | 'src/main/res', 303 | 'src/main/res/layouts', 304 | file('src/main/res/layouts').listFiles() 305 | ] 306 | } 307 | } 308 | } 309 | ``` 310 | 311 | Now you can separate out activity layouts, fragment layout and custom layouts in their respective folder as shown 312 | 313 | ![Build Variants](/images/layout_structure.png) 314 | 315 | This will make navigating for layout files a lot easier and keep resources segregated. 316 | 317 | 318 | #### The Critics principle
319 | When you’re reviewing code of your teammates don’t be a friend, Be their arch enemy, don’t let them make mistakes that you might have to clean someday. Cleaning other’s shit will only make your hand dirty. Enforce good practices in code reviews. 320 | 321 | Please feel free to contribute by raising a [PR](https://github.com/niharika2810/android-development-best-practices/compare) to add more. I will be happy to learn and share :-) 322 | 323 | You can check the article [here](https://proandroiddev.com/android-development-best-practices-7278e9cdbbe9) which is originally published here on my [personal website](https://thedroidlady.com/2020-07-23-android-development-best-practices). 324 | 325 | -------------------------------------------------------------------------------- /images/best_practice.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niharika2810/android-development-best-practices/6cd31cd4caca19304986ec7213cbab22fc3ba9d3/images/best_practice.jpeg -------------------------------------------------------------------------------- /images/build_variants.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niharika2810/android-development-best-practices/6cd31cd4caca19304986ec7213cbab22fc3ba9d3/images/build_variants.png -------------------------------------------------------------------------------- /images/layout_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niharika2810/android-development-best-practices/6cd31cd4caca19304986ec7213cbab22fc3ba9d3/images/layout_structure.png -------------------------------------------------------------------------------- /images/modularization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/niharika2810/android-development-best-practices/6cd31cd4caca19304986ec7213cbab22fc3ba9d3/images/modularization.png --------------------------------------------------------------------------------