Skip to content

Commit

Permalink
🎨 chore: Add README.md, update gradle properties, build config, and d…
Browse files Browse the repository at this point in the history
…ependencies

- Increase JVM memory to 4GB
- Add configuration cache for faster builds
- Update AndroidX dependencies to the latest versions
- Update Kotlin version to 2.0.0
- Update Gradle version to 8.7.0
- Add multiDexEnabled flag in build config
- Update lifecycle version to 2.8.3
- Update Work manager version to 2.9.0
- Update JUnit and Espresso versions

See README.md for more details.

Signed-off-by: Dmytro Turskyi <dmytro.turskyi@gmail.com>
  • Loading branch information
Turskyi committed Jul 21, 2024
1 parent b4a5e95 commit f4397cb
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 28 deletions.
Empty file.
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct-single.svg)](https://stand-with-ukraine.pp.ua)
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/Turskyi/Hydration-Reminder-Service">

# Hydration Reminder Service

## Project Description

The Hydration Reminder Service is an Android mobile application designed to remind users to drink
water. The app features a single screen with a picture of a glass and a counter in the middle.
Above the glass, there is a text prompt: "Press the glass of water after you have hydrated." At
the bottom, the text "Hydrate while charging reminder sent 0 times" is displayed.

## Features

- **Main Screen**: Displays a picture of a glass with a counter. Users are prompted to press the
- glass after hydrating.
- **Water Count**: Keeps track of the number of times the user has hydrated.
- **Charging Reminder**: Sends reminders to hydrate while the device is charging.

## Installation Instructions

1. Download the project.
2. Open the project in Android Studio.
3. Run the project from Android Studio.

## Usage

Once installed, developers can observe a solid example of using a worker, intent service, and
shared preference listener. The app can be installed on an Android device and used as a hydration
reminder app. Note that the app is not unique and similar functionality can be found in many other
apps on Google Play. The primary usefulness of the project lies in its educational value,
demonstrating how to use the mentioned technologies.

## Technologies Used

- **Kotlin**: Programming language.
- **BroadcastReceiver**: For receiving system-wide broadcast announcements.
- **JobIntentService**: For handling background tasks.
- **kotlinx.coroutines**: For coroutine support.
- **androidx.preference:preference-ktx**: For preference support.
- **androidx.work:work-runtime-ktx**: For WorkManager support.
- Architectural pattern: [Monolith](https://en.wikipedia.org/wiki/Monolithic_application).
- **Code Readability:** code is easily readable with no unnecessary blank lines, no unused variables
or methods, and no commented-out code, all variables, methods, and resource IDs are descriptively
named such that another developer reading the code can easily understand their function.

## Contributing

Anyone can contribute by creating a pull request with changes. Contributions are welcome, although
the app currently does not have unique features that differentiate it from other hydration
reminder apps.

## Credits

This project may have been inspired by a tutorial from Google, but the specific tutorial is no
longer available.

## License

This project does not have an intentional license.

### Screenshot:

<!--suppress CheckImageSize -->
<img src="screenshots/Screenshot_20240720.png" width="400" alt="screenshot">
29 changes: 15 additions & 14 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ plugins {
}

android {
compileSdkVersion 31
compileSdkVersion 34

defaultConfig {
applicationId "io.github.turskyi.hydrationreminder"
minSdkVersion 21
targetSdkVersion 31
targetSdkVersion 34
versionCode 1
versionName "1.0.0"

multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

Expand All @@ -24,32 +24,33 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '11'
}
namespace 'io.github.turskyi.hydrationreminder'
}

dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'

// for lifecycleScope and coroutine scope
def LIFECYCLE_VERSION = "2.4.1"
def LIFECYCLE_VERSION = "2.8.3"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION"

// data store
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation 'androidx.preference:preference-ktx:1.2.1'

// Work manager (Kotlin + coroutines)
def work_version = "2.7.1"
def work_version = "2.9.0"
implementation "androidx.work:work-runtime-ktx:$work_version"

// tests
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
}
5 changes: 3 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.turskyi.hydrationreminder">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

Expand All @@ -15,6 +15,7 @@
android:theme="@style/Theme.HydrationReminderService">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:screenOrientation="portrait">
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package io.github.turskyi.hydrationreminder

import android.content.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
Expand Down Expand Up @@ -138,7 +142,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
* This is a listener that will update the UI when the water count or charging reminder counts
* change
*/
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) {
if (PreferenceUtilities.KEY_WATER_COUNT == key) {
updateWaterCount()
} else if (PreferenceUtilities.KEY_CHARGING_REMINDER_COUNT == key) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ class StartJobIntentServiceReceiver : BroadcastReceiver() {
* @param intent an Intent meant for a [androidx.core.app.JobIntentService]
* @return a new Intent intended for use by this receiver based off the passed intent
*/
fun getIntent(context: Context, intent: Intent, job_id: Int): Intent {
fun getIntent(context: Context, intent: Intent, jobId: Int): Intent {
val component: ComponentName =
intent.component ?: throw RuntimeException("Missing intent component")
val newIntent: Intent = Intent(intent)
.putExtra(EXTRA_SERVICE_CLASS, component.className)
.putExtra(EXTRA_JOB_ID, job_id)
.putExtra(EXTRA_JOB_ID, jobId)
newIntent.setClass(context, StartJobIntentServiceReceiver::class.java)
return newIntent
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ object NotificationUtils {
val ignoreReminderPendingIntent = PendingIntent.getBroadcast(
context,
ACTION_IGNORE_PENDING_INTENT_ID,
StartJobIntentServiceReceiver.getIntent(context, ignoreReminderIntent,
StartJobIntentServiceReceiver.getIntent(
context, ignoreReminderIntent,
WaterReminderIntentService.JOB_ID
),
PendingIntent.FLAG_UPDATE_CURRENT
Expand All @@ -107,7 +108,7 @@ object NotificationUtils {
context, incrementWaterCountIntent,
WaterReminderIntentService.JOB_ID
),
PendingIntent.FLAG_CANCEL_CURRENT
PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
return NotificationCompat.Action(
R.drawable.ic_local_drink_black_24px,
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.6.21"
ext.kotlin_version = "2.0.0"
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath 'com.android.tools.build:gradle:8.5.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

// NOTE: Do not place your application dependencies here; they belong
Expand All @@ -25,6 +25,6 @@ allprojects {
}
}

task clean(type: Delete) {
tasks.register('clean', Delete) {
delete rootProject.buildDir
}
11 changes: 9 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=512m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
Expand All @@ -18,4 +18,11 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
kotlin.code.style=official
#configuration-cache
org.gradle.unsafe.configuration-cache=true
org.gradle.unsafe.configuration-cache-problems=warn
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
android.suppressUnsupportedCompileSdk=34
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
Binary file added screenshots/Screenshot_20240720.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f4397cb

Please sign in to comment.