Skip to content

Commit

Permalink
Update 3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihai-Cristian Condrea committed Jun 7, 2024
1 parent 56669d6 commit 1b1b1ab
Show file tree
Hide file tree
Showing 19 changed files with 301 additions and 131 deletions.
26 changes: 26 additions & 0 deletions .idea/appInsightsSettings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions .idea/kotlinScripting.xml

This file was deleted.

2 changes: 1 addition & 1 deletion .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/migrations.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 37 additions & 13 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
Expand All @@ -12,26 +13,47 @@ android {
applicationId = "com.d4rk.musicsleeptimer.plus"
minSdk = 26
targetSdk = 34
versionCode = 26
versionName = "1.0.0"
versionCode = 27
versionName = "3.0.0"
archivesName = "${applicationId}-v${versionName}"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
resourceConfigurations += listOf("en", "de", "es", "fr", "hi", "hu", "in", "it", "ja", "ro", "ru", "tr", "sv", "bg", "pl", "uk")
resourceConfigurations += listOf(
"en" ,
"de" ,
"es" ,
"fr" ,
"hi" ,
"hu" ,
"in" ,
"it" ,
"ja" ,
"ro" ,
"ru" ,
"tr" ,
"sv" ,
"bg" ,
"pl" ,
"uk"
)
}
buildTypes {
release {
multiDexEnabled = true
isMinifyEnabled = true
isShrinkResources = true
isDebuggable = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt") , "proguard-rules.pro"
)
}
debug {
multiDexEnabled = true
isMinifyEnabled = true
isShrinkResources = true
isDebuggable = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt") , "proguard-rules.pro"
)
}
}
compileOptions {
Expand All @@ -52,12 +74,14 @@ android {
}
}
dependencies {
implementation("com.google.firebase:firebase-crashlytics-ktx:18.5.1")
implementation("com.google.firebase:firebase-analytics-ktx:21.5.0")
implementation("com.google.firebase:firebase-perf:20.5.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.multidex:multidex:2.0.1")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.crashlytics.ktx)
implementation(libs.firebase.analytics.ktx)
implementation(libs.firebase.perf)
implementation(libs.appcompat)
implementation(libs.work.runtime.ktx)
implementation(libs.multidex)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
}
43 changes: 23 additions & 20 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,51 +1,54 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<application
android:appCategory="audio"
android:description="@string/app_description"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher"
android:logo="@drawable/ic_launcher_foreground"
android:label="@string/app_name"
android:description="@string/app_description"
android:theme="@android:style/Theme.DeviceDefault"
android:appCategory="audio"
android:localeConfig="@xml/config_locales"
android:logo="@drawable/ic_launcher_foreground"
android:roundIcon="@mipmap/ic_launcher"
android:theme="@android:style/Theme.DeviceDefault"
tools:targetApi="33">
<service
android:name=".services.SleepTileService"
android:exported="true"
android:icon="@drawable/ic_music_off"
android:label="@string/app_name"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
android:exported="true">
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE"/>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>

<meta-data
android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="true"/>
android:value="true" />
<meta-data
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
android:value="true"/>
android:value="true" />
</service>
<service android:name=".services.SleepAudioService"/>
<service android:name=".services.SleepAudioService" />
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true"/>
android:value="true" />
</service>

<meta-data
android:name="firebase_performance_logcat_enabled"
android:value="true"/>
android:value="true" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
android:value="@integer/google_play_services_version" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.d4rk.musicsleeptimer.plus.notifications

import android.app.Notification
import android.app.Notification.CATEGORY_EVENT
import android.app.Notification.VISIBILITY_PUBLIC
Expand All @@ -22,57 +23,93 @@ import java.text.DateFormat.SHORT
import java.util.Date
import java.util.concurrent.TimeUnit.MILLISECONDS
import java.util.concurrent.TimeUnit.MINUTES

object SleepNotification {
private val TIMEOUT_INITIAL_MILLIS = MINUTES.toMillis(30)
private val TIMEOUT_INCREMENT_MILLIS = MINUTES.toMillis(10)
private val TIMEOUT_DECREMENT_MILLIS = MINUTES.toMillis(10)
private enum class Action(private val value: String) {

private enum class Action(private val value : String) {
CANCEL("com.d4rk.musicsleeptimer.plus.action.CANCEL") {
override fun title(context: Context) = context.getText(android.R.string.cancel)
},
override fun title(context : Context) = context.getText(android.R.string.cancel)
} ,
INCREMENT("com.d4rk.musicsleeptimer.plus.action.INCREMENT") {
override fun title(context: Context) = context.getString(R.string.notification_action_increment, MILLISECONDS.toMinutes(TIMEOUT_INCREMENT_MILLIS))
},
override fun title(context : Context) = context.getString(
R.string.notification_action_increment ,
MILLISECONDS.toMinutes(TIMEOUT_INCREMENT_MILLIS)
)
} ,
DECREMENT("com.d4rk.musicsleeptimer.plus.action.DECREMENT") {
override fun title(context: Context) = context.getString(R.string.notification_action_decrement, MILLISECONDS.toMinutes(TIMEOUT_DECREMENT_MILLIS))
},;
override fun title(context : Context) = context.getString(
R.string.notification_action_decrement ,
MILLISECONDS.toMinutes(TIMEOUT_DECREMENT_MILLIS)
)
} , ;

companion object {
fun parse(value: String?): Action? = values().firstOrNull { it.value == value }
fun parse(value : String?) : Action? = entries.firstOrNull { it.value == value }
}
fun intent(context: Context): Intent = Intent(context, SleepTileService::class.java).setAction(value)
fun pendingIntent(context: Context, cancel: Boolean = false): PendingIntent? = PendingIntent.getService(context, 0, intent(context), FLAG_IMMUTABLE).apply { if (cancel) cancel() }
fun action(context: Context, cancel: Boolean = false): Notification.Action.Builder = Notification.Action.Builder(Icon.createWithResource(context, 0), title(context), pendingIntent(context, cancel))
abstract fun title(context: Context): CharSequence?

fun intent(context : Context) : Intent =
Intent(context , SleepTileService::class.java).setAction(value)

fun pendingIntent(context : Context , cancel : Boolean = false) : PendingIntent? =
PendingIntent.getService(context , 0 , intent(context) , FLAG_IMMUTABLE)
.apply { if (cancel) cancel() }

fun action(context : Context , cancel : Boolean = false) : Notification.Action.Builder =
Notification.Action.Builder(
Icon.createWithResource(context , 0) ,
title(context) ,
pendingIntent(context , cancel)
)

abstract fun title(context : Context) : CharSequence?
}
fun Context.notificationManager(): NotificationManager? = getSystemService(NotificationManager::class.java)
fun Context.find() = notificationManager()?.activeNotifications?.firstOrNull { it.id == R.id.notification_id }?.notification
fun Context.handle(intent: Intent?) = when (Action.parse(intent?.action)) {

fun Context.notificationManager() : NotificationManager? =
getSystemService(NotificationManager::class.java)

fun Context.find() =
notificationManager()?.activeNotifications?.firstOrNull { it.id == R.id.notification_id }?.notification

fun Context.handle(intent : Intent?) = when (Action.parse(intent?.action)) {
INCREMENT -> update(TIMEOUT_INCREMENT_MILLIS)
DECREMENT -> update(-TIMEOUT_DECREMENT_MILLIS)
DECREMENT -> update(- TIMEOUT_DECREMENT_MILLIS)
CANCEL -> cancel()
null -> Unit
}

fun Context.toggle() = if (find() == null) show() else cancel()
private fun Context.cancel() = notificationManager()?.cancel(R.id.notification_id) ?: Unit
private fun Context.update(timeout: Long) = find()?.let {
private fun Context.update(timeout : Long) = find()?.let {
it.`when` - currentTimeMillis()
}?.let {
if (it > - timeout) it + timeout else it
}?.let {
show(it)
}
?.let {
if (it > -timeout) it + timeout else it
}
?.let { show(it)
}
private fun Context.show(timeout: Long = TIMEOUT_INITIAL_MILLIS) {

private fun Context.show(timeout : Long = TIMEOUT_INITIAL_MILLIS) {
require(timeout > 0)
val eta = currentTimeMillis() + timeout
val notification = Notification.Builder(this, getString(R.string.notification_channel_id)).setCategory(CATEGORY_EVENT).setVisibility(VISIBILITY_PUBLIC).setOnlyAlertOnce(true).setOngoing(true).setSmallIcon(R.drawable.ic_music_off).setSubText(DateFormat.getTimeInstance(SHORT).format(Date(eta))).setShowWhen(true).setWhen(eta).setUsesChronometer(true).setChronometerCountDown(true).setTimeoutAfter(timeout).setDeleteIntent(SleepAudioService.pendingIntent(this)).addAction(INCREMENT.action(this).build()).addAction(DECREMENT.action(this, cancel = timeout <= TIMEOUT_DECREMENT_MILLIS).build()).addAction(CANCEL.action(this).build()).build()
val notification = Notification.Builder(this , getString(R.string.notification_channel_id))
.setCategory(CATEGORY_EVENT).setVisibility(VISIBILITY_PUBLIC).setOnlyAlertOnce(true)
.setOngoing(true).setSmallIcon(R.drawable.ic_music_off)
.setSubText(DateFormat.getTimeInstance(SHORT).format(Date(eta))).setShowWhen(true)
.setWhen(eta).setUsesChronometer(true).setChronometerCountDown(true)
.setTimeoutAfter(timeout).setDeleteIntent(SleepAudioService.pendingIntent(this))
.addAction(INCREMENT.action(this).build()).addAction(
DECREMENT.action(this , cancel = timeout <= TIMEOUT_DECREMENT_MILLIS).build()
).addAction(CANCEL.action(this).build()).build()
createNotificationChannel()
notificationManager()?.notify(R.id.notification_id, notification)
notificationManager()?.notify(R.id.notification_id , notification)
}

private fun Context.createNotificationChannel() {
val id = getString(R.string.notification_channel_id)
val name: CharSequence = getString(R.string.app_name)
val channel = NotificationChannel(id, name, IMPORTANCE_LOW).apply {
val name : CharSequence = getString(R.string.app_name)
val channel = NotificationChannel(id , name , IMPORTANCE_LOW).apply {
setBypassDnd(true)
lockscreenVisibility = VISIBILITY_PUBLIC
}
Expand Down
Loading

0 comments on commit 1b1b1ab

Please sign in to comment.