sample-code-movies

Introduction: This repository contains sample code. Its purpose being, to quickly demonstrate Android and software development in general, clean code, best practices, testing and all those other must know goodies.
More: Author   ReportBugs   
Tags:

This repository contains sample code.

Its purpose being, to quickly demonstrate Android, Kotlin and software development in general. More so and amongst others, the main focus of this project is:

  • Setup and Gradle configuration,
  • Gradle modules,
  • Clean architecture,
  • Clean code,
  • Best practices,
  • Testing and
  • All those other must know goodies.

Below is a list of goodies that are being showcased:

  1. Architectural Patterns
    1. Modularization (Modularize the App Horizontally by Features)
    2. Navigation Component (Navigation refers to the interactions that allow users to navigate across, into, and back out from the different pieces of content within your app)
    3. Clean Architecture (By employing clean architecture, you can design applications with very low coupling and independent of technical implementation details, such as databases and frameworks. That way, the application becomes easy to maintain and flexible to change. It also becomes intrinsically testable.)
    4. Result (Add Result for Error Handling)
  2. UI Patterns
    1. MVVM (Model View ViewModel)
    2. MVI (Model View Intent)
    3. ViewModel (Architecture Components ViewModel Class)
    4. LivaData (Architecture Components LiveData Class)
  3. Kotlin
    1. Kotlin (A modern programming language that makes developers happier)
    2. Kotlin Symbol Processing (Kotlin Symbol Processing (KSP) is an API that you can use to develop lightweight compiler plugins. KSP provides a simplified compiler plugin API that leverages the power of Kotlin while keeping the learning curve at a minimum. Compared to kapt, annotation processors that use KSP can run up to 2 times faster)
    3. Kotlin Coroutines (Coroutines simplify asynchronous programming by putting the complications into libraries. The logic of the program can be expressed sequentially in a coroutine, and the underlying library will figure out the asynchrony for us)
    4. Asynchronous Flow (Suspending functions asynchronously returns a single value, but how can we return multiple asynchronously computed values? This is where Kotlin Flows come in)
  4. Android Support
    1. AndroidX (A new package structure to make it clearer which packages are bundled with the Android operating system, and which are packaged with your app's APK)
    2. Android KTX (Android KTX is a set of Kotlin extensions that is part of the Android Jetpack family)
    3. View Binding (View binding is a feature that allows you to more easily write code that interacts with views)
    4. Room Persistence Library (The Room persistence library provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite)
    5. Paging Library (The Paging Library helps you load and display small chunks of data at a time. Loading partial data on demand reduces usage of network bandwidth and system resources)
  5. Android UI
    1. Material Components (Modular and customizable Material Design UI components for Android)
    2. Dark Theme (Dark theme is available in Android 10 (API level 29) and higher)
    3. Constraint Layout (A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way)
    4. Recycler View (A flexible view for providing a limited window into a large data set)
    5. Shared Element Transition (Activity transitions in material design apps provide visual connections between different states through motion and transformations between common elements)
  6. Libraries
    1. Koin (A pragmatic lightweight dependency injection framework for Kotlin)
    2. Retrofit (Type-safe HTTP client for Android and Java by Square, Inc.)
    3. GSON (A Java serialization/deserialization library to convert Java Objects into JSON and back)
    4. Glide (An image loading and caching library for Android focused on smooth scrolling)
    5. Timber (A logger with a small, extensible API which provides utility on top of Android's normal Log class)
  7. Code Quality
    1. Android Lint (The lint tool checks your Android project source files for potential bugs and optimization improvements for correctness, security, performance, usability, accessibility, and internationalization)
    2. Detekt (Static code analysis for Kotlin)
  8. Tests
    1. JUnit4 (A programmer-oriented testing framework for Java)
    2. Strikt (Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit or Spek)
    3. MockK (MockK is a mocking library for Kotlin)
    4. Robolectric (Android Unit Testing Framework)
    5. MockWebServer (A scriptable web server for testing HTTP clients)
    6. Espresso (Use Espresso to write concise, beautiful, and reliable Android UI tests)
    7. Jacoco (JaCoCo is a free code coverage library for Java, which has been created by the EclEmma team based on the lessons learned from using and integration existing libraries for many years)
  9. Debug
    1. LeakCanary (A memory leak detection library for Android and Java)
    2. Strict Mode (StrictMode is a developer tool which detects things you might be doing by accident and brings them to your attention so you can fix them)
  10. Build
    1. Gradle Kotlin DSL (Kotlin language support for Gradle build scripts)
    2. Gradle Versions (Gradle plugin to discover dependency updates)
    3. Dependency Analysis (Gradle plugin for Java, Kotlin, and Android projects. Provides advice for managing dependencies and other applied plugins)
    4. Gradle Doctor (The right prescription for your Gradle build)
    5. Module Graph Assert (Gradle plugin to keep your modules graph healthy and lean.)

Mad Scorecards

  • December 2020 - G.O.A.T. You’re a MAD legend, the Greatest Of All Time of Android development.

Screenshots

alt tag

Usage

The first thing that you need to do in order to be able to build and run this project is to locate the 'local.properties' file (and if it doesn't exist, create it). Then, add the following properties:

# Gradle
gradle.ignored.variants=release
# The Movie Database (TMDb)
themoviedb.api.key=<YOUR.THEMOVIEDB.API.KEY>

For more information on how to configure Gradle for use with GitHub Packages visit Configuring Gradle for use with GitHub Packages.

For more information on how to configure the Gradle ignored variants read the specific 'Build Variant' section below.

For more information on how to obtain your personal TMDB api key visit
The Movie Database API (v3).

Build Variant

This project is setup in a way that can be configured to filter out on demand specific build variants by just specifying the 'ignored_variants' property, which is located within the 'local.properties' file. If no configuration is specified, then the default configuration will be applied, which is all build types and flavors.

Add the 'gradle.ignored.variants' property and assign that to a value. This value can be a single variant value, such as the 'release' built type or a comma separated list of variant values, such as 'debug,release,etc'. Any variant that goes in there will be then filtered out by the build.

This is mainly done in order to speed up build times and complexity during development, thus making developers happier since 
in most cases developers usually only care about the 'debug' build type (and a single build flavor, if that is even available).

Building The Project

All set, use the below command to build the project in order to install it on an Android device for demonstration:

./gradlew clean build -x check

Or faster yet and targeting a specific build type (in our case the debug build type):

./gradlew clean assembleDebug

Open an emulator or connect a physical device to experiment with the sample app, use the below command, which first uninstalls and then installs the sample app:

./gradlew uninstallDebug | ./gradlew installDebug

Or faster yet, target a specific device (in our case an emulator):

adb -s emulator-5554 uninstall io.petros.movies | 
adb -s emulator-5554 install app\build\outputs\apk\debug\app-debug.apk

Use this command in order to run the static code analysis for the project:

./gradlew check -x test

Or if you want to be more specific, run the below commands to run the code quality tool or your choice (in isolation):

./gradlew detekt
./gradlew lintDebug

Run the project unit tests using this command (this includes Robolectric):

./gradlew test

There might be a possibility that you encounter a Java version related problem while having the Robolectric tests run. In that case, first run 'java -version' and check the Java version on your machine. Them, you might end up needing to upgrade or downgrade your Java version to be able to run the Robolectric tests. This is a Robolectric's specific problem, which should get fixed in subsequent Robolectric releases.

Now, if you want to be more specific, run the below commands to run the tests or your choice (per module):

./gradlew <kotlin_module>:test
./gradlew <android_module>:testDebugUnitTest

Run the project instrumentation tests using this command (Espresso):

./gradlew connectedDebugAndroidTest

In order to run successfully the instrumentation tests and avoid flakiness, you need to turn off system animations on the device used for testing. To do so, on your device, under 'Settings -> Developer options', disable the following 3 settings within the 'DRAWING' section:

  • Window animation scale
  • Transition animation scale
  • Animator duration scale

Now, if you want to be more specific, run the below command to run the instrumentation tests or your choice (for app module):

./gradlew app:connectedDebugAndroidTest

Run the project Jacoco reports using this command:

./gradlew jacoco

If you feel like it you can also unleash the 'monkey' and stress test the app with some random instructions (10K of them should do it), use the below command:

adb shell monkey -p io.petros.movies.debug -v 10000

Use this command in order to check dependency updates for the project:

./gradlew dependencyUpdates

Run the project dependency analysis reports using this command:

./gradlew buildHealth

Run the project module graph assert reports using this command:

./gradlew assertModuleGraph

And if you feel like it you can also generate 'Graphviz' files to visualise the modularization result, see below commands:

./gradlew generateModulesGraphvizText -Pmodules.graph.print.statistics=true (command line visualization)
./gradlew generateModulesGraphvizText -Pmodules.graph.output.gv=module_graph_assert (file output for Graphviz visualization)
dot -T png modules_graph -O (convert the above generated .dot file to a .png file, you need to install Graphviz first)

Modularization

alt tag

Future

Below is a list of all those I REALLY WANNA DO future architecture and library enhancements:

  1. DONE Update Gradle to the Latest Version. For more info, see Gradle Release Notes
  2. DONE Update Android Studio to the Latest Canary Version. For more info, see Android Studio Release Updates
  3. DONE Replace current to the new AndroidX Package Structure. For more info, see AndroidX (A new package structure to make it clearer which packages are bundled with the Android operating system, and which are packaged with your app's APK)
  4. DONE Replace Manual Android Extensions with Android KTX. For more info, see Android KTX (Android KTX is a set of Kotlin extensions that is part of the Android Jetpack family)
  5. DONE Replace Gradle Groovy with Kotlin DSL. For more info, see Gradle Kotlin DSL (Kotlin language support for Gradle build scripts)
  6. DONE Replace RxJava with Coroutines. For more info, see Coroutines (Coroutines simplify asynchronous programming by putting the complications into libraries. The logic of the program can be expressed sequentially in a coroutine, and the underlying library will figure out the asynchrony for us)
  7. DONE Replace Dagger with Koin. For more info, see Koin (A pragmatic lightweight dependency injection framework for Kotlin)
  8. DONE Replace AssertJ with Strikt. For more info see Strikt (Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit or Spek)
  9. DONE Replace Mockito Kotlin with MockK. For more info see MockK (MockK is a mocking library for Kotlin)
  10. DONE Upgrade JUnit4 to Spek Framework and JUnit5. For more info, see Spek (A specification framework for Kotlin) and JUnit5 (JUnit 5 is the next generation of JUnit)
  11. DONE Support Android 10 (Target SDK 29). For more info, see Android 10 (Build app experiences with dark theme and gesture navigation. Support new protections for user privacy and security)
  12. DONE Re-add Detekt Plugin. For more info, see Detekt (Static code analysis for Kotlin)
  13. DONE Find new Versions Plugin. For example, see Gradle Versions Plugin (Gradle plugin to discover dependency updates)
  14. ⏸️ PAUSED Find new Dexcount Plugin. For example, see Dexcount Gradle Plugin (A Gradle plugin to report the number of method references in your APK on every build)
  15. DONE Migrate to View Binding (From Kotlin Android Extensions Plugin). For more info, see View Binding (View binding is a feature that allows you to more easily write code that interacts with views. Once view binding is enabled in a module, it generates a binding class for each XML layout file present in that module. An instance of a binding class contains direct references to all views that have an ID in the corresponding layout)
  16. DONE Modularize the App Horizontally by Features. To get an understanding of Modularization and how to it applies to an Android project, start with this Article Modularization (To take advantage of new distribution features (Instant apps, app bundles) from Google, or even just create a clear separation of concerns to make our project easier to work with— modularizing our applications can help us to achieve all of these things)
  17. DONE Add Result for Error Handling. To get an understanding of the power of types for errors, start with this Article Designing Errors with Kotlin (Exceptions! Developers adore exceptions. It is so easy to throw an error and forget about consequences. Is it a good idea though? Should Kotlin follow the same path? Fortunately enough there are many good languages we can learn from)
  18. DONE Add Code Coverage Reports for Tests with Jacoco. For more info see Jacoco (Java Code Coverage Library)
  19. DONE Add Integration Tests with MockWebServer (See MIT comment which stands for Missing Integration Tests). For more info, see MockWebServer (A scriptable web server for testing HTTP clients)
  20. DONE Add missing Unit Tests (See MUT comment which stands for Missing Unit Tests). For more info, see JUnit4 (JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks)
  21. DONE Add missing Robolectric Tests (See MRT comment which stands for Missing Robolectric Tests). For more info, see Robolectric (Robolectric is a framework that brings fast and reliable unit tests to Android)
  22. DONE Add missing Espresso Tests (See MET comment which stands for Missing Espresso Tests). For more info, see Espresso (Use Espresso to write concise, beautiful, and reliable Android UI tests)
  23. DONE Add Support for Dark Theme. For more info see Dark Theme (Dark theme is available in Android 10 (API level 29) and higher)
  24. DONE Enhance MVVM with MVI. To get an understanding of MVI and how it applies to MVVM (or MVP), start with this Article MVI (Model-View_Intent, is an architecture enhancement that tries to solve the state problem, which most complex application have, especially when the screen complexity grows)
  25. DONE Replace Manual Navigation with the Navigation Architecture Component. For more info, see Navigation Architecture Component (The Navigation Architecture Component simplifies the implementation of navigation in an Android app)
  26. DONE Add Offline Support with Room. For more info, see Room (The Room persistence library provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite)
  27. DONE Replace Manual Pagination with the Paging Architecture Component. For more info, see Paging Architecture Component (The Paging Library makes it easier for you to load data gradually and gracefully within your app's RecyclerView)
  28. ⏸️ PAUSED Add Chucker for HTTP Inspection. For more info see Chucker 🔎 An HTTP inspector for Android & OkHTTP (like Charles but on device) - More Chucker than Chuck
  29. ⚙️ IN PROGRESS Add Jetpack Compose. For more info see Jetpack Compose (Jetpack Compose simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs)
  30. 🛑 STOPPED Add Bitrise CI. For more info see Bitrise (Continuous Integration and Continuous Delivery for mobile apps)
  31. DONE Add GitHub Actions (instead of Bitrise CI). For more info see GitHub Actions (Automate, customize, and execute your software development workflows right in your repository with GitHub Actions. You can discover, create, and share actions to perform any job you'd like, including CI/CD, and combine actions in a completely customized workflow.)
  32. DONE Add Gradle Wrapper Validation Action. For more info see Gradle Wrapper Validation Action (This action validates the checksums of Gradle Wrapper JAR files present in the source tree and fails if unknown Gradle Wrapper JAR files are found.)
  33. DONE Add Dependabot. For more info see Dependabot (Monitor vulnerabilities in dependencies used in your project and keep your dependencies up-to-date with Dependabot.)
  34. DONE Add Version Catalog. For more info see Version Catalog (A version catalog is a list of dependencies, represented as dependency coordinates, that a user can pick from when declaring dependencies in a build script.)
  35. DONE Migrate to Convention Plugins with Build Logic (from buildSrc). For more info see Convention Plugins with Build Logic (Convention plugins are Gradle’s way of sharing your build logic between modules.)
  36. DONE Migrate to KSP (from kapt). For more info see Kotlin Symbol Processing (Kotlin Symbol Processing (KSP) is an API that you can use to develop lightweight compiler plugins. KSP provides a simplified compiler plugin API that leverages the power of Kotlin while keeping the learning curve at a minimum. Compared to kapt, annotation processors that use KSP can run up to 2 times faster.)
  37. Add Support for R8 (ProGuard). For more info see ProGuard and R8: a comparison of optimizers (ProGuard and R8 have three important functions, Shrinking or tree shaking: removes unused classes, fields and methods from the application, Code optimization: makes the code smaller and more efficient at the instruction level, Name obfuscation: renames the remaining classes, fields and methods with short meaningless names. At this point, it mostly reduces the size of the code)
  38. Sing the App. For more info see App Singing (Android requires that all APKs be digitally signed with a certificate before they can be installed. And you need to sign your Android App Bundle before you can upload it to the Play Console.)
  39. Create an Automated Release Process using Gradle Play Publisher Plugin. For more info see Gradle Play Publisher (Gradle plugin to upload your App Bundle or APK and other app details to the Google Play Store)
  40. Convert APK Upload Format to App Bundles. For more info see App Bundles (An Android App Bundle is a new upload format that includes all your app’s compiled code and resources, but defers APK generation and signing to Google Play)
  41. Add Jetpack Benchmark. For more info see Jetpack Benchmark (The Jetpack Benchmark library allows you to quickly benchmark your Kotlin-based or Java-based code from within Android Studio. The library handles warmup, measures your code performance, and outputs benchmarking results to the Android Studio console)
  42. Integrate Maps into the App. For more info see Maps SDK for Android (With the Maps SDK for Android, you can add maps based on Google Maps data to your application)
  43. Add Background Support with Work Manager. For more info see Work Manager (The WorkManager API makes it easy to specify deferrable, asynchronous tasks and when they should run)
  44. Add Support for Material Design 2.0. For more info see Material Design 2.0 (Make beautiful products, faster. Material is a design system – backed by open-source code – that helps teams build digital experiences)
  45. Enhance ConstraintLayout with MotionLayout. For more info see MotionLayout (A MotionLayout is a ConstraintLayout which allows you to animate layouts between various states)
  46. Add Support for App Shortcuts. For more info see App Shortcuts (Define shortcuts to perform specific actions in your app. These shortcuts can be displayed in a supported launcher and help your users quickly start common or recommended tasks within your app)
  47. Add Runtime Permissions with Permissions Dispatcher Library. For more info see Permissions Dispatcher (Simple annotation-based API to handle runtime permissions.)
  48. Add Settings Screen. For more info see Settings (Settings allow users to change the functionality and behavior of an application)
  49. Add Support for Firebase Crashlytics. For more info see Firebase Crashlytics (Get clear, actionable insight into app issues with this powerful crash reporting solution for Android and iOS)
  50. Add Support for Firebase Performance Monitoring. For more info see Firebase Performance Monitoring (Gain insight into your app's performance issues)
  51. Add Support for Firebase Remote Config. For more info see Firebase Remote Config (Change the behavior and appearance of your app without publishing an app update, at no cost, for unlimited daily active users.)
  52. Add Support for Firebase Push Notifications. For more info see Firebase Cloud Messaging (Firebase Cloud Messaging (FCM) is a cross-platform messaging solution that lets you reliably deliver messages at no cost)
  53. Create a Continue Integration Environment using GitLab. For more info see GitLab Continuous Integration & Delivery (GitLab has integrated CI/CD pipelines to build, test, deploy, and monitor your code)
  54. Enable Deep Links and Android App Links. For more info see Android App Links (Set up Android App Links to take users to a link's specific content directly in your app, bypassing the app-selection dialog, also known as the disambiguation dialog)
  55. Add Support for Finger Print Login. For more info see Fingerprint Authentication (New APIs to let you authenticate users by using their fingerprint scans on supported devices)
  56. Add Support for Instant Apps. For more info see Google Play Instant (Google Play Instant enables native apps and games to launch on devices running Android 5.0 (API level 21) without being installed)
  57. Add Support for Slices. For more info see Slices (Slices are UI templates that can display rich, dynamic, and interactive content from your app from within the Google Search app and later in other places like the Google Assistant)
  58. Add AdMob as a Source of App Monetization. For more info see AdMob (AdMob makes earning revenue easy with in-app ads, actionable insights, and powerful, easy-to-use tools that grow your app business)
  59. Add Google Play Billing as a Source of App Monetization. For more info see Google Play Billing Library (Google Play Billing is a service that lets you sell digital content from inside an Android app, or in-app)
  60. Add Support for Machine Learning. For more info see ML Kit (ML Kit beta brings Google’s machine learning expertise to mobile developers in a powerful and easy-to-use package)
  61. Make the App compliant with Android's Accessibility Features and Services. For more info see Accessibility (Accessibility is an important part of any app. Whether you're developing a new app or improving an existing one, consider the accessibility of your app's components)
  62. Convert Imperative to Functional Programming. For more info see Arrow (Functional companion to Kotlin's Standard Library)
  63. Add Kotlin Native Support to Build the iOS equivalent App. For more info see Kotlin Native (Kotlin/Native is a technology for compiling Kotlin code to native binaries, which can run without a virtual machine)
  64. Add Kotlin Multiplatform Support to Share Code between the Android and iOS App. For more info see Kotlin Multiplatform (Kotlin Multiplatform brings the invaluable benefit of reuse for code and expertise, saving the effort for tasks more challenging than implementing everything twice or multiple times)

THANK YOU

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools