Fixed Playlist save
This commit is contained in:
parent
9a32aa2805
commit
e9b7b5a203
5 changed files with 129 additions and 33 deletions
|
@ -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,8 +49,44 @@ class SavePlaylistDialog : DialogFragment() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val playlistWithSongs = extraNotNull<PlaylistWithSongs>(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()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val file = PlaylistsUtil.savePlaylistWithSongs(playlistWithSongs)
|
||||
MediaScannerConnection.scanFile(
|
||||
requireActivity(),
|
||||
|
@ -65,6 +104,7 @@ class SavePlaylistDialog : DialogFragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
return materialDialog(R.string.save_playlist_title)
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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<Song> = 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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -321,7 +322,7 @@ public class PlaylistsUtil {
|
|||
Cursor cursor =
|
||||
context
|
||||
.getContentResolver()
|
||||
.query(EXTERNAL_CONTENT_URI, new String[] {}, selection, values, null);
|
||||
.query(EXTERNAL_CONTENT_URI, new String[]{}, selection, values, null);
|
||||
|
||||
boolean exists = false;
|
||||
if (cursor != null) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue