From dd628ed6f12f093009526ca2bc4d0eb27780c9a4 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Tue, 14 Mar 2023 12:47:50 +0530 Subject: [PATCH 01/22] Update targetSdk to 33 --- app/build.gradle | 2 +- appthemehelper/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8641e6fa1..dae931b97 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,7 +10,7 @@ android { defaultConfig { minSdk 21 - targetSdk 32 + targetSdk 33 vectorDrawables.useSupportLibrary = true diff --git a/appthemehelper/build.gradle b/appthemehelper/build.gradle index 31bfc76af..2a5e0f50d 100644 --- a/appthemehelper/build.gradle +++ b/appthemehelper/build.gradle @@ -1,12 +1,12 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdk 32 + compileSdk 33 namespace "code.name.monkey.appthemehelper" defaultConfig { minSdk 21 - targetSdk 32 + targetSdk 33 } buildTypes { release { From 23da382b220ca55eebb75670195bd88fe4099687 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Tue, 14 Mar 2023 12:47:22 +0530 Subject: [PATCH 02/22] refactor: Migrate to Photo picker to select images --- .../tageditor/AbsTagEditorActivity.kt | 48 +++-------------- .../artists/AbsArtistDetailsFragment.kt | 52 +++++++------------ 2 files changed, 25 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt index c8ca11247..df973203e 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt @@ -29,6 +29,7 @@ import android.view.animation.OvershootInterpolator import android.widget.ImageView import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.IntentSenderRequest +import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.lifecycle.lifecycleScope @@ -37,7 +38,6 @@ import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R.drawable import code.name.monkey.retromusic.activities.base.AbsBaseActivity -import code.name.monkey.retromusic.activities.saf.SAFGuideActivity import code.name.monkey.retromusic.extensions.accentColor import code.name.monkey.retromusic.extensions.colorButtons import code.name.monkey.retromusic.extensions.hideSoftKeyboard @@ -45,7 +45,6 @@ import code.name.monkey.retromusic.extensions.setTaskDescriptionColorAuto import code.name.monkey.retromusic.model.ArtworkInfo import code.name.monkey.retromusic.model.AudioTagInfo import code.name.monkey.retromusic.repository.Repository -import code.name.monkey.retromusic.util.SAFUtil import code.name.monkey.retromusic.util.logD import com.google.android.material.button.MaterialButton import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -56,7 +55,6 @@ import org.jaudiotagger.audio.AudioFileIO import org.jaudiotagger.tag.FieldKey import org.koin.android.ext.android.inject import java.io.File -import java.util.Collections abstract class AbsTagEditorActivity : AbsBaseActivity() { abstract val editorImage: ImageView @@ -212,6 +210,11 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { } } + private val pickArtworkImage = + registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> + loadImageFromFile(uri) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) _binding = bindingInflater.invoke(layoutInflater) @@ -252,14 +255,7 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { } private fun startImagePicker() { - val intent = Intent(Intent.ACTION_GET_CONTENT) - intent.type = "image/*" - startActivityForResult( - Intent.createChooser( - intent, - getString(R.string.pick_from_local_storage) - ), REQUEST_CODE_SELECT_IMAGE - ) + pickArtworkImage.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) } protected abstract fun loadCurrentImage() @@ -400,36 +396,6 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { } } - - override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { - super.onActivityResult(requestCode, resultCode, intent) - when (requestCode) { - REQUEST_CODE_SELECT_IMAGE -> if (resultCode == Activity.RESULT_OK) { - intent?.data?.let { - loadImageFromFile(it) - } - } - - SAFGuideActivity.REQUEST_CODE_SAF_GUIDE -> { - SAFUtil.openTreePicker(this) - } - - SAFUtil.REQUEST_SAF_PICK_TREE -> { - if (resultCode == Activity.RESULT_OK) { - SAFUtil.saveTreeUri(this, intent) - writeTags(savedSongPaths) - } - } - - SAFUtil.REQUEST_SAF_PICK_FILE -> { - if (resultCode == Activity.RESULT_OK) { - writeTags(Collections.singletonList(currentSongPath + SAFUtil.SEPARATOR + intent!!.dataString)) - } - } - } - } - - private fun getAudioFile(path: String): AudioFile { return try { AudioFileIO.read(File(path)) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt index 3dfae6cd5..8f2acec1b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/artists/AbsArtistDetailsFragment.kt @@ -1,6 +1,5 @@ package code.name.monkey.retromusic.fragments.artists -import android.app.Activity import android.content.Intent import android.graphics.Color import android.os.Bundle @@ -9,6 +8,7 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import android.view.View +import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.widget.PopupMenu import androidx.core.os.bundleOf @@ -153,14 +153,10 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs)) ) val songText = resources.getQuantityString( - R.plurals.albumSongs, - artist.songCount, - artist.songCount + R.plurals.albumSongs, artist.songCount, artist.songCount ) val albumText = resources.getQuantityString( - R.plurals.albums, - artist.songCount, - artist.songCount + R.plurals.albums, artist.songCount, artist.songCount ) binding.fragmentArtistContent.songTitle.text = songText binding.fragmentArtistContent.albumTitle.text = albumText @@ -174,8 +170,7 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm ) { biography = null this.lang = lang - detailsViewModel.getArtistInfo(name, lang, null) - .observe(viewLifecycleOwner) { result -> + detailsViewModel.getArtistInfo(name, lang, null).observe(viewLifecycleOwner) { result -> when (result) { is Result.Loading -> logD("Loading") is Result.Error -> logE("Error") @@ -214,11 +209,8 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm } private fun loadArtistImage(artist: Artist) { - Glide.with(requireContext()) - .asBitmapPalette() - .artistImageOptions(artist) - .load(RetroGlideExtension.getArtistModel(artist)) - .dontAnimate() + Glide.with(requireContext()).asBitmapPalette().artistImageOptions(artist) + .load(RetroGlideExtension.getArtistModel(artist)).dontAnimate() .into(object : SingleColorTarget(binding.image) { override fun onColorReady(color: Int) { setColors(color) @@ -274,13 +266,8 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm } R.id.action_set_artist_image -> { - val intent = Intent(Intent.ACTION_GET_CONTENT) - intent.type = "image/*" selectImageLauncher.launch( - Intent.createChooser( - intent, - getString(R.string.pick_from_local_storage) - ) + PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly) ) return true } @@ -336,14 +323,14 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm SortOrder.ArtistSongSortOrder.SONG_Z_A -> sortOrder.findItem(R.id.action_sort_order_title_desc).isChecked = true - SortOrder.ArtistSongSortOrder.SONG_ALBUM -> - sortOrder.findItem(R.id.action_sort_order_album).isChecked = true + SortOrder.ArtistSongSortOrder.SONG_ALBUM -> sortOrder.findItem(R.id.action_sort_order_album).isChecked = + true - SortOrder.ArtistSongSortOrder.SONG_YEAR -> - sortOrder.findItem(R.id.action_sort_order_year).isChecked = true + SortOrder.ArtistSongSortOrder.SONG_YEAR -> sortOrder.findItem(R.id.action_sort_order_year).isChecked = + true - SortOrder.ArtistSongSortOrder.SONG_DURATION -> - sortOrder.findItem(R.id.action_sort_order_song_duration).isChecked = true + SortOrder.ArtistSongSortOrder.SONG_DURATION -> sortOrder.findItem(R.id.action_sort_order_song_duration).isChecked = + true else -> { throw IllegalArgumentException("invalid $savedSongSortOrder") @@ -352,14 +339,11 @@ abstract class AbsArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragm } private val selectImageLauncher = - registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == Activity.RESULT_OK) { - result.data?.data?.let { - lifecycleScope.launch { - CustomArtistImageUtil.getInstance(requireContext()) - .setCustomArtistImage(artist, it) - } - + registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> + lifecycleScope.launch { + if (uri != null) { + CustomArtistImageUtil.getInstance(requireContext()) + .setCustomArtistImage(artist, uri) } } } From 931e59319a00e8cdb3ff8c786775e329198e5892 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Tue, 14 Mar 2023 13:17:57 +0530 Subject: [PATCH 03/22] fix: Fix Home tab title --- .../code/name/monkey/retromusic/fragments/home/HomeFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/home/HomeFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/home/HomeFragment.kt index 2946b4f16..48b60aa81 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/home/HomeFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/home/HomeFragment.kt @@ -175,7 +175,7 @@ class HomeFragment : findNavController().navigate(R.id.action_search, null, navOptions) } val hexColor = String.format("#%06X", 0xFFFFFF and accentColor()) - val appName = "Retro Music".parseAsHtml() + val appName = "Retro Music".parseAsHtml() binding.appBarLayout.title = appName } From ccf3b7f6a52144b74df231c23caf1b547ec3a2cf Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Tue, 14 Mar 2023 13:06:19 +0530 Subject: [PATCH 04/22] fix: Remove Blurred album art on lockscreen feature for Android 11 and above Hide Blur album art preference on Android 11+ devices as the lockscreen album art feature was removed by Google. And even if the feature is present in some Custom ROMs there is also an option to set blur so this preference is unnecessary on Android 11 and above. --- .../fragments/settings/PersonalizeSettingsFragment.kt | 8 ++++++++ .../code/name/monkey/retromusic/util/PreferenceUtil.kt | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt index 24218f6fb..f02727d20 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/PersonalizeSettingsFragment.kt @@ -17,7 +17,10 @@ package code.name.monkey.retromusic.fragments.settings import android.os.Bundle import android.view.View import code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference +import code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference +import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.retromusic.APPBAR_MODE +import code.name.monkey.retromusic.BLURRED_ALBUM_ART import code.name.monkey.retromusic.HOME_ALBUM_GRID_STYLE import code.name.monkey.retromusic.HOME_ARTIST_GRID_STYLE import code.name.monkey.retromusic.R @@ -27,12 +30,17 @@ class PersonalizeSettingsFragment : AbsSettingsFragment() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.pref_ui) + // Hide Blur album art preference on Android 11+ devices as the lockscreen album art feature was removed by Google + // And if the feature is present in some Custom ROM's there is also an option to set blur so this preference is unnecessary on Android 11 and above + val blurredAlbumArt: ATESwitchPreference? = findPreference(BLURRED_ALBUM_ART) + blurredAlbumArt?.isVisible = !VersionUtils.hasR() } override fun invalidateSettings() {} override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + val homeArtistStyle: ATEListPreference? = findPreference(HOME_ARTIST_GRID_STYLE) homeArtistStyle?.setOnPreferenceChangeListener { preference, newValue -> setSummary(preference, newValue) diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt index 493949be7..68c2be9ab 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt +++ b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt @@ -279,7 +279,7 @@ object PreferenceUtil { val isBlurredAlbumArt get() = sharedPreferences.getBoolean( BLURRED_ALBUM_ART, false - ) + ) && !VersionUtils.hasR() val blurAmount get() = sharedPreferences.getInt(NEW_BLUR_AMOUNT, 25) From 6ec2e6ee9a6aa9d849d292b3d4d549d2f1bcd5a0 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Tue, 14 Mar 2023 13:36:07 +0530 Subject: [PATCH 05/22] Code Cleanup --- .../java/code/name/monkey/retromusic/Constants.kt | 1 - .../retromusic/fragments/settings/AudioSettings.kt | 13 +++++++++---- .../fragments/settings/ThemeSettingsFragment.kt | 3 +++ .../name/monkey/retromusic/util/PreferenceUtil.kt | 5 ----- app/src/main/res/values-v26/bools.xml | 4 ---- app/src/main/res/values-v27/bools.xml | 4 ---- app/src/main/res/values-v31/bools.xml | 2 -- app/src/main/res/values/bools.xml | 4 ---- app/src/main/res/xml/pref_audio.xml | 9 --------- app/src/main/res/xml/pref_general.xml | 5 ++--- 10 files changed, 14 insertions(+), 36 deletions(-) delete mode 100644 app/src/main/res/values-v26/bools.xml delete mode 100644 app/src/main/res/values-v27/bools.xml diff --git a/app/src/main/java/code/name/monkey/retromusic/Constants.kt b/app/src/main/java/code/name/monkey/retromusic/Constants.kt index d17b3194e..c51689cab 100644 --- a/app/src/main/java/code/name/monkey/retromusic/Constants.kt +++ b/app/src/main/java/code/name/monkey/retromusic/Constants.kt @@ -119,7 +119,6 @@ const val ARTIST_GRID_SIZE_LAND = "artist_grid_size_land" const val PLAYLIST_GRID_SIZE = "playlist_grid_size" const val PLAYLIST_GRID_SIZE_LAND = "playlist_grid_size_land" const val COLORED_APP_SHORTCUTS = "colored_app_shortcuts" -const val AUDIO_DUCKING = "audio_ducking" const val LAST_ADDED_CUTOFF = "last_added_interval" const val LAST_SLEEP_TIMER_VALUE = "last_sleep_timer_value" const val NEXT_SLEEP_TIMER_ELAPSED_REALTIME = "next_sleep_timer_elapsed_real_time" diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AudioSettings.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AudioSettings.kt index 17915712a..d493085c0 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AudioSettings.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/AudioSettings.kt @@ -49,11 +49,16 @@ class AudioSettings : AbsSettingsFragment() { if (VersionUtils.hasS()) { bluetoothPreference?.setOnPreferenceChangeListener { _, newValue -> if (newValue as Boolean) { - if (ActivityCompat.checkSelfPermission(requireContext(), - BLUETOOTH_CONNECT) != PERMISSION_GRANTED + if (ActivityCompat.checkSelfPermission( + requireContext(), + BLUETOOTH_CONNECT + ) != PERMISSION_GRANTED ) { - ActivityCompat.requestPermissions(requireActivity(), arrayOf( - BLUETOOTH_CONNECT), BLUETOOTH_PERMISSION_REQUEST) + ActivityCompat.requestPermissions( + requireActivity(), arrayOf( + BLUETOOTH_CONNECT + ), BLUETOOTH_PERMISSION_REQUEST + ) } } return@setOnPreferenceChangeListener true diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt index f7fbc122b..a89fedf96 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/settings/ThemeSettingsFragment.kt @@ -16,6 +16,7 @@ package code.name.monkey.retromusic.fragments.settings import android.annotation.SuppressLint import android.os.Bundle +import android.view.View import androidx.core.content.edit import androidx.preference.Preference import androidx.preference.TwoStatePreference @@ -139,5 +140,7 @@ class ThemeSettingsFragment : AbsSettingsFragment() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { addPreferencesFromResource(R.xml.pref_general) + val wallpaperAccent: ATESwitchPreference? = findPreference(WALLPAPER_ACCENT) + wallpaperAccent?.isVisible = VersionUtils.hasOreoMR1() && !VersionUtils.hasS() } } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt index 68c2be9ab..18991786a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt +++ b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.kt @@ -266,11 +266,6 @@ object PreferenceUtil { ALBUM_ART_ON_LOCK_SCREEN, true ) - val isAudioDucking - get() = sharedPreferences.getBoolean( - AUDIO_DUCKING, true - ) - val isBluetoothSpeaker get() = sharedPreferences.getBoolean( BLUETOOTH_PLAYBACK, false diff --git a/app/src/main/res/values-v26/bools.xml b/app/src/main/res/values-v26/bools.xml deleted file mode 100644 index e557d81d8..000000000 --- a/app/src/main/res/values-v26/bools.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - false - \ No newline at end of file diff --git a/app/src/main/res/values-v27/bools.xml b/app/src/main/res/values-v27/bools.xml deleted file mode 100644 index a3eb593f3..000000000 --- a/app/src/main/res/values-v27/bools.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - true - \ No newline at end of file diff --git a/app/src/main/res/values-v31/bools.xml b/app/src/main/res/values-v31/bools.xml index 51349c34e..e9ef74c3c 100644 --- a/app/src/main/res/values-v31/bools.xml +++ b/app/src/main/res/values-v31/bools.xml @@ -2,6 +2,4 @@ true true - - false \ No newline at end of file diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml index 654eeffa5..5e9f24c9f 100644 --- a/app/src/main/res/values/bools.xml +++ b/app/src/main/res/values/bools.xml @@ -5,9 +5,5 @@ true - false - false - - true false \ No newline at end of file diff --git a/app/src/main/res/xml/pref_audio.xml b/app/src/main/res/xml/pref_audio.xml index 749202ced..6bf54069c 100755 --- a/app/src/main/res/xml/pref_audio.xml +++ b/app/src/main/res/xml/pref_audio.xml @@ -2,15 +2,6 @@ - - + android:title="@string/pref_title_wallpaper_accent" /> Date: Tue, 14 Mar 2023 18:48:22 +0530 Subject: [PATCH 06/22] fix: Fix activity recreate logic when downloading split language apk --- .../java/code/name/monkey/retromusic/extensions/extensions.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/normal/java/code/name/monkey/retromusic/extensions/extensions.kt b/app/src/normal/java/code/name/monkey/retromusic/extensions/extensions.kt index 59d05fb74..2bedd4a72 100644 --- a/app/src/normal/java/code/name/monkey/retromusic/extensions/extensions.kt +++ b/app/src/normal/java/code/name/monkey/retromusic/extensions/extensions.kt @@ -12,6 +12,7 @@ import com.google.android.play.core.splitinstall.SplitInstallManagerFactory import com.google.android.play.core.splitinstall.SplitInstallRequest import com.google.android.play.core.splitinstall.SplitInstallSessionState import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener +import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus import java.util.* fun Context.setUpMediaRouteButton(menu: Menu) { @@ -24,7 +25,8 @@ fun FragmentActivity.installLanguageAndRecreate(code: String) { val manager = SplitInstallManagerFactory.create(this) val listener = object: SplitInstallStateUpdatedListener{ override fun onStateUpdate(state: SplitInstallSessionState) { - if (state.sessionId() == mySessionId) { + // Restart the activity if the language is installed (sessionId is same and status is installed) + if (state.sessionId() == mySessionId && state.status() == SplitInstallSessionStatus.INSTALLED) { recreate() manager.unregisterListener(this) } From 3e93dcfc4d560b86193c1f70eb2a06e35e4c7ff8 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Tue, 14 Mar 2023 18:50:18 +0530 Subject: [PATCH 07/22] feat: Add a function to check for Android 13 --- .../code/name/monkey/appthemehelper/util/VersionUtils.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/appthemehelper/src/main/java/code/name/monkey/appthemehelper/util/VersionUtils.kt b/appthemehelper/src/main/java/code/name/monkey/appthemehelper/util/VersionUtils.kt index ac8db0c5d..269c2c698 100644 --- a/appthemehelper/src/main/java/code/name/monkey/appthemehelper/util/VersionUtils.kt +++ b/appthemehelper/src/main/java/code/name/monkey/appthemehelper/util/VersionUtils.kt @@ -82,4 +82,13 @@ object VersionUtils { fun hasS(): Boolean { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S } + + /** + * @return true if device is running API >= 33 + */ + @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU) + @JvmStatic + fun hasT(): Boolean { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + } } From ab16d7e105e0816ec34f96c1cd9e94ec3cbe43f4 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Wed, 15 Mar 2023 12:09:53 +0530 Subject: [PATCH 08/22] fix: Fix playlist reordering crash --- .../song/OrderablePlaylistSongAdapter.kt | 29 +++++++------------ .../playlists/PlaylistDetailsFragment.kt | 12 +++----- .../fragments/queue/PlayingQueueFragment.kt | 19 ++++++------ 3 files changed, 25 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt index 88a0b7a8d..bf85fe28b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt @@ -26,6 +26,7 @@ import code.name.monkey.retromusic.db.toSongsEntity import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.model.Song +import code.name.monkey.retromusic.util.ViewUtil import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange import kotlinx.coroutines.Dispatchers @@ -50,11 +51,7 @@ class OrderablePlaylistSongAdapter( override fun getItemId(position: Int): Long { // requires static value, it means need to keep the same value // even if the item position has been changed. - return if (position != 0) { - dataSet[position - 1].id - } else { - -1 - } + return dataSet[position].id } override fun createViewHolder(view: View): SongAdapter.ViewHolder { @@ -99,26 +96,22 @@ class OrderablePlaylistSongAdapter( } override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean { - if (dataSet.size == 0 or 1 || isInQuickSelectMode) { + if (isInQuickSelectMode) { return false } - val dragHandle = holder.dragView ?: return false - - val handleWidth = dragHandle.width - val handleHeight = dragHandle.height - val handleLeft = dragHandle.left - val handleTop = dragHandle.top - - return (x >= handleLeft && x < handleLeft + handleWidth && - y >= handleTop && y < handleTop + handleHeight) && position != 0 + return ViewUtil.hitTest(holder.imageText!!, x, y) || ViewUtil.hitTest( + holder.dragView!!, + x, + y + ) } override fun onMoveItem(fromPosition: Int, toPosition: Int) { - dataSet.add(toPosition - 1, dataSet.removeAt(fromPosition - 1)) + dataSet.add(toPosition, dataSet.removeAt(fromPosition)) } - override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange { - return ItemDraggableRange(0, itemCount - 1) + override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange? { + return null } override fun onCheckCanDrop(draggingPosition: Int, dropPosition: Int): Boolean { diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt index a4e2152d3..bb99dbdc9 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt @@ -12,6 +12,7 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.SimpleItemAnimator import code.name.monkey.retromusic.R import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailNewBinding @@ -34,7 +35,6 @@ import com.google.android.material.transition.MaterialArcMotion import com.google.android.material.transition.MaterialContainerTransform import com.google.android.material.transition.MaterialSharedAxis import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator -import com.h6ah4i.android.widget.advrecyclerview.animator.GeneralItemAnimator import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.parameter.parametersOf @@ -126,15 +126,11 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli val wrappedAdapter: RecyclerView.Adapter<*> = dragDropManager.createWrappedAdapter(playlistSongAdapter) - - val animator: GeneralItemAnimator = DraggableItemAnimator() - binding.recyclerView.itemAnimator = animator - - dragDropManager.attachRecyclerView(binding.recyclerView) - binding.recyclerView.apply { + adapter = wrappedAdapter layoutManager = LinearLayoutManager(requireContext()) - binding.recyclerView.adapter = wrappedAdapter + itemAnimator = DraggableItemAnimator() + dragDropManager.attachRecyclerView(this) ThemedFastScroller.create(this) } playlistSongAdapter.registerAdapterDataObserver(object : diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/queue/PlayingQueueFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/queue/PlayingQueueFragment.kt index 059b10bb0..84ecea2a3 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/queue/PlayingQueueFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/queue/PlayingQueueFragment.kt @@ -80,9 +80,6 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q recyclerViewDragDropManager = RecyclerViewDragDropManager() recyclerViewSwipeManager = RecyclerViewSwipeManager() - val animator = DraggableItemAnimator() - animator.supportsChangeAnimations = false - playingQueueAdapter = PlayingQueueAdapter( requireActivity(), MusicPlayerRemote.playingQueue.toMutableList(), @@ -94,12 +91,15 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q linearLayoutManager = LinearLayoutManager(requireContext()) - binding.recyclerView.layoutManager = linearLayoutManager - binding.recyclerView.adapter = wrappedAdapter - binding.recyclerView.itemAnimator = animator - recyclerViewTouchActionGuardManager?.attachRecyclerView(binding.recyclerView) - recyclerViewDragDropManager?.attachRecyclerView(binding.recyclerView) - recyclerViewSwipeManager?.attachRecyclerView(binding.recyclerView) + + binding.recyclerView.apply { + layoutManager = linearLayoutManager + adapter = wrappedAdapter + itemAnimator = DraggableItemAnimator() + recyclerViewTouchActionGuardManager?.attachRecyclerView(this) + recyclerViewDragDropManager?.attachRecyclerView(this) + recyclerViewSwipeManager?.attachRecyclerView(this) + } linearLayoutManager.scrollToPositionWithOffset(MusicPlayerRemote.position + 1, 0) binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { @@ -184,6 +184,7 @@ class PlayingQueueFragment : AbsMusicServiceFragment(R.layout.fragment_playing_q private fun setupToolbar() { binding.appBarLayout.toolbar.subtitle = getUpNextAndQueueTime() + binding.appBarLayout.toolbar.isTitleCentered = false binding.clearQueue.backgroundTintList = ColorStateList.valueOf(accentColor()) ColorStateList.valueOf( MaterialValueHelper.getPrimaryTextColor( From 8772bcb0b7dc8dc855891a730052fd4f7d0e8cb5 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Wed, 15 Mar 2023 12:10:51 +0530 Subject: [PATCH 09/22] fix: Use ShapeableImageView and added top margin to artist name in song item --- app/src/main/res/layout-sw600dp/item_queue.xml | 6 ++++-- app/src/main/res/layout/item_list.xml | 6 ++++-- app/src/main/res/layout/item_queue.xml | 16 ++++++++++------ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/app/src/main/res/layout-sw600dp/item_queue.xml b/app/src/main/res/layout-sw600dp/item_queue.xml index 7917c4ea8..11d8b1336 100644 --- a/app/src/main/res/layout-sw600dp/item_queue.xml +++ b/app/src/main/res/layout-sw600dp/item_queue.xml @@ -44,18 +44,19 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="16dp" - app:cardCornerRadius="6dp" + app:cardCornerRadius="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/drag_view" app:layout_constraintTop_toTopOf="parent"> - @@ -93,6 +94,7 @@ android:id="@+id/text" android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_marginTop="4dp" android:ellipsize="end" android:maxLines="1" android:paddingHorizontal="16dp" diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml index 55df9fda7..c23159d1a 100755 --- a/app/src/main/res/layout/item_list.xml +++ b/app/src/main/res/layout/item_list.xml @@ -35,18 +35,19 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="16dp" - app:cardCornerRadius="10dp" + app:cardCornerRadius="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/drag_view" app:layout_constraintTop_toTopOf="parent"> - @@ -87,6 +88,7 @@ android:ellipsize="end" android:maxLines="1" android:paddingHorizontal="16dp" + android:layout_marginTop="4dp" android:textAppearance="@style/TextViewBody2" android:textColor="?android:attr/textColorSecondary" app:layout_constraintBottom_toBottomOf="parent" diff --git a/app/src/main/res/layout/item_queue.xml b/app/src/main/res/layout/item_queue.xml index 855392064..83a497076 100644 --- a/app/src/main/res/layout/item_queue.xml +++ b/app/src/main/res/layout/item_queue.xml @@ -4,14 +4,15 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:clickable="true" - android:focusable="true" android:background="?rectSelector" - android:transitionGroup="true"> + android:clickable="true" + android:focusable="true"> + + @@ -43,18 +44,20 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - app:cardCornerRadius="6dp" + android:transitionGroup="true" + app:cardCornerRadius="4dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toEndOf="@id/drag_view" app:layout_constraintTop_toTopOf="parent"> - @@ -94,6 +97,7 @@ android:id="@+id/text" android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_marginTop="4dp" android:ellipsize="end" android:maxLines="1" android:paddingHorizontal="16dp" From 3d7e89e2705fc8137430ef401ddeb6214b5eccf8 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Wed, 15 Mar 2023 19:27:55 +0530 Subject: [PATCH 10/22] fix: Fix incorrect color of Top App Bar in Home tab in Landscape mode --- app/src/main/res/layout-land/fragment_home.xml | 5 ++--- app/src/main/res/layout/fragment_home.xml | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/layout-land/fragment_home.xml b/app/src/main/res/layout-land/fragment_home.xml index a9e0cca1e..c18e49710 100644 --- a/app/src/main/res/layout-land/fragment_home.xml +++ b/app/src/main/res/layout-land/fragment_home.xml @@ -13,17 +13,16 @@ --> + android:fitsSystemWindows="true" /> Date: Sat, 18 Mar 2023 14:28:53 +0530 Subject: [PATCH 11/22] fix: Fix corrupting of files when writing tags to unsupported files --- app/build.gradle | 2 +- .../tageditor/AbsTagEditorActivity.kt | 51 +++- .../activities/tageditor/TagWriter.kt | 263 +++++++++--------- app/src/main/res/values/strings.xml | 1 + 4 files changed, 171 insertions(+), 146 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index dae931b97..6bd881cf1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -154,7 +154,7 @@ dependencies { implementation "io.insert-koin:koin-core:$koin_version" implementation "io.insert-koin:koin-android:$koin_version" - def glide_version = '4.15.0' + def glide_version = '4.15.1' implementation "com.github.bumptech.glide:glide:$glide_version" ksp "com.github.bumptech.glide:ksp:$glide_version" implementation "com.github.bumptech.glide:okhttp3-integration:$glide_version" diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt index df973203e..dbdfb2b69 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AbsTagEditorActivity.kt @@ -46,6 +46,7 @@ import code.name.monkey.retromusic.model.ArtworkInfo import code.name.monkey.retromusic.model.AudioTagInfo import code.name.monkey.retromusic.repository.Repository import code.name.monkey.retromusic.util.logD +import code.name.monkey.retromusic.util.logE import com.google.android.material.button.MaterialButton import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.GlobalScope @@ -98,7 +99,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -107,7 +109,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TITLE) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -115,7 +118,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.COMPOSER) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -124,7 +128,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -133,7 +138,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ARTIST) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -142,7 +148,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.ALBUM_ARTIST) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -151,7 +158,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.GENRE) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -160,7 +168,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.YEAR) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -169,7 +178,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.TRACK) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -178,7 +188,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.DISC_NO) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -187,7 +198,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { get() { return try { getAudioFile(songPaths!![0]).tagOrCreateAndSetDefault.getFirst(FieldKey.LYRICS) - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) null } } @@ -205,7 +217,8 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { ) } return null - } catch (ignored: Exception) { + } catch (e: Exception) { + logE(e) return null } } @@ -356,9 +369,12 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { artworkInfo ) ) - val pendingIntent = MediaStore.createWriteRequest(contentResolver, getSongUris()) - launcher.launch(IntentSenderRequest.Builder(pendingIntent).build()) + if (cacheFiles.isNotEmpty()) { + val pendingIntent = + MediaStore.createWriteRequest(contentResolver, getSongUris()) + launcher.launch(IntentSenderRequest.Builder(pendingIntent).build()) + } } else { TagWriter.writeTagsToFiles( this@AbsTagEditorActivity, AudioTagInfo( @@ -396,9 +412,14 @@ abstract class AbsTagEditorActivity : AbsBaseActivity() { } } + private lateinit var audioFile: AudioFile + private fun getAudioFile(path: String): AudioFile { return try { - AudioFileIO.read(File(path)) + if (!this::audioFile.isInitialized) { + audioFile = AudioFileIO.read(File(path)) + } + audioFile } catch (e: Exception) { Log.e(TAG, "Could not read audio file $path", e) AudioFile() diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt index e4cf7fe89..b9d5f28dd 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/TagWriter.kt @@ -7,6 +7,7 @@ import android.media.MediaScannerConnection import android.os.Build import android.util.Log import androidx.annotation.RequiresApi +import code.name.monkey.retromusic.R import code.name.monkey.retromusic.extensions.showToast import code.name.monkey.retromusic.misc.UpdateToastMediaScannerCompletionListener import code.name.monkey.retromusic.model.AudioTagInfo @@ -20,6 +21,7 @@ import org.jaudiotagger.audio.exceptions.CannotReadException import org.jaudiotagger.audio.exceptions.CannotWriteException import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException import org.jaudiotagger.audio.exceptions.ReadOnlyFileException +import org.jaudiotagger.tag.FieldDataInvalidException import org.jaudiotagger.tag.TagException import org.jaudiotagger.tag.images.AndroidArtwork import org.jaudiotagger.tag.images.Artwork @@ -31,9 +33,9 @@ class TagWriter { companion object { suspend fun scan(context: Context, toBeScanned: List?) { - if (toBeScanned == null || toBeScanned.isEmpty()) { + if (toBeScanned.isNullOrEmpty()) { Log.i("scan", "scan: Empty") - context.showToast( "Scan file from folder") + context.showToast("Scan file from folder") return } MediaScannerConnection.scanFile( @@ -50,150 +52,151 @@ class TagWriter { suspend fun writeTagsToFiles(context: Context, info: AudioTagInfo) { withContext(Dispatchers.IO) { - runCatching { - var artwork: Artwork? = null - var albumArtFile: File? = null - if (info.artworkInfo?.artwork != null) { - try { - albumArtFile = createAlbumArtFile(context).canonicalFile - info.artworkInfo.artwork.compress( - Bitmap.CompressFormat.JPEG, - 100, - albumArtFile.outputStream() - ) - artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) - } catch (e: IOException) { - e.printStackTrace() - } + var artwork: Artwork? = null + var albumArtFile: File? = null + if (info.artworkInfo?.artwork != null) { + try { + albumArtFile = createAlbumArtFile(context).canonicalFile + info.artworkInfo.artwork.compress( + Bitmap.CompressFormat.JPEG, + 100, + albumArtFile.outputStream() + ) + artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) + } catch (e: IOException) { + e.printStackTrace() } - var wroteArtwork = false - var deletedArtwork = false - for (filePath in info.filePaths!!) { - try { - val audioFile = AudioFileIO.read(File(filePath)) - val tag = audioFile.tagOrCreateAndSetDefault - if (info.fieldKeyValueMap != null) { - for ((key, value) in info.fieldKeyValueMap) { - try { - tag.setField(key, value) - } catch (e: Exception) { - e.printStackTrace() - } - } - } - if (info.artworkInfo != null) { - if (info.artworkInfo.artwork == null) { - tag.deleteArtworkField() - deletedArtwork = true - } else if (artwork != null) { - tag.deleteArtworkField() - tag.setField(artwork) - wroteArtwork = true - } - } - audioFile.commit() - } catch (e: CannotReadException) { - e.printStackTrace() - } catch (e: IOException) { - e.printStackTrace() - } catch (e: CannotWriteException) { - e.printStackTrace() - } catch (e: TagException) { - e.printStackTrace() - } catch (e: ReadOnlyFileException) { - e.printStackTrace() - } catch (e: InvalidAudioFrameException) { - e.printStackTrace() - } - } - if (wroteArtwork) { - insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) - } else if (deletedArtwork) { - deleteAlbumArt(context, info.artworkInfo!!.albumId) - } - scan(context, info.filePaths) - }.onFailure { - it.printStackTrace() } + var wroteArtwork = false + var deletedArtwork = false + for (filePath in info.filePaths!!) { + try { + val audioFile = AudioFileIO.read(File(filePath)) + val tag = audioFile.tagOrCreateAndSetDefault + if (info.fieldKeyValueMap != null) { + for ((key, value) in info.fieldKeyValueMap) { + try { + tag.setField(key, value) + } catch (e: FieldDataInvalidException) { + withContext(Dispatchers.Main) { + context.showToast(R.string.could_not_write_tags_to_file) + } + return@withContext listOf() + } catch (e: Exception) { + e.printStackTrace() + } + } + } + if (info.artworkInfo != null) { + if (info.artworkInfo.artwork == null) { + tag.deleteArtworkField() + deletedArtwork = true + } else if (artwork != null) { + tag.deleteArtworkField() + tag.setField(artwork) + wroteArtwork = true + } + } + audioFile.commit() + } catch (e: CannotReadException) { + e.printStackTrace() + } catch (e: IOException) { + e.printStackTrace() + } catch (e: CannotWriteException) { + e.printStackTrace() + } catch (e: TagException) { + e.printStackTrace() + } catch (e: ReadOnlyFileException) { + e.printStackTrace() + } catch (e: InvalidAudioFrameException) { + e.printStackTrace() + } + } + if (wroteArtwork) { + insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) + } else if (deletedArtwork) { + deleteAlbumArt(context, info.artworkInfo!!.albumId) + } + scan(context, info.filePaths) } } - @RequiresApi(Build.VERSION_CODES.R) suspend fun writeTagsToFilesR(context: Context, info: AudioTagInfo): List = withContext(Dispatchers.IO) { val cacheFiles = mutableListOf() - runCatching { - var artwork: Artwork? = null - var albumArtFile: File? = null - if (info.artworkInfo?.artwork != null) { - try { - albumArtFile = createAlbumArtFile(context).canonicalFile - info.artworkInfo.artwork.compress( - Bitmap.CompressFormat.JPEG, - 100, - albumArtFile.outputStream() - ) - artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) - } catch (e: IOException) { - e.printStackTrace() - } + var artwork: Artwork? = null + var albumArtFile: File? = null + if (info.artworkInfo?.artwork != null) { + try { + albumArtFile = createAlbumArtFile(context).canonicalFile + info.artworkInfo.artwork.compress( + Bitmap.CompressFormat.JPEG, + 100, + albumArtFile.outputStream() + ) + artwork = AndroidArtwork.createArtworkFromFile(albumArtFile) + } catch (e: IOException) { + e.printStackTrace() } - var wroteArtwork = false - var deletedArtwork = false - for (filePath in info.filePaths!!) { - try { - val originFile = File(filePath) - val cacheFile = File(context.cacheDir, originFile.name) - cacheFiles.add(cacheFile) - originFile.inputStream().use { input -> - cacheFile.outputStream().use { output -> - input.copyTo(output) - } + } + var wroteArtwork = false + var deletedArtwork = false + for (filePath in info.filePaths!!) { + try { + val originFile = File(filePath) + val cacheFile = File(context.cacheDir, originFile.name) + cacheFiles.add(cacheFile) + originFile.inputStream().use { input -> + cacheFile.outputStream().use { output -> + input.copyTo(output) } - val audioFile = AudioFileIO.read(cacheFile) - val tag = audioFile.tagOrCreateAndSetDefault - if (info.fieldKeyValueMap != null) { - for ((key, value) in info.fieldKeyValueMap) { - try { - tag.setField(key, value) - } catch (e: Exception) { - e.printStackTrace() + } + val audioFile = AudioFileIO.read(cacheFile) + val tag = audioFile.tagOrCreateAndSetDefault + if (info.fieldKeyValueMap != null) { + for ((key, value) in info.fieldKeyValueMap) { + try { + tag.setField(key, value) + } catch (e: FieldDataInvalidException) { + withContext(Dispatchers.Main) { + context.showToast(R.string.could_not_write_tags_to_file) } + return@withContext listOf() + } catch (e: Exception) { + e.printStackTrace() } } - if (info.artworkInfo != null) { - if (info.artworkInfo.artwork == null) { - tag.deleteArtworkField() - deletedArtwork = true - } else if (artwork != null) { - tag.deleteArtworkField() - tag.setField(artwork) - wroteArtwork = true - } - } - audioFile.commit() - } catch (e: CannotReadException) { - e.printStackTrace() - } catch (e: IOException) { - e.printStackTrace() - } catch (e: CannotWriteException) { - e.printStackTrace() - } catch (e: TagException) { - e.printStackTrace() - } catch (e: ReadOnlyFileException) { - e.printStackTrace() - } catch (e: InvalidAudioFrameException) { - e.printStackTrace() } + if (info.artworkInfo != null) { + if (info.artworkInfo.artwork == null) { + tag.deleteArtworkField() + deletedArtwork = true + } else if (artwork != null) { + tag.deleteArtworkField() + tag.setField(artwork) + wroteArtwork = true + } + } + audioFile.commit() + } catch (e: CannotReadException) { + e.printStackTrace() + } catch (e: IOException) { + e.printStackTrace() + } catch (e: CannotWriteException) { + e.printStackTrace() + } catch (e: TagException) { + e.printStackTrace() + } catch (e: ReadOnlyFileException) { + e.printStackTrace() + } catch (e: InvalidAudioFrameException) { + e.printStackTrace() } - if (wroteArtwork) { - insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) - } else if (deletedArtwork) { - deleteAlbumArt(context, info.artworkInfo!!.albumId) - } - }.onFailure { - it.printStackTrace() + } + if (wroteArtwork) { + insertAlbumArt(context, info.artworkInfo!!.albumId, albumArtFile!!.path) + } else if (deletedArtwork) { + deleteAlbumArt(context, info.artworkInfo!!.albumId) } cacheFiles } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e6eaba7a..e9609c7c1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -562,4 +562,5 @@ You have to select at least one category. You will be forwarded to the issue tracker website. Your account data is only used for authentication. + Could not write tags to the music file! From 4e557fffaebc285fd05aaffb2e8f1053f31d8a18 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Sat, 18 Mar 2023 15:08:07 +0530 Subject: [PATCH 12/22] feat: Add A13 granular permissions --- app/src/main/AndroidManifest.xml | 11 ++++++++--- .../retromusic/activities/PermissionActivity.kt | 5 +---- .../activities/base/AbsMusicServiceActivity.kt | 13 ++++++++++--- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8db74d0f6..c9c99e633 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,11 @@ - + + + @@ -30,7 +34,9 @@ + tools:ignore="UnusedAttribute"> diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/PermissionActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/PermissionActivity.kt index da88b2a90..f58be5ba2 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/PermissionActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/PermissionActivity.kt @@ -129,10 +129,7 @@ class PermissionActivity : AbsMusicServiceActivity() { } private fun hasStoragePermission(): Boolean { - return ActivityCompat.checkSelfPermission( - this, - Manifest.permission.READ_EXTERNAL_STORAGE - ) == PackageManager.PERMISSION_GRANTED + return hasPermissions() } @RequiresApi(Build.VERSION_CODES.S) diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt index 07937c7b5..e2485a7ee 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsMusicServiceActivity.kt @@ -16,8 +16,10 @@ package code.name.monkey.retromusic.activities.base import android.Manifest import android.content.* +import android.os.Build.VERSION_CODES import android.os.Bundle import android.os.IBinder +import androidx.core.content.ContextCompat import androidx.lifecycle.lifecycleScope import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.retromusic.R @@ -96,8 +98,7 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventLi filter.addAction(MEDIA_STORE_CHANGED) filter.addAction(FAVORITE_STATE_CHANGED) - registerReceiver(musicStateReceiver, filter) - + ContextCompat.registerReceiver(this, musicStateReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED) receiverRegistered = true } @@ -190,7 +191,13 @@ abstract class AbsMusicServiceActivity : AbsBaseActivity(), IMusicServiceEventLi } override fun getPermissionsToRequest(): Array { - return mutableListOf(Manifest.permission.READ_EXTERNAL_STORAGE).apply { + return mutableListOf().apply { + if (VersionUtils.hasT()) { + add(Manifest.permission.READ_MEDIA_AUDIO) + add(Manifest.permission.POST_NOTIFICATIONS) + } else { + add(Manifest.permission.READ_EXTERNAL_STORAGE) + } if (!VersionUtils.hasR()) { add(Manifest.permission.WRITE_EXTERNAL_STORAGE) } From e483038b6c6451b6f50b73c20419f9884d748595 Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Sat, 18 Mar 2023 15:50:50 +0530 Subject: [PATCH 13/22] feat: Add A13 per-app language preference compatibility with the existing language chooser --- .../retromusic/extensions/extensions.kt | 4 +- app/src/main/AndroidManifest.xml | 11 +++++ .../code/name/monkey/retromusic/Constants.kt | 1 + .../retromusic/LanguageContextWrapper.kt | 25 ----------- .../activities/base/AbsThemeActivity.kt | 24 +++++----- .../activities/bugreport/model/DeviceInfo.kt | 3 +- .../settings/OtherSettingsFragment.kt | 18 +++++++- .../retromusic/glide/RetroMusicGlideModule.kt | 8 +++- .../monkey/retromusic/util/PreferenceUtil.kt | 15 ++++++- app/src/main/res/xml/locales_config.xml | 45 +++++++++++++++++++ .../retromusic/extensions/extensions.kt | 4 +- 11 files changed, 113 insertions(+), 45 deletions(-) delete mode 100644 app/src/main/java/code/name/monkey/retromusic/LanguageContextWrapper.kt create mode 100644 app/src/main/res/xml/locales_config.xml diff --git a/app/src/fdroid/java/code/name/monkey/retromusic/extensions/extensions.kt b/app/src/fdroid/java/code/name/monkey/retromusic/extensions/extensions.kt index 1dc3ae58f..dffaedfa4 100644 --- a/app/src/fdroid/java/code/name/monkey/retromusic/extensions/extensions.kt +++ b/app/src/fdroid/java/code/name/monkey/retromusic/extensions/extensions.kt @@ -8,8 +8,8 @@ import androidx.fragment.app.FragmentActivity fun Context.setUpMediaRouteButton(menu: Menu) {} -fun FragmentActivity.installLanguageAndRecreate(code: String) { - recreate() +fun FragmentActivity.installLanguageAndRecreate(code: String, onInstallComplete: () -> Unit) { + onInstallComplete() } fun Context.goToProVersion() {} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c9c99e633..e35633fe0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,6 +39,7 @@ android:enableOnBackInvokedCallback="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:localeConfig="@xml/locales_config" android:requestLegacyExternalStorage="true" android:restoreAnyVersion="true" android:roundIcon="@mipmap/ic_launcher_round" @@ -328,6 +329,16 @@ + + + + +