Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: set up JDK 1.11
uses: actions/setup-java@v1
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 1.11
java-version: 17
distribution: temurin
- name: Build with Gradle
run: ./gradlew assembleDebug
run: ./gradlew assembleDebug
54 changes: 9 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,38 @@
![Android CI](https://github.com/ashwini009/TvFlix/workflows/Android%20CI/badge.svg?branch=master&event=push) ![GitHub top language](https://img.shields.io/github/languages/top/ashwini009/TvFlix?style=plastic) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=21) ![GitHub stars](https://img.shields.io/github/stars/ashwini009/TvFlix?style=social) ![GitHub forks](https://img.shields.io/github/forks/ashwini009/TvFlix?style=social)


# TvFlix :tv:
# TvFlix :tv:

The aim of this app is to replicate the high level functionality of www.tvmaze.com and showcase an android app out of it.
The aim of this app is to replicate the high level functionality of www.tvmaze.com and showcase an android app out of it.
It connects with [TVDB API](https://api.thetvdb.com) to give you popular shows and let you mark anyone as favorite.
TvFlix consists of 3 pieces of UI right now:
1. Home with Popular Shows
2. Favorites
3. All Shows

This app is under development. :construction_worker: :hammer_and_wrench:

*Note: TvFlix is an unofficial app built only for learning and sharing the latest concepts with #AndroidDevs*

## Android Development and Architecture

* The entire codebase is in [Kotlin](https://kotlinlang.org/)
* Uses Kotlin [Coroutines](https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html).
* Uses [Jetpack Compose](https://developer.android.com/jetpack/compose) for UI
* Uses Kotlin [Coroutines](https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html) and [StateFlow](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/) for reactive state management
* Uses MVVM Architecture by [Architecture Components](https://developer.android.com/topic/libraries/architecture/). Room, ViewModel, Paging
* Uses [Hilt Android](https://developer.android.com/training/dependency-injection/hilt-android) with [Dagger](https://dagger.dev/) for dependency injection
* Uses [KSP](https://developer.android.com/build/migrate-to-ksp) for annotation processing
* Unit Testing by [Mockito](https://github.com/mockito/mockito)
* Tests Coroutines and architecture components like ViewModel
* UI Test by [Espresso](https://developer.android.com/training/testing/espresso) based on [Robot Pattern](https://academy.realm.io/posts/kau-jake-wharton-testing-robots/)
* UI Test by [Compose Testing](https://developer.android.com/jetpack/compose/testing)
* Uses [Kotlin Coroutines Test](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/) to unit test Kotlin Coroutines
* Uses [StateFlow](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-state-flow/) as a replacement over LiveData as a state-holder observable
* Uses [Firebase Remote Config](https://firebase.google.com/products/remote-config) for experimentation and feature rollout
* Uses [Firebase App Distribution](https://firebase.google.com/products/app-distribution) for internal distribution and quality testing

## Further Reading

There are several articles written on this repository which state the design and architecture.

### Kotlin Everywhere. Coroutines, Tests, Robots and much more…

The TvFlix complete repository has been re-written in Kotlin with Coroutines covering
Unit Tests across ViewModels and UI tests for the app.
Know more:
[Kotlin Everywhere. Coroutines, Tests, Robots and much more…](https://proandroiddev.com/kotlin-everywhere-coroutines-tests-robots-and-much-more-b02030206cc9)

### MVVM using Android Architecture Components

The codebase tries to follow Uncle Bob Clean Code Architecture with [SOLID principles](https://en.wikipedia.org/wiki/SOLID).
Know more:
[Migration from MVP to MVVM using Android Architecture Components](https://medium.com/@kumarashwini/migration-from-mvp-to-mvvm-using-android-architecture-components-4bc058a1f73c)

### Pagination using Paging Library

The Shows screen displays the list of shows fetched from TvMaze API using [Paging3](https://developer.android.com/topic/libraries/architecture/paging/v3-overview) of Android Architecture Components. It also handles the retry if any network error occurred. Recently the repository has been [migrated to use Paging3](https://github.com/reactivedroid/TvFlix/pull/14).
Paging3 is in heavy development, and if you want to catch up with stable library(Paging 2), then check out this blog
[Pagination using Paging Library with RxJava and Dagger](https://medium.com/@kumarashwini/pagination-using-paging-library-with-rxjava-and-dagger-d9d05dbd8eac)

### Room Persistence Library

The Favourites screen displays the list of shows marked favourites from the Home screen. The user can add/remove from
the favorites as and when required. The implementation of the favorites is done using `Room` Persistence Library with RxJava and Dagger.
Know more:
[Room with RxJava and Dagger](https://medium.com/@kumarashwini/room-with-rxjava-and-dagger-2722f4420651)

### Static Code Analysis

TvFlix has Static Code Analysis tools like FindBugs, PMD and Checkstyle integrated. These tools help in finding potential bugs that would have been missed and help in making the codebase clean.
Know more:
[Static Code Analysis for Android Using FindBugs, PMD and CheckStyle](https://blog.mindorks.com/static-code-analysis-for-android-using-findbugs-pmd-and-checkstyle-3a2861834c6a)
* Uses [Paging3](https://developer.android.com/topic/libraries/architecture/paging/v3-overview) for paginated show listing

## Contributions

If you have found an issue in this sample, please file it.
Better yet, if you want to contribute to the repository, go ahead, any kind of patches are encouraged,
and may be submitted by forking this project and submitting a pull request.
and may be submitted by forking this project and submitting a pull request.
If you have something big in mind, or any architectural change, please raise an issue first to discuss it.

## License
Expand All @@ -93,4 +57,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
```
67 changes: 31 additions & 36 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
plugins {
id("com.android.application")
kotlin("android")
kotlin("kapt")
kotlin("plugin.compose")
id("com.google.devtools.ksp")
kotlin("plugin.parcelize")
id("dagger.hilt.android.plugin")
id("com.google.gms.google-services")
Expand All @@ -21,6 +22,7 @@ android {
buildFeatures {
viewBinding = true
dataBinding = true
compose = true
buildConfig = true
}

Expand All @@ -31,17 +33,11 @@ android {
versionCode = Deps.Versions.app_version_code
versionName = Deps.Versions.app_version_name
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
// Refer https://developer.android.com/jetpack/androidx/releases/room#compiler-options
arguments(
mapOf(
"room.schemaLocation" to "$projectDir/schemas",
"room.incremental" to "true",
"room.expandProjection" to "true"
)
)
}

ksp {
arg("room.schemaLocation", "$projectDir/schemas")
arg("room.incremental", "true")
arg("room.expandProjection", "true")
}
}
flavorDimensions.addAll(listOf("default"))
Expand Down Expand Up @@ -76,26 +72,18 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

testOptions {
unitTests.isIncludeAndroidResources = true
animationsDisabled = true
}

kapt {
useBuildCache = true
javacOptions {
// Increase the max count of errors from annotation processors.
// Default is 100.
option("-Xmaxerrs", 500)
}
}
testBuildType = "debug"

packagingOptions {
packaging {
resources.excludes.addAll(
listOf(
"META-INF/ASL2.0",
Expand All @@ -110,8 +98,9 @@ android {
}

kotlinOptions {
jvmTarget = "11"
jvmTarget = "17"
}
namespace = "com.android.tvflix"
}

dependencies {
Expand All @@ -121,13 +110,22 @@ dependencies {
implementation(Deps.AndroidX.ktx_core)
implementation(Deps.AndroidX.ktx_fragment)
implementation(Deps.AndroidX.ktx_activity)
implementation(Deps.AndroidX.compose_activity)
implementation(Deps.AndroidX.constraint_layout)
kapt(Deps.AndroidX.Lifecycle.compiler)
implementation(platform(Deps.AndroidX.Compose.bom))
implementation(Deps.AndroidX.Compose.ui)
implementation(Deps.AndroidX.Compose.foundation)
implementation(Deps.AndroidX.Compose.material)
implementation(Deps.AndroidX.Compose.material_icons)
implementation(Deps.AndroidX.Compose.tooling_preview)
implementation(Deps.AndroidX.Compose.navigation)
implementation(Deps.AndroidX.Compose.hilt_navigation)
implementation(Deps.AndroidX.Lifecycle.viewmodel)
implementation(Deps.AndroidX.Paging.runtime)
implementation(Deps.AndroidX.Paging.compose)
testImplementation(Deps.AndroidX.Paging.common)
implementation(Deps.AndroidX.Room.runtime)
kapt(Deps.AndroidX.Room.compiler)
ksp(Deps.AndroidX.Room.compiler)
testImplementation(Deps.AndroidX.Room.testing)
implementation(Deps.AndroidX.Room.ktx)
implementation(Deps.AndroidX.annotation)
Expand All @@ -138,7 +136,8 @@ dependencies {
implementation(Deps.OkHttp.logging_interceptor)
implementation(Deps.Glide.runtime)
implementation(Deps.Glide.okhttp_integration)
kapt(Deps.Glide.compiler)
implementation(Deps.Coil.compose)
ksp(Deps.Glide.ksp)
implementation(Deps.Retrofit.main)
implementation(Deps.Retrofit.moshi)

Expand All @@ -154,27 +153,25 @@ dependencies {
testImplementation(Deps.AndroidX.Test.core)
androidTestImplementation(Deps.AndroidX.Test.runner)
androidTestImplementation(Deps.AndroidX.Test.junit)
// Espresso
androidTestImplementation(Deps.AndroidX.Test.Espresso.core)
androidTestImplementation(Deps.AndroidX.Test.Espresso.contrib)
androidTestImplementation(Deps.AndroidX.Test.Espresso.idling_resource)
androidTestImplementation(Deps.AndroidX.Test.rules)
androidTestImplementation(Deps.AndroidX.Compose.test_junit4)
testImplementation(Deps.Test.truth)
testImplementation(Deps.Test.robolectric)
testImplementation(Deps.Coroutines.test)
// end-region Test

implementation(Deps.Moshi.kotlin)
kapt(Deps.Moshi.codegen)
ksp(Deps.Moshi.codegen)

implementation(Deps.Coroutines.core)
implementation(Deps.Coroutines.android)

debugImplementation(Deps.Chucker.debug)
debugImplementation(Deps.AndroidX.Compose.tooling)
debugImplementation(Deps.AndroidX.Compose.test_manifest)
releaseImplementation(Deps.Chucker.release)

implementation(Deps.Hilt.android)
kapt(Deps.Hilt.android_compiler)
ksp(Deps.Hilt.android_compiler)

// start-region Firebase
implementation(platform(Deps.Firebase.firebase_bom))
Expand All @@ -184,5 +181,3 @@ dependencies {
implementation(Deps.Firebase.remote_config)
// end-region Firebase
}


47 changes: 0 additions & 47 deletions app/src/androidTest/java/com/android/tvflix/home/HomeRobot.kt

This file was deleted.

48 changes: 0 additions & 48 deletions app/src/androidTest/java/com/android/tvflix/home/HomeTest.kt

This file was deleted.

This file was deleted.

Loading
Loading