diff --git a/README.md b/README.md
index 251a1bc..67d871f 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# VolumeLockr
VolumeLockr allows you to control your Android device volume levels and set locks for each one of them.
-
  
+
  
## Installation
You can either download it from F-Droid or build it manually.
diff --git a/app/build.gradle b/app/build.gradle
index dd45cab..a29f530 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,20 +1,21 @@
plugins {
id 'com.android.application'
- id 'org.jetbrains.kotlin.kapt'
+ id 'org.jetbrains.kotlin.kapt' apply false
id 'kotlin-android'
id 'com.mikepenz.aboutlibraries.plugin'
}
android {
- compileSdkVersion 31
+ compileSdk 34
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.klee.volumelockr"
- minSdkVersion 16
- targetSdkVersion 31
- versionCode 9
- versionName "1.5.0"
+ minSdkVersion 19
+ targetSdkVersion 34
+ versionCode 11
+ versionName "1.6.1"
+ multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -36,6 +37,7 @@ android {
buildFeatures {
viewBinding true
}
+ namespace 'com.klee.volumelockr'
}
dependencies {
@@ -43,7 +45,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
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 'com.google.android.material:material:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1bfbc50..c8d3816 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,10 +1,11 @@
-
+
+
+
+ android:theme="@style/Theme.VolumeLockr">
-
+
= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- mMode = Settings.Global.getInt(contentResolver, MODE_RINGER_SETTING)
- }
+ mMode = Settings.Global.getInt(contentResolver, MODE_RINGER_SETTING)
registerObservers()
@@ -95,9 +98,7 @@ class VolumeService : Service() {
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
- mAllowLower = sharedPreferences.getBoolean(ALLOW_LOWER, false)
-
+ loadGeneralPreferences()
return START_STICKY
}
@@ -162,12 +163,13 @@ class VolumeService : Service() {
private fun savePreferences() {
val sharedPreferences = getSharedPreferences(APP_SHARED_PREFERENCES, MODE_PRIVATE)
- val editor = sharedPreferences.edit()
- editor.putString(LOCKS_KEY, Gson().toJson(mVolumeLock))
- editor.apply()
+ sharedPreferences.edit {
+ putString(LOCKS_KEY, Gson().toJson(mVolumeLock))
+ }
}
private fun loadPreferences() {
+ loadGeneralPreferences()
val sharedPreferences = getSharedPreferences(APP_SHARED_PREFERENCES, MODE_PRIVATE)
class Token : TypeToken>()
val value = sharedPreferences.getString(LOCKS_KEY, "")
@@ -177,6 +179,11 @@ class VolumeService : Service() {
}
}
+ private fun loadGeneralPreferences() {
+ val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
+ mAllowLower = sharedPreferences.getBoolean(ALLOW_LOWER, false)
+ }
+
@WorkerThread
@Synchronized
private fun checkVolumes() {
@@ -207,9 +214,7 @@ class VolumeService : Service() {
override fun onChange(selfChange: Boolean) {
super.onChange(selfChange)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- mMode = Settings.Global.getInt(contentResolver, MODE_RINGER_SETTING)
- }
+ mMode = Settings.Global.getInt(contentResolver, MODE_RINGER_SETTING)
mModeListener?.invoke()
}
@@ -233,11 +238,9 @@ class VolumeService : Service() {
registerObserver(VOLUME_VOICE_HEADSET_SETTING)
registerObserver(VOLUME_VOICE_BT_SETTING)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- contentResolver.registerContentObserver(
- Settings.Global.getUriFor(MODE_RINGER_SETTING), true, mModeObserver
- )
- }
+ contentResolver.registerContentObserver(
+ Settings.Global.getUriFor(MODE_RINGER_SETTING), true, mModeObserver
+ )
}
private fun registerObserver(setting: String) {
@@ -248,7 +251,7 @@ class VolumeService : Service() {
@Synchronized
fun tryShowNotification() {
- if (mVolumeLock.size == 0) {
+ if (mVolumeLock.isEmpty()) {
return
}
@@ -267,7 +270,7 @@ class VolumeService : Service() {
@RequiresApi(Build.VERSION_CODES.N)
@Synchronized
fun tryHideNotification() {
- if (mVolumeLock.size > 0) {
+ if (mVolumeLock.isNotEmpty()) {
return
}
diff --git a/app/src/main/java/com/klee/volumelockr/ui/MainActivity.kt b/app/src/main/java/com/klee/volumelockr/ui/MainActivity.kt
index 50c779b..3f6bacb 100644
--- a/app/src/main/java/com/klee/volumelockr/ui/MainActivity.kt
+++ b/app/src/main/java/com/klee/volumelockr/ui/MainActivity.kt
@@ -3,36 +3,44 @@ package com.klee.volumelockr.ui
import android.app.AlertDialog
import android.app.Dialog
import android.app.NotificationManager
-import android.content.Context
import android.content.Intent
+import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
import androidx.fragment.app.DialogFragment
import com.klee.volumelockr.R
-import com.klee.volumelockr.service.VolumeService
class MainActivity : AppCompatActivity() {
+ companion object {
+ private const val NOTIFICATION_PERMISSION = "android.permission.POST_NOTIFICATIONS"
+ private const val PERMISSION_REQUEST_CODE = 25
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
- }
-
- override fun onResume() {
- super.onResume()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkDoNotDisturbPermission()
}
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (ContextCompat.checkSelfPermission(applicationContext, NOTIFICATION_PERMISSION)
+ == PackageManager.PERMISSION_DENIED) {
+ requestPermissions(arrayOf(NOTIFICATION_PERMISSION), PERMISSION_REQUEST_CODE)
+ }
+ }
}
@RequiresApi(Build.VERSION_CODES.M)
private fun checkDoNotDisturbPermission() {
val notificationManager =
- getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (!notificationManager.isNotificationPolicyAccessGranted) {
PolicyAccessDialog().show(supportFragmentManager, PolicyAccessDialog.TAG)
diff --git a/app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt b/app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt
index 731d562..3d7ef03 100644
--- a/app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt
+++ b/app/src/main/java/com/klee/volumelockr/ui/VolumeAdapter.kt
@@ -5,10 +5,10 @@ import android.media.AudioManager
import android.os.Build
import android.view.LayoutInflater
import android.view.ViewGroup
-import android.widget.SeekBar
import androidx.annotation.MainThread
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.slider.Slider
import com.klee.volumelockr.databinding.VolumeCardBinding
import com.klee.volumelockr.service.VolumeService
import com.klee.volumelockr.ui.SettingsFragment
@@ -44,11 +44,9 @@ class VolumeAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val volume = mVolumeList[position]
holder.binding.mediaTextView.text = volume.name
- holder.binding.seekBar.progress = mService?.getLocks()?.get(volume.stream) ?: volume.value
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- holder.binding.seekBar.min = volume.min
- }
- holder.binding.seekBar.max = volume.max
+ holder.binding.slider.value = mService?.getLocks()?.get(volume.stream)?.toFloat() ?: volume.value.toFloat()
+ holder.binding.slider.valueFrom = volume.min.toFloat()
+ holder.binding.slider.valueTo = volume.max.toFloat()
registerSeekBarCallback(holder, volume)
registerSwitchButtonCallback(holder, volume)
@@ -58,28 +56,21 @@ class VolumeAdapter(
handleRingerMode(holder, volume)
if (isPasswordProtected()) {
- holder.binding.seekBar.isEnabled = false
+ holder.binding.slider.isEnabled = false
holder.binding.switchButton.isEnabled = false
}
}
private fun registerSeekBarCallback(holder: ViewHolder, volume: Volume) {
- val listener = object : SeekBar.OnSeekBarChangeListener {
- override fun onProgressChanged(view: SeekBar?, progress: Int, fromUser: Boolean) {
+ val listener =
+ Slider.OnChangeListener { _, value, _ ->
if (volume.stream != AudioManager.STREAM_NOTIFICATION || mService?.getMode() == 2) {
- mAudioManager.setStreamVolume(volume.stream, progress, 0)
+ mAudioManager.setStreamVolume(volume.stream, value.toInt(), 0)
}
- volume.value = progress
- }
-
- override fun onStartTrackingTouch(view: SeekBar?) {
+ volume.value = value.toInt()
}
-
- override fun onStopTrackingTouch(view: SeekBar?) {
- }
- }
- holder.binding.seekBar.setOnSeekBarChangeListener(listener)
+ holder.binding.slider.addOnChangeListener(listener)
}
private fun registerSwitchButtonCallback(holder: ViewHolder, volume: Volume) {
@@ -98,7 +89,7 @@ class VolumeAdapter(
for (key in it) {
if (volume.stream == key) {
holder.binding.switchButton.isChecked = true
- holder.binding.seekBar.isEnabled = false
+ holder.binding.slider.isEnabled = false
}
}
}
@@ -128,7 +119,7 @@ class VolumeAdapter(
private fun handleRingerMode(holder: ViewHolder, volume: Volume) {
if (volume.stream == AudioManager.STREAM_NOTIFICATION) {
- holder.binding.seekBar.isEnabled =
+ holder.binding.slider.isEnabled =
mService?.getMode() == 2 &&
mService?.getLocks()?.containsKey(AudioManager.STREAM_NOTIFICATION) == false
}
@@ -139,7 +130,7 @@ class VolumeAdapter(
it.addLock(volume.stream, volume.value)
adjustService()
adjustNotification()
- holder.binding.seekBar.isEnabled = false
+ holder.binding.slider.isEnabled = false
}
}
@@ -148,7 +139,7 @@ class VolumeAdapter(
it.removeLock(volume.stream)
adjustService()
adjustNotification()
- holder.binding.seekBar.isEnabled = true
+ holder.binding.slider.isEnabled = true
}
}
diff --git a/app/src/main/java/com/klee/volumelockr/ui/VolumeLockrApplication.kt b/app/src/main/java/com/klee/volumelockr/ui/VolumeLockrApplication.kt
new file mode 100644
index 0000000..44d16ab
--- /dev/null
+++ b/app/src/main/java/com/klee/volumelockr/ui/VolumeLockrApplication.kt
@@ -0,0 +1,11 @@
+package com.klee.volumelockr.ui
+
+import android.app.Application
+import com.google.android.material.color.DynamicColors
+
+class VolumeLockrApplication: Application() {
+ override fun onCreate() {
+ super.onCreate()
+ DynamicColors.applyToActivitiesIfAvailable(this)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/preference_switch.xml b/app/src/main/res/layout/preference_switch.xml
new file mode 100644
index 0000000..99df707
--- /dev/null
+++ b/app/src/main/res/layout/preference_switch.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/volume_card.xml b/app/src/main/res/layout/volume_card.xml
index 5494e1d..04738fc 100644
--- a/app/src/main/res/layout/volume_card.xml
+++ b/app/src/main/res/layout/volume_card.xml
@@ -1,12 +1,11 @@
-
-
-
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
deleted file mode 100644
index b46415f..0000000
--- a/app/src/main/res/values-night/themes.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index a0077b9..efd56ba 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -1,16 +1,14 @@
-
-
\ No newline at end of file
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
index c456e8f..43d418d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = "1.5.20"
+ ext.kotlin_version = '1.8.0'
repositories {
google()
mavenCentral()
@@ -9,7 +9,7 @@ buildscript {
}
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.0.4'
+ classpath 'com.android.tools.build:gradle:8.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:8.9.0"
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
index 1d1d271..2b33c2d 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
index b053184..0149537 100644
Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png differ
diff --git a/gradle.properties b/gradle.properties
index 2521752..dced600 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -16,4 +16,7 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
-kotlin.code.style=official
\ No newline at end of file
+kotlin.code.style=official
+android.defaults.buildfeatures.buildconfig=true
+android.nonTransitiveRClass=false
+android.nonFinalResIds=false
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index a2e01c0..8307a0f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionSha256Sum=f581709a9c35e9cb92e16f585d2c4bc99b2b1a5f85d2badbd3dc6bff59e1e6dd
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/screenshot.png b/screenshot.png
deleted file mode 100644
index d3ad445..0000000
Binary files a/screenshot.png and /dev/null differ
diff --git a/screenshot_night.png b/screenshot_night.png
deleted file mode 100644
index 2c8a254..0000000
Binary files a/screenshot_night.png and /dev/null differ