From e9b7b5a20363d10b33bf1ad22381ee2e4790509c Mon Sep 17 00:00:00 2001 From: Prathamesh More Date: Wed, 17 Nov 2021 16:52:39 +0530 Subject: [PATCH] Fixed Playlist save --- .../retromusic/dialogs/SavePlaylistDialog.kt | 70 +++++++++++++++---- .../retromusic/extensions/IntentExtensions.kt | 35 ++++++++++ .../monkey/retromusic/helper/M3UWriter.kt | 24 +++++-- .../monkey/retromusic/util/PlaylistsUtil.java | 7 +- .../appthemehelper/util/VersionUtils.kt | 26 ++++--- 5 files changed, 129 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/code/name/monkey/retromusic/extensions/IntentExtensions.kt diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/SavePlaylistDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/SavePlaylistDialog.kt index 62770536..ef4dd7cc 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/SavePlaylistDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/SavePlaylistDialog.kt @@ -21,13 +21,16 @@ import android.widget.Toast import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope +import code.name.monkey.appthemehelper.util.VersionUtils import code.name.monkey.retromusic.App import code.name.monkey.retromusic.EXTRA_PLAYLIST import code.name.monkey.retromusic.R import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.extensions.colorButtons +import code.name.monkey.retromusic.extensions.createNewFile import code.name.monkey.retromusic.extensions.extraNotNull import code.name.monkey.retromusic.extensions.materialDialog +import code.name.monkey.retromusic.helper.M3UWriter import code.name.monkey.retromusic.util.PlaylistsUtil import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -46,22 +49,59 @@ class SavePlaylistDialog : DialogFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - lifecycleScope.launch(Dispatchers.IO) { - val playlistWithSongs = extraNotNull(EXTRA_PLAYLIST).value - val file = PlaylistsUtil.savePlaylistWithSongs(playlistWithSongs) - MediaScannerConnection.scanFile( - requireActivity(), - arrayOf(file.path), - null - ) { _, _ -> + val playlistWithSongs = extraNotNull(EXTRA_PLAYLIST).value + + if (VersionUtils.hasR()) { + createNewFile( + "audio/mpegurl", + playlistWithSongs.playlistEntity.playlistName + ) { outputStream, data -> + try { + if (outputStream != null) { + lifecycleScope.launch(Dispatchers.IO) { + M3UWriter.writeIO( + outputStream, + playlistWithSongs + ) + withContext(Dispatchers.Main) { + Toast.makeText( + requireContext(), + String.format( + requireContext().getString(R.string.saved_playlist_to), + data?.lastPathSegment + ), + Toast.LENGTH_LONG + ).show() + dismiss() + } + } + } + } catch (e: Exception) { + Toast.makeText( + context, + "Something went wrong : " + e.message, + Toast.LENGTH_SHORT + ) + .show() + } } - withContext(Dispatchers.Main) { - Toast.makeText( - requireContext(), - String.format(App.getContext().getString(R.string.saved_playlist_to), file), - Toast.LENGTH_LONG - ).show() - dismiss() + } else { + lifecycleScope.launch(Dispatchers.IO) { + val file = PlaylistsUtil.savePlaylistWithSongs(playlistWithSongs) + MediaScannerConnection.scanFile( + requireActivity(), + arrayOf(file.path), + null + ) { _, _ -> + } + withContext(Dispatchers.Main) { + Toast.makeText( + requireContext(), + String.format(App.getContext().getString(R.string.saved_playlist_to), file), + Toast.LENGTH_LONG + ).show() + dismiss() + } } } } diff --git a/app/src/main/java/code/name/monkey/retromusic/extensions/IntentExtensions.kt b/app/src/main/java/code/name/monkey/retromusic/extensions/IntentExtensions.kt new file mode 100644 index 00000000..3c1f3988 --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/extensions/IntentExtensions.kt @@ -0,0 +1,35 @@ +package code.name.monkey.retromusic.extensions + +import android.app.Activity +import android.content.Intent +import android.net.Uri +import android.os.Environment +import android.provider.DocumentsContract +import androidx.activity.result.ActivityResult +import androidx.activity.result.contract.ActivityResultContracts +import androidx.documentfile.provider.DocumentFile +import androidx.fragment.app.Fragment +import java.io.File +import java.io.OutputStream + +fun Fragment.createNewFile( + mimeType: String, + fileName: String, + write: (outputStream: OutputStream?, data: Uri?) -> Unit +) { + val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) + intent.addCategory(Intent.CATEGORY_OPENABLE) + intent.type = mimeType + intent.putExtra(Intent.EXTRA_TITLE, fileName) + val startForResult = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) + { result: ActivityResult -> + if (result.resultCode == Activity.RESULT_OK) { + val outputStream: OutputStream? = + context?.contentResolver?.openOutputStream(result.data?.data!!) + write(outputStream, result.data?.data) + } + + } + startForResult.launch(intent) +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/M3UWriter.kt b/app/src/main/java/code/name/monkey/retromusic/helper/M3UWriter.kt index 293d3d38..c834b9a5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/M3UWriter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/M3UWriter.kt @@ -18,10 +18,7 @@ import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.toSongs import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.model.Song -import java.io.BufferedWriter -import java.io.File -import java.io.FileWriter -import java.io.IOException +import java.io.* object M3UWriter : M3UConstants { @JvmStatic @@ -69,4 +66,23 @@ object M3UWriter : M3UConstants { } return file } + + fun writeIO(outputStream: OutputStream, playlistWithSongs: PlaylistWithSongs) { + val songs: List = playlistWithSongs.songs.sortedBy { + it.songPrimaryKey + }.toSongs() + if (songs.isNotEmpty()) { + val bufferedWriter = outputStream.bufferedWriter() + bufferedWriter.write(M3UConstants.HEADER) + songs.forEach { + bufferedWriter.newLine() + bufferedWriter.write(M3UConstants.ENTRY + it.duration + M3UConstants.DURATION_SEPARATOR + it.artistName + " - " + it.title) + bufferedWriter.newLine() + bufferedWriter.write(it.data) + } + bufferedWriter.close() + } + outputStream.flush() + outputStream.close() + } } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java index 9b677849..bcdf278e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/PlaylistsUtil.java @@ -36,6 +36,7 @@ import java.util.List; import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.db.PlaylistWithSongs; +import code.name.monkey.retromusic.helper.M3UConstants; import code.name.monkey.retromusic.helper.M3UWriter; import code.name.monkey.retromusic.model.Playlist; import code.name.monkey.retromusic.model.PlaylistSong; @@ -319,9 +320,9 @@ public class PlaylistsUtil { private static boolean doesPlaylistExist( @NonNull Context context, @NonNull final String selection, @NonNull final String[] values) { Cursor cursor = - context - .getContentResolver() - .query(EXTERNAL_CONTENT_URI, new String[] {}, selection, values, null); + context + .getContentResolver() + .query(EXTERNAL_CONTENT_URI, new String[]{}, selection, values, null); boolean exists = false; if (cursor != null) { 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 80a9585e..e29e9e5f 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 @@ -8,18 +8,11 @@ import android.os.Build object VersionUtils { - /** - * @return true if device is running API >= 21 - */ - fun hasLollipop(): Boolean { - return Build.VERSION.SDK_INT >= 21 - } - /** * @return true if device is running API >= 23 */ fun hasMarshmallow(): Boolean { - return Build.VERSION.SDK_INT >= 23 + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M } /** @@ -30,7 +23,7 @@ object VersionUtils { } /** - * @return true if device is running API >= 24 + * @return true if device is running API >= 25 */ fun hasNougatMR(): Boolean { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 @@ -44,20 +37,31 @@ object VersionUtils { } /** - * @return true if device is running API >= 27 + * @return true if device is running API >= 28 */ fun hasP(): Boolean { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P } /** - * @return true if device is running API >= 28 + * @return true if device is running API >= 29 */ @JvmStatic fun hasQ(): Boolean { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q } + /** + * @return true if device is running API >= 30 + */ + @JvmStatic + fun hasR(): Boolean { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R + } + + /** + * @return true if device is running API >= 31 + */ @JvmStatic fun hasS(): Boolean { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S