fetch whole songs from MediaStore on Android Q+, not just paths

This commit is contained in:
tibbi 2020-05-06 10:33:09 +02:00
parent 3186dfb737
commit 4a089bc878
4 changed files with 76 additions and 53 deletions

View file

@ -331,7 +331,7 @@ class MainActivity : SimpleActivity(), MainActivityInterface {
toast(R.string.fetching_songs)
ensureBackgroundThread {
val folderSongs = getFolderSongs(File(it))
RoomHelper(applicationContext).addSongsToPlaylist(folderSongs)
RoomHelper(applicationContext).addPathsToPlaylist(folderSongs)
sendIntent(REFRESH_LIST)
}
}
@ -356,7 +356,7 @@ class MainActivity : SimpleActivity(), MainActivityInterface {
ensureBackgroundThread {
lastFilePickerPath = it
if (it.isAudioFast()) {
RoomHelper(applicationContext).addSongToPlaylist(it)
RoomHelper(applicationContext).addPathToPlaylist(it)
sendIntent(REFRESH_LIST)
} else {
toast(R.string.invalid_file_format)
@ -398,7 +398,7 @@ class MainActivity : SimpleActivity(), MainActivityInterface {
val playlist = Playlist(0, playlistName)
val newPlaylistId = playlistDAO.insert(playlist).toInt()
RoomHelper(applicationContext).addSongsToPlaylist(folderSongs, newPlaylistId)
RoomHelper(applicationContext).addPathsToPlaylist(folderSongs, newPlaylistId)
playlistChanged(newPlaylistId)
}

View file

@ -67,7 +67,7 @@ fun Context.getPlaylistSongs(playlistId: Int): ArrayList<Song> {
songs.forEach {
it.title = it.getProperTitle(showFilename)
if (File(it.path).exists()) {
if (File(it.path).exists() || it.path.startsWith("content://")) {
validSongs.add(it)
} else {
invalidSongs.add(it)

View file

@ -9,15 +9,19 @@ import com.simplemobiletools.musicplayer.extensions.songsDAO
import com.simplemobiletools.musicplayer.models.Song
class RoomHelper(val context: Context) {
fun addSongToPlaylist(path: String) {
addSongsToPlaylist(arrayListOf(path))
fun addPathToPlaylist(path: String) {
addPathsToPlaylist(arrayListOf(path))
}
fun addSongsToPlaylist(paths: ArrayList<String>, playlistId: Int = context.config.currentPlaylist) {
fun addPathsToPlaylist(paths: ArrayList<String>, playlistId: Int = context.config.currentPlaylist) {
val songs = getSongsFromPaths(paths, playlistId)
context.songsDAO.insertAll(songs)
}
fun addSongsToPlaylist(songs: ArrayList<Song>, playlistId: Int = context.config.currentPlaylist) {
context.songsDAO.insertAll(songs)
}
fun getSongFromPath(path: String): Song? {
val songs = getSongsFromPaths(arrayListOf(path), 0)
return songs.firstOrNull()

View file

@ -353,28 +353,47 @@ class MusicService : Service(), MediaPlayer.OnPreparedListener, MediaPlayer.OnEr
}
private fun getAllDeviceSongs() {
val ignoredPaths = config.ignoredPaths
val uri = Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(
Audio.Media.DURATION,
Audio.Media.DATA
)
Audio.Media._ID,
Audio.Media.DURATION,
Audio.Media.DATA,
Audio.Media.ALBUM,
Audio.Media.TITLE,
Audio.Media.ARTIST)
val paths = ArrayList<String>()
queryCursor(uri, projection) { cursor ->
val duration = cursor.getIntValue(Audio.Media.DURATION) / 1000
if (duration > MIN_INITIAL_DURATION) {
val path = cursor.getStringValue(Audio.Media.DATA)
if (!ignoredPaths.contains(path) && !path.doesThisOrParentHaveNoMedia()) {
paths.add(path)
if (isQPlus()) {
val showFilename = config.showFilename
val songs = ArrayList<Song>()
queryCursor(uri, projection) { cursor ->
val id = cursor.getLongValue(Audio.Media._ID)
val path = ContentUris.withAppendedId(Audio.Media.EXTERNAL_CONTENT_URI, id).toString()
val title = cursor.getStringValue(Audio.Media.TITLE)
val artist = cursor.getStringValue(Audio.Media.ARTIST)
val duration = cursor.getIntValue(Audio.Media.DURATION) / 1000
val album = cursor.getStringValue(Audio.Media.ALBUM)
val song = Song(id, title, artist, path, duration, album, ALL_SONGS_PLAYLIST_ID, TYPE_FILE)
song.title = song.getProperTitle(showFilename)
songs.add(song)
}
RoomHelper(this).addSongsToPlaylist(songs)
} else {
val ignoredPaths = config.ignoredPaths
val paths = ArrayList<String>()
queryCursor(uri, projection) { cursor ->
val duration = cursor.getIntValue(Audio.Media.DURATION) / 1000
if (duration > MIN_INITIAL_DURATION) {
val path = cursor.getStringValue(Audio.Media.DATA)
if (!ignoredPaths.contains(path) && !path.doesThisOrParentHaveNoMedia()) {
paths.add(path)
}
}
}
}
val storedAllSongPaths = songsDAO.getSongsFromPlaylist(ALL_SONGS_PLAYLIST_ID).map { it.path }
paths.removeAll(storedAllSongPaths)
RoomHelper(this).addSongsToPlaylist(paths)
val storedAllSongPaths = songsDAO.getSongsFromPlaylist(ALL_SONGS_PLAYLIST_ID).map { it.path }
paths.removeAll(storedAllSongPaths)
RoomHelper(this).addPathsToPlaylist(paths)
}
}
private fun getSortedSongs() {
@ -440,25 +459,25 @@ class MusicService : Service(), MediaPlayer.OnPreparedListener, MediaPlayer.OnEr
}
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL)
.setContentTitle(title)
.setContentText(artist)
.setSmallIcon(R.drawable.ic_headset_small)
.setLargeIcon(mCurrSongCover)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setWhen(notifWhen)
.setShowWhen(showWhen)
.setUsesChronometer(usesChronometer)
.setContentIntent(getContentIntent())
.setOngoing(ongoing)
.setChannelId(NOTIFICATION_CHANNEL)
.setCategory(Notification.CATEGORY_SERVICE)
.setStyle(androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mMediaSession?.sessionToken))
.addAction(R.drawable.ic_previous_vector, getString(R.string.previous), getIntent(PREVIOUS))
.addAction(playPauseIcon, getString(R.string.playpause), getIntent(PLAYPAUSE))
.addAction(R.drawable.ic_next_vector, getString(R.string.next), getIntent(NEXT))
.setContentTitle(title)
.setContentText(artist)
.setSmallIcon(R.drawable.ic_headset_small)
.setLargeIcon(mCurrSongCover)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setWhen(notifWhen)
.setShowWhen(showWhen)
.setUsesChronometer(usesChronometer)
.setContentIntent(getContentIntent())
.setOngoing(ongoing)
.setChannelId(NOTIFICATION_CHANNEL)
.setCategory(Notification.CATEGORY_SERVICE)
.setStyle(androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mMediaSession?.sessionToken))
.addAction(R.drawable.ic_previous_vector, getString(R.string.previous), getIntent(PREVIOUS))
.addAction(playPauseIcon, getString(R.string.playpause), getIntent(PLAYPAUSE))
.addAction(R.drawable.ic_next_vector, getString(R.string.next), getIntent(NEXT))
startForeground(NOTIFICATION_ID, notification.build())
@ -472,8 +491,8 @@ class MusicService : Service(), MediaPlayer.OnPreparedListener, MediaPlayer.OnEr
val playbackState = if (getIsPlaying()) PlaybackStateCompat.STATE_PLAYING else PlaybackStateCompat.STATE_PAUSED
try {
mMediaSession!!.setPlaybackState(PlaybackStateCompat.Builder()
.setState(playbackState, PLAYBACK_POSITION_UNKNOWN, 1.0f)
.build())
.setState(playbackState, PLAYBACK_POSITION_UNKNOWN, 1.0f)
.build())
} catch (ignored: IllegalStateException) {
}
}
@ -502,13 +521,13 @@ class MusicService : Service(), MediaPlayer.OnPreparedListener, MediaPlayer.OnEr
}
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL)
.setContentTitle("")
.setContentText("")
.setSmallIcon(R.drawable.ic_headset_small)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setChannelId(NOTIFICATION_CHANNEL)
.setCategory(Notification.CATEGORY_SERVICE)
.setContentTitle("")
.setContentText("")
.setSmallIcon(R.drawable.ic_headset_small)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setChannelId(NOTIFICATION_CHANNEL)
.setCategory(Notification.CATEGORY_SERVICE)
startForeground(NOTIFICATION_ID, notification.build())
}
@ -684,8 +703,8 @@ class MusicService : Service(), MediaPlayer.OnPreparedListener, MediaPlayer.OnEr
val lockScreenImage = if (albumImage.second) albumImage.first else null
val metadata = MediaMetadataCompat.Builder()
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, lockScreenImage)
.build()
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, lockScreenImage)
.build()
mMediaSession?.setMetadata(metadata)
}