Skip to content

Test Android app that uses GitHub REST API and shows a company repos list

License

Notifications You must be signed in to change notification settings

IsaacRF/github-ndapp-repolist

Repository files navigation

Github NdApp

Author: IsaacRF239

Minimum SDK: API 16

Target SDK: API 29

Android test app built in modern Architecture that consumes GitHub API to show sample data. This is part of a coding challenge developed for Xing, you can find the assessment details here

github-ndapp-demo

Main Features

MVVM Architecture

This project uses MVVM (Model - View - Viewmodel) architecture, via new Jetpack ViewModel feature.

image

Development Patterns

This project implements "By feature + layout" structure, Separation of Concerns pattern and SOLID principles.

By feature + layout structure

Project architecture combines the "By feature" structure, consisting on separating all files concerning to a specific feature (for example, an app screen / section) on its own package, plus the "By layout" classic structure, separating all files serving a similar purpose on its own sub-package.

By feature structure complies with the Separation of Concerns and encapsulation patterns, also making the app highly scalable, modular and way easier to manipulate, as deleting or adding features impact only app base layer and refactor is minimum to non-existent.

ByFeatureFolderStructure

Testing project replicates the same feature structure to ease test running separation

TestFolderStructure

LiveData / Observable Pattern

Data is handled via LiveData / Observable Pattern instead of RxJava, as it's better performant and includes a series of benefits as, for example, avoiding manual app lifecycle management.

RepoListViewModel

val repoList: LiveData<NetworkResource<List<Repo>>> = repoListRepository.getRepos(organizationName)

RepoListActivity

//Observe live data changes and update UI accordingly
repoListViewModel.repoList.observe(this) {
    when(it.status) {
        Status.LOADING -> {}
        Status.SUCCESS -> {}
        Status.ERROR -> {}
    }
}

Dependency Injection

Project implements Dependency Injection (SOLID) to isolate modules, avoid inter-dependencies and make testing easier

Dependency Injection is handled via Hilt, a library that uses Dagger under the hood easing its implementation via @ annotations, and is developed and recommended to use by Google.

GithubNdApp (App main class)

@HiltAndroidApp
class GithubNdApp : Application() {}

RepoListActivity

@AndroidEntryPoint
class RepoListActivity : AppCompatActivity(), RepoListItemViewAdapter.OnRepoListener {
    private val repoListViewModel: RepoListViewModel by viewModels()
}

RepoListViewModel

class RepoListViewModel @ViewModelInject constructor (
    private val repoListRepository: RepoListRepository,
    @Assisted private val state: SavedStateHandle
) : ViewModel() {}

API Calls

API Calls are handled via retrofit, declaring calls via an interface, and automatically deserialized by Gson into model objects.

RepoListService

@Headers("Authorization: token ???????????????")
@GET("/orgs/{organizationName}/repos")
fun getRepos(
    @Path("organizationName") organizationName: String,
    @Query("page") page: Int
): Call<List<Repo>>

Forcing TLS1.2 on Android 4.1 (API 16) - 5.0 (API 21)

Android mininum SDK has been stablished in API 16 to avoid security conflicts against GitHub API.

GitHub API deprecated the SSLv3 and TLSv1.0 connection protocols for security reasons in favor of TLSv1.3 and TLSv1.2, as can be seen here: https://www.ssllabs.com/ssltest/analyze.html?d=api.github.com

GitHubAPITLS

GitHubAPICiphers

As stated in Google Developer guidelines (https://developer.android.com/reference/javax/net/ssl/SSLSocket.html), TLSv1.2 protocol is only available in Android 4.1+ (not enabled by default, requiring some tweaks), and in Android 5.0+ (enabled by default). So any Android version below 4.1 uses TLSv1.0 or TLSv1.1, and fails to establish a secure SSL connection with the API, being unable to retrieve any data.

AndroidTLSSupport

The required tweaks to run the api calls on API 14 -> 21 are done via a custom TLS Socked Factory that forces the enabling of TLSv1.2 when available, and also forces the ciphers required by the API.

Image rendering and caching

Repo owner avatar image is rendered and cached using EpicBitmapRenderer, a Java library I also developed.

EpicBitmapRenderer Icon

Testing

All business logic and services are tested using Mockito and okhttp Mockwebserver.

Every test is isolated, and all API calls are mocked to avoid test results to depend on external sources, becoming unrealiable and possibly leading to unexpected results.

About

Test Android app that uses GitHub REST API and shows a company repos list

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages