A small app for downloading adrianmato.art wallpapers

Related tags

App Artdrian
Overview

Artdrian

A small app for downloading adrianmato.art wallpapers

Technical details of the app

  • Target SDK: 33
./gradlew test #Execute Unit testing
./gradlew executeScreenshotTest #Execute screenshot testing. Note that the baseline is a Pixel XL API 33 or they may mismatch

Architecture

The app is built follow the principles of Clean Architecture, and it is also a small test bed for the newest trends of Android development.

There are several differentiated layers on the code, separated by packaging. A nice to have would have done to separate those into modules; but being a small app, it beats the purpose. I'll enumerate the packages and some information of what contains.

Datasources

It holds both local and api classes for retrieving and storing data.

WallpaperApi is implemented through Retrofit and connects to the server serving the wallpapers. I used GSon for deserialization. I know there are more modern alternatives like Moshi or Kotlin Serialization, but this is the one I am more familliar with, and while it has certain risks with Kotlin, I am experienced enough to handle them and the app is very limited and controlled, so I will not run any problems with it.

WallpaperMemoryDataSource is an easy, memory cache for storing the information retrieved from the API, however, it is abstracted behind WallpaperDataSource, as I may choose to use another kind of persistence in the future (Room or File).

All of the Datasources class API are protected suspend functions so I can indicate the compiler when there is an effect that may take some time and therefore, should be protected behind a Coroutine.

The WallpaperRepository class decorates the same api as WallpaperDataSource, however adding different CachePolicies that could help me tweaking the behavior of the app if I wanted to in case of low connectivity situations, or use it as a failsafe. I have done more generic repositories in the past (namely my old Kor repos). However, by default, I simply use the classic priorize the local information and fallback to the network.

For the manipulation of the data, I used (Arrow)[https://arrow-kt.io/]. Normally I favor some FP when doing that, as the code, while a little strange to unfamilliar devs, it provides quite concise code and easy data structures to work with errors.

For testing this layer, I used some ad-hoc fakes and white box testing together with snapshot testing. I used the kotlin-snapshot library for that.

Use cases

For the use cases I used a normal approach, all of them encapsulate the business logic, again, using suspend functions to convey that there are side effects going on and Arrow to return information.

The tests for this layer have been done through white, large scoped tests which include using MockWebServer to simulate the API calls, snapshot testing and ad-hoc fakes to provide a more realistic test conditions.

UI - ViewModels

While I have used extensively MVP in the past I have wanted to give a chance to use Android ViewModels.

AFAIK, the main advantage of the Android ViewModels is that they hide away the complexity of saving the state on configuration changes, and while I haven't done an extensive test of them, I have tried to rotate the device, and they seemed to fulfill my expectations.

A ViewModel instance holds the appropiate UseCases and exposes the calls using Kotlin Flows. As I do not have the need to go further and use a StateFlow or SharedFlow, they behaved quite nice. I am not so experienced using them, so probably there are some nuances that I may be missing or I may have implemented myself instead of relying of the more native to Android flows.

Those flows emit ViewStates that the Activity and the Composables subscribe to and modifies the UI state when received. Those flows are executed via lifecycleScopes on the IO dispatcher.

The ViewModels are tested almost E2E using a combination of Robolectric to supply the Android parts, custom DI to inject certain test doubles and MockWebServer.

UI - Compose

I have used Compose to write the whole UI. Nothing much to say on that regard, I set some state hoisting to handle certain situations and used a hand from (Accompanist)[https://google.github.io/accompanist/permissions/] for permission handling in Compose.

Each Activity has an Screen under their *View file (eg. WallpaperListViews). This is a Composable that takes a ViewState and renders appropiately depending on the state.

The UI has been tested using dummy Compose Testing with ComposeRules and Screenshot testing using (Shot)(https://github.com/pedrovgs/Shot)

UI - Activities

I did not complicate myself and made a classic and easy two-activities list/detail. I could have used Fragments or choose some Compose Navigation/NavGraph solutions, but due to the small scope of the app and the investment on the latter ones, which I have not used in the past, I decided to go for something classical and easy, with Intents.

I did certain testing of the flows using ComposeAndroidRule and Espresso. Those tests are the most complex the application have and required extensive refactoring to allow me to create an alternative Dependency Injection on Test time.

In order to do that, I needed to create my own alternative Application instance that loads a Test Graph with doubles, and

The API was mocked, although the retrieval of the images are not at the moment of this commit. However, this allows me to run easy and relatively fast UI tests, and can navigate through the app and perform actions in a manipulable way.

For asserting certain situations like "Saving the wallpaper" or "Setting it up", I required to create some IdlingResources for the test, one for listening to file changes, and another, a little more crude to check for signas from a BroadcastReceiver.

Work to do

I have run out of time to work on the Info button in the Detail Screen and will not work at the time of this tag. I will keep working on it.

Also I would like to give a better support of other form factors using Compose.

The part of the Themeing at the moment, works, but it may require reworking to have better dynamic Material 3 theme and Day/Night.

Being a fan of Offline First discipline, I would love to have it work as offline as possible.

Also I would like to create a service, maybe with Workmanager to be able to rotate through the dowloaded wallpapers automatically.

Comments
  • [FEATURE]: Improve presentation

    [FEATURE]: Improve presentation

    :pushpin: References

    • Issue: #25

    :tophat: What is the goal?

    Provide a proper app naming and logo to the app

    How is it being implemented?

    I extracted the vector

    Captures, GIF or Videos (UI Tasks)

    image

    How can it be tested?

    • [ ] Use case 1: The app displays a correct icon and naming
    opened by Sefford 0
  • [Feature]: Improve presentation of the app

    [Feature]: Improve presentation of the app

    What feature would you want to add?

    As a developer, I want to improve on the presentation of the app, letting it have an icon, improve naming and add the presentation

    This feature will be completed when...

    The app is able to have a better presentation on the launcher.

    Code of Conduct

    • [X] I agree to follow this project's Code of Conduct
    opened by Sefford 0
  • #23 Abstracts Dispatcher through DI

    #23 Abstracts Dispatcher through DI

    :pushpin: References

    • Issue:

    :tophat: What is the goal?

    Improve the code by injecting the dispatchers instead of having them pushed from the Activity.

    How is it being implemented?

    Basically we abstract the execution details inside of the ViewModel, and provide the dispatcher to work through DI.

    We need to also provide a dispatcher double (the current thread) on tests, so we can do our tests on a single thread.

    How can it be tested?

    • [ ] Use case 1: App should keep working
    opened by Sefford 0
  • [Feature]: Inject Dispatchers

    [Feature]: Inject Dispatchers

    What feature would you want to add?

    As a developer, I want to inject the dispatchers into the ViewModel, so I can save applying them all the time on the ViewModels

    This feature will be completed when...

    The app is able to have the Dispatchers injected via DI using Dispatchers.IO.

    The tests have the Dispatcher.Main injected instead.

    Code of Conduct

    • [X] I agree to follow this project's Code of Conduct
    opened by Sefford 0
  • [Feature] Added Mutex protection on FileManager and Repository

    [Feature] Added Mutex protection on FileManager and Repository

    :pushpin: References

    • Issue: #21

    :tophat: What is the goal?

    Improve concurrency on key components in the architecture

    How is it being implemented?

    Using the Mutex component of the Coroutines Library.

    How can it be tested?

    • [ ] Use case 1: Application keeps working as expected
    opened by Sefford 0
  • [Feature]: Improve concurrency

    [Feature]: Improve concurrency

    What feature would you want to add?

    As a developer I want to improve concurrency.

    Probably there are certain resources that do require to be protected from excessive concurrency.

    The key will be to use Mutex in the DataSource and file downloader to properly restrict concurrent acess

    This feature will be completed when...

    The app is able to better support concurrent operations

    Code of Conduct

    • [X] I agree to follow this project's Code of Conduct
    opened by Sefford 0
  • #19 Fixes Ghost Waves 003

    #19 Fixes Ghost Waves 003

    :pushpin: References

    • Issue: #19

    :tophat: What is the goal?

    Fix the reason why Ghost Waves 003 was not showing

    How is it being implemented?

    Seems like unlike the other URLs, Ghost Waves 003 uses a JPG instead of a PNG, so I needed to introduce a special case into it, and now it shows.

    Used some Property-based testing with JQwik to assert the special case.

    Captures, GIF or Videos (UI Tasks)

    How can it be tested?

    • [ ] Use case 1: Ghost Waves 003 should be showing now
    opened by Sefford 0
  • [Feature] Removed Robolectric from the ViewModel tests

    [Feature] Removed Robolectric from the ViewModel tests

    :pushpin: References

    • Issue: #17

    :tophat: What is the goal?

    Perform faster tests by removing Robolectric dependencies from ViewModel tests

    How is it being implemented?

    Ditto.

    How can it be tested?

    • [ ] Use case 1: ViewModel tests keep passing
    opened by Sefford 0
  • [Feature]: Remove Robolectric from ViewModel tests

    [Feature]: Remove Robolectric from ViewModel tests

    What feature would you want to add?

    As a developer, I want fast tests, so I noticed even being an Android-native component, Android ViewModels do not require Android runtime to work.

    I can turn the ViewModel tests to JUnit5 ones and keep Robolectric dependencies just in case.

    This feature will be completed when...

    The app is able to run the ViewModel tests without robolectric

    Code of Conduct

    • [X] I agree to follow this project's Code of Conduct
    opened by Sefford 0
  • #15 Adds Wallpaper info and tests

    #15 Adds Wallpaper info and tests

    :pushpin: References

    • Issue: #15

    :tophat: What is the goal?

    Show some Wallpaper info in the detail screen

    How is it being implemented?

    I exercised a little the Animation APIs of Compose to produce a meaningful animation of showing and hiding the overlay.

    • I used AnimatedContent to animate the disappearing buttons and the Icon and Text of the Info button.
    • AnimatedVisibility to show/hide the text on the overlay
    • animateFloatAsState to produce an animation over the overlay gradient to extend it to the top and the bottom

    I also made a screenshot test for the Info overlay in the WallpaperDetailViewTest class.

    Captures, GIF or Videos (UI Tasks)

    https://user-images.githubusercontent.com/878293/201228413-40791f9f-1e91-4f7e-8dfc-b3f80e790c11.mp4

    How can it be tested?

    • [ ] Use case 1: When in the detail screen of a wallpaper, click the Info button

    • [ ] Use case 2: When the wallpaper info is set, click Close to close it back

    opened by Sefford 0
  • [Feature]: Add info state on Wallpaper Detail

    [Feature]: Add info state on Wallpaper Detail

    What feature would you want to add?

    As a user I want to see the info in the wallpaper detail

    This feature will be completed when...

    The app is able to show the information about the wallpaper detail

    Code of Conduct

    • [X] I agree to follow this project's Code of Conduct
    opened by Sefford 0
  • [Feature]: Improve networking performance

    [Feature]: Improve networking performance

    What feature would you want to add?

    As a developer I want to improve the networking performance.

    As such, it is time to put on mechanisms to allow the app to save network bandwith.

    • Will enable a local database persistence to save metadata and a cache policy to keep it as long as possible
    • Use previews instead of the target downloads to increase speed on the preview of the wallpapers
    • Try to cache the previews themselves and maybe the wallpapers to the storage so the app do not download wallpapers again and again

    This feature will be completed when...

    The app is able to do the aforementioned things

    Code of Conduct

    • [X] I agree to follow this project's Code of Conduct
    opened by Sefford 0
Owner
Saúl Díaz
Saúl Díaz
Small library that allows the application to display a small troubleshooting guide in case of repeated app startup crashes.

AppSalvager What is it? AppSalvager allows you to combat the issue of repeating crashes on app startup. Failed data migration, SDKs not handling their

Alexander Leontev 29 Aug 31, 2022
Android app for downloading novels

QuickNovel Adfree FOSS Android app for downloading novels. Discord: https://discord.gg/5Hus6fM Download: https://github.com/LagradOst/QuickNovel/relea

Osten 509 Jan 9, 2023
Android app for streaming and downloading Movies, TV-Series and Anime.

CloudStream-3 DOWNLOAD: https://github.com/LagradOst/CloudStream-3/releases Discord: https://discord.gg/5Hus6fM Features: AdFree, No ads whatsoever No

Osten 1.9k Aug 1, 2022
Android app for streaming and downloading Movies, TV-Series and Anime.

AquaStream ⚠️ Warning: By default this app doesn't provide any video sources, you have to install extensions in order to add functionality to the app.

null 17 Oct 3, 2022
Demo of Downloading Songs/Images through Android Download Manager using RxJava2

Downloader Demo using RxJava Overview This project is for downloading items(songs, images etc) in Android using RxJava2. There are, however 2 conditio

Anshul Jain 168 Nov 25, 2022
Application for downloading and installing skins for minecraft.

Minecraft skins Application for downloading and installing skins for minecraft. Also user can choose favourites skins. Table of Contents Screenshots G

Vladyslav 0 Oct 30, 2021
A template for Advent of Code challenge with input downloading and prepared test classes

Advent of Code Kotlin Template A template which will help you concentrate on the puzzle solutions. It brings Downloading and caching of the puzzle inp

Henning B 2 Dec 1, 2021
Downloading and saving cats for android

Task 5: Downloading and saving cats! Use this API: https://docs.thecatapi.com/ to implement the app with the following features: Ability to download a

null 0 Oct 5, 2021
Small app to demonstrate app modularization combined with clean architecture

Football Hightlights Sample Sample project, exploring the app Modularization in combination with some concepts of the clean architecture, in particula

null 1 Oct 31, 2021
A small Crypto app with neat UI.

CryptoAppUI A small Crypto app with neat UI. Note: To login in or sign up just enter any dummy values. Perform crypto transaction though this app usin

Zain Khalid 3 Jul 17, 2022
A small API to add Quran with Tajweed Color in Android App

QuranApi A simple Api to implement Quran in Android. Add To Project Step 1. Add the JitPack repository to your build file Add it in your root build.gr

DevilCat 11 Aug 5, 2022
Money Manager app that helps you to add your daily small incomes and expenses and track them easily.

Simple Money Manager This app is a simple money manager app which helps you to add your daily small incomes and expenses and track them easily. Screen

Yash Bansal 2 Nov 21, 2021
An small android app based on banking logic, usilng SQLITE as database, material design, navigation drawer implemented

Android Banking App Project - Using Sqlite The Banking app using java in android studio and sqlite for crud. Packages Used Material Design Contributin

Md-Mahin-Rahman 4 Dec 6, 2022
Collection of Small Android Projects

AndroidDemoProjects ActivityRecognition: Example of using Google Play Services to recognize a user's activity, such as running, walking, or riding a b

Paul Ruiz 601 Dec 9, 2022
Small training project where dagger, dagger hilt and other components are used for clean architecture

LeagueNow ?? LeagueNow is a sample soccer team list Android application ?? built to demonstrate use of modern Android development tools - (Kotlin, Arc

Kevin Serrano 1 Oct 21, 2021
Backend service for mobile/web application for a small cinema playing only movies

FFC - Fast & Furious Cinema Backend service for mobile/web application for a small cinema playing only movies from Fast & Furious franchise. Some assu

Łukasz Lipka 0 Dec 12, 2021
☀️ Wheater is a small demo application based on modern Android tech-stacks and MVVM architecture. ⛅

Wheater is a small demo application based on modern Android tech-stacks and MVVM architecture. Tech stack & Open-source libraries Minimum SDK level 19

null 2 Jan 17, 2022
DiscordBot - Small Discord bot using JDA

Discord bot written in kotlin and using JDA Use it yourself ./gradlew build crea

chell 2 Feb 2, 2022
SIMNumberSetter - A small Xposed module to set the SIM card's phone subscriber number

SIM Number Setter SIM Number Setter is a small Xposed module that invokes normal

Kieron Quinn 99 Dec 30, 2022