Skip to content

Commit 2feaf59

Browse files
authored
Merge pull request #561 from naveensingh/improve_file_deletion
Improve file deletion
2 parents 3c03ce8 + 8658d9e commit 2feaf59

File tree

10 files changed

+138
-70
lines changed

10 files changed

+138
-70
lines changed

app/src/main/kotlin/com/simplemobiletools/musicplayer/adapters/AlbumsTracksAdapter.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ class AlbumsTracksAdapter(
179179
positions.forEach {
180180
items.removeAt(it)
181181
}
182+
183+
// finish activity if all tracks are deleted
184+
if (items.none { it is Track }) {
185+
activity.finish()
186+
}
182187
}
183188
}
184189
}

app/src/main/kotlin/com/simplemobiletools/musicplayer/adapters/TracksAdapter.kt

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,9 @@ class TracksAdapter(
114114

115115
override fun getItemKeyPosition(key: Int) = tracks.indexOfFirst { it.hashCode() == key }
116116

117-
override fun onActionModeCreated() {
118-
if (isPlaylistContent) {
119-
notifyDataSetChanged()
120-
}
121-
}
117+
override fun onActionModeCreated() {}
122118

123-
override fun onActionModeDestroyed() {
124-
if (isPlaylistContent) {
125-
notifyDataSetChanged()
126-
}
127-
}
119+
override fun onActionModeDestroyed() {}
128120

129121
private fun addToPlaylist() {
130122
activity.addTracksToPlaylist(getSelectedTracks()) {
@@ -207,6 +199,11 @@ class TracksAdapter(
207199
}
208200

209201
finishActMode()
202+
203+
// finish activity if all tracks are deleted
204+
if (tracks.isEmpty() && !isPlaylistContent) {
205+
activity.finish()
206+
}
210207
}
211208
}
212209
}

app/src/main/kotlin/com/simplemobiletools/musicplayer/adapters/TracksHeaderAdapter.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ class TracksHeaderAdapter(activity: SimpleActivity, var items: ArrayList<ListIte
160160
positions.forEach {
161161
items.removeAt(it)
162162
}
163+
164+
// finish activity if all tracks are deleted
165+
if (items.none { it is Track }) {
166+
activity.finish()
167+
}
163168
}
164169
}
165170
}
@@ -227,7 +232,9 @@ class TracksHeaderAdapter(activity: SimpleActivity, var items: ArrayList<ListIte
227232
}
228233
}
229234
} else {
230-
findViewById<ImageView>(R.id.album_image).setImageDrawable(placeholder)
235+
activity.runOnUiThread {
236+
findViewById<ImageView>(R.id.album_image).setImageDrawable(placeholder)
237+
}
231238
}
232239
}
233240
}

app/src/main/kotlin/com/simplemobiletools/musicplayer/extensions/Activity.kt

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ package com.simplemobiletools.musicplayer.extensions
33
import android.app.Activity
44
import android.content.ContentUris
55
import android.content.Intent
6-
import android.net.Uri
76
import android.provider.MediaStore
87
import com.simplemobiletools.commons.activities.BaseSimpleActivity
98
import com.simplemobiletools.commons.dialogs.PropertiesDialog
10-
import com.simplemobiletools.commons.extensions.getMediaContent
9+
import com.simplemobiletools.commons.extensions.rescanPaths
1110
import com.simplemobiletools.commons.extensions.toast
1211
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
1312
import com.simplemobiletools.commons.helpers.isRPlus
@@ -70,40 +69,61 @@ fun Activity.playNextInQueue(track: Track, callback: () -> Unit) {
7069
}
7170

7271
fun BaseSimpleActivity.deleteTracks(tracks: List<Track>, callback: () -> Unit) {
73-
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
74-
if (isRPlus()) {
75-
val (tracksWithoutId, tracksWithId) = tracks.partition { (it.flags and FLAG_MANUAL_CACHE) != 0 }
76-
77-
val uris = tracksWithId.map { ContentUris.withAppendedId(uri, it.mediaStoreId) } as ArrayList<Uri>
78-
val contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
79-
uris += tracksWithoutId.mapNotNull { getMediaContent(it.path, contentUri) }
72+
try {
73+
audioHelper.deleteTracks(tracks)
74+
audioHelper.removeInvalidAlbumsArtists()
75+
} catch (ignored: Exception) {
76+
}
8077

81-
deleteSDK30Uris(uris) { success ->
82-
if (success) {
83-
removeQueueItems(tracks)
78+
val contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
79+
maybeRescanTrackPaths(tracks) { tracksToDelete ->
80+
if (tracksToDelete.isNotEmpty()) {
81+
if (isRPlus()) {
82+
val uris = tracksToDelete.map { ContentUris.withAppendedId(contentUri, it.mediaStoreId) }
83+
deleteSDK30Uris(uris) { success ->
84+
if (success) {
85+
removeQueueItems(tracksToDelete)
86+
EventBus.getDefault().post(Events.RefreshFragments())
87+
callback()
88+
} else {
89+
toast(R.string.unknown_error_occurred)
90+
}
91+
}
92+
} else {
93+
tracksToDelete.forEach { track ->
94+
try {
95+
val where = "${MediaStore.Audio.Media._ID} = ?"
96+
val args = arrayOf(track.mediaStoreId.toString())
97+
contentResolver.delete(contentUri, where, args)
98+
File(track.path).delete()
99+
} catch (ignored: Exception) {
100+
}
101+
}
102+
103+
removeQueueItems(tracksToDelete)
84104
EventBus.getDefault().post(Events.RefreshFragments())
85105
callback()
86-
} else {
87-
toast(R.string.unknown_error_occurred)
88106
}
89107
}
90-
return
91108
}
109+
}
92110

93-
tracks.forEach { track ->
94-
try {
95-
val where = "${MediaStore.Audio.Media._ID} = ?"
96-
val args = arrayOf(track.mediaStoreId.toString())
97-
contentResolver.delete(uri, where, args)
98-
audioHelper.deleteTrack(track.mediaStoreId)
99-
File(track.path).delete()
100-
} catch (ignored: Exception) {
111+
private fun Activity.maybeRescanTrackPaths(tracks: List<Track>, callback: (tracks: List<Track>) -> Unit) {
112+
val tracksWithoutId = tracks.filter { it.mediaStoreId == 0L || (it.flags and FLAG_MANUAL_CACHE != 0) }
113+
if (tracksWithoutId.isNotEmpty()) {
114+
val pathsToRescan = tracksWithoutId.map { it.path }
115+
rescanPaths(pathsToRescan) {
116+
for (track in tracks) {
117+
if (track.mediaStoreId == 0L || (track.flags and FLAG_MANUAL_CACHE != 0)) {
118+
track.mediaStoreId = getMediaStoreIdFromPath(track.path)
119+
}
120+
}
121+
122+
callback(tracks)
101123
}
124+
} else {
125+
callback(tracks)
102126
}
103-
104-
removeQueueItems(tracks)
105-
EventBus.getDefault().post(Events.RefreshFragments())
106-
callback()
107127
}
108128

109129
fun Activity.refreshAfterEdit(track: Track) {

app/src/main/kotlin/com/simplemobiletools/musicplayer/fragments/FoldersFragment.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,7 @@ class FoldersFragment(context: Context, attributeSet: AttributeSet) : MyViewPage
3030

3131
override fun setupFragment(activity: BaseSimpleActivity) {
3232
ensureBackgroundThread {
33-
var tracks = context.audioHelper.getAllTracks()
34-
tracks = tracks.distinctBy { "${it.path}/${it.mediaStoreId}" }.toMutableList() as ArrayList<Track>
35-
36-
Track.sorting = context.config.trackSorting
37-
tracks.sort()
38-
33+
val tracks = context.audioHelper.getAllTracks()
3934
val foldersMap = tracks.groupBy { it.folderName }
4035
val folders = ArrayList<Folder>()
4136
val excludedFolders = activity.config.excludedFolders

app/src/main/kotlin/com/simplemobiletools/musicplayer/helpers/AudioHelper.kt

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ class AudioHelper(private val context: Context) {
2525
}
2626

2727
fun getAllTracks(): ArrayList<Track> {
28-
return context.tracksDAO.getAll()
28+
val tracks = context.tracksDAO.getAll()
2929
.distinctBy { "${it.path}/${it.mediaStoreId}" } as ArrayList<Track>
30+
31+
Track.sorting = config.trackSorting
32+
tracks.sort()
33+
return tracks
3034
}
3135

3236
fun getFolderTracks(folder: String): ArrayList<Track> {
@@ -53,8 +57,14 @@ class AudioHelper(private val context: Context) {
5357
context.tracksDAO.removeTrack(mediaStoreId)
5458
}
5559

56-
fun deleteTracks(albums: List<Track>) {
57-
context.tracksDAO.removeTracks(albums.toList())
60+
fun deleteTracks(tracks: List<Track>) {
61+
tracks.forEach {
62+
deleteTrack(it.mediaStoreId)
63+
}
64+
}
65+
66+
fun insertArtists(artists: List<Artist>) {
67+
context.artistDAO.insertAll(artists)
5868
}
5969

6070
fun getAllArtists(): ArrayList<Artist> {
@@ -81,8 +91,18 @@ class AudioHelper(private val context: Context) {
8191
)
8292
}
8393

94+
fun deleteArtist(id: Long) {
95+
context.artistDAO.deleteArtist(id)
96+
}
97+
8498
fun deleteArtists(artists: List<Artist>) {
85-
context.artistDAO.deleteAll(artists)
99+
artists.forEach {
100+
deleteArtist(it.id)
101+
}
102+
}
103+
104+
fun insertAlbums(albums: List<Album>) {
105+
context.albumsDAO.insertAll(albums)
86106
}
87107

88108
fun getAlbum(albumId: Long): Album? {
@@ -107,8 +127,14 @@ class AudioHelper(private val context: Context) {
107127
.distinctBy { "${it.path}/${it.mediaStoreId}" } as ArrayList<Track>
108128
}
109129

130+
private fun deleteAlbum(id: Long) {
131+
context.albumsDAO.deleteAlbum(id)
132+
}
133+
110134
fun deleteAlbums(albums: List<Album>) {
111-
context.albumsDAO.deleteAll(albums.toList())
135+
albums.forEach {
136+
deleteAlbum(it.id)
137+
}
112138
}
113139

114140
fun insertPlaylist(playlist: Playlist): Long {
@@ -147,4 +173,16 @@ class AudioHelper(private val context: Context) {
147173
context.tracksDAO.removePlaylistSongs(it.id)
148174
}
149175
}
176+
177+
fun removeInvalidAlbumsArtists() {
178+
val tracks = context.tracksDAO.getAll()
179+
val albums = context.albumsDAO.getAll()
180+
val artists = context.artistDAO.getAll()
181+
182+
val invalidAlbums = albums.filter { album -> tracks.none { it.albumId == album.id } }
183+
deleteAlbums(invalidAlbums)
184+
185+
val invalidArtists = artists.filter { artist -> tracks.none { it.artistId == artist.id } }
186+
deleteArtists(invalidArtists)
187+
}
150188
}

app/src/main/kotlin/com/simplemobiletools/musicplayer/helpers/SimpleMediaScanner.kt

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class SimpleMediaScanner(private val context: Application) {
3333
private var showProgress = false
3434
private var onScanComplete: ((complete: Boolean) -> Unit)? = null
3535

36+
private val mediaStorePaths = arrayListOf<String>()
3637
private val newTracks = arrayListOf<Track>()
3738
private val newAlbums = arrayListOf<Album>()
3839
private val newArtists = arrayListOf<Artist>()
@@ -75,6 +76,7 @@ class SimpleMediaScanner(private val context: Application) {
7576
newTracks.clear()
7677
newAlbums.clear()
7778
newArtists.clear()
79+
mediaStorePaths.clear()
7880
scanning = false
7981
hideScanProgress()
8082
}
@@ -91,6 +93,7 @@ class SimpleMediaScanner(private val context: Application) {
9193
newTracks += getTracksSync()
9294
newArtists += getArtistsSync()
9395
newAlbums += getAlbumsSync(newArtists)
96+
mediaStorePaths += newTracks.map { it.path }
9497

9598
// ignore tracks from excluded folders and tracks with no albums, artists
9699
val albumIds = newAlbums.map { it.id }
@@ -154,17 +157,19 @@ class SimpleMediaScanner(private val context: Application) {
154157
}
155158

156159
private fun updateAllDatabases() {
157-
context.tracksDAO.insertAll(newTracks)
158-
context.albumsDAO.insertAll(newAlbums)
159-
context.artistDAO.insertAll(newArtists)
160+
context.audioHelper.apply {
161+
insertTracks(newTracks)
162+
insertAlbums(newAlbums)
163+
insertArtists(newArtists)
164+
}
160165
updateAllTracksPlaylist()
161166
}
162167

163168
private fun updateAllTracksPlaylist() {
164169
if (!config.wasAllTracksPlaylistCreated) {
165170
val allTracksLabel = context.resources.getString(R.string.all_tracks)
166171
val playlist = Playlist(ALL_TRACKS_PLAYLIST_ID, allTracksLabel)
167-
context.playlistDAO.insert(playlist)
172+
context.audioHelper.insertPlaylist(playlist)
168173
config.wasAllTracksPlaylistCreated = true
169174
}
170175

@@ -300,6 +305,10 @@ class SimpleMediaScanner(private val context: Application) {
300305
findAudioFiles(rootFile, audioFilePaths, excludedPaths)
301306
}
302307

308+
if (audioFilePaths.isEmpty()) {
309+
return arrayListOf()
310+
}
311+
303312
val tracksSet = ConcurrentHashMap.newKeySet<Track>()
304313
val paths = audioFilePaths.toTypedArray()
305314
val totalPaths = paths.size
@@ -359,6 +368,7 @@ class SimpleMediaScanner(private val context: Application) {
359368
tracks.add(it)
360369
}
361370

371+
maybeRescanPaths(audioFilePaths)
362372
return tracks
363373
}
364374

@@ -383,6 +393,11 @@ class SimpleMediaScanner(private val context: Application) {
383393
}
384394
}
385395

396+
private fun maybeRescanPaths(paths: ArrayList<String>) {
397+
val pathsToRescan = paths.filter { path -> path !in mediaStorePaths }
398+
context.rescanPaths(pathsToRescan)
399+
}
400+
386401
private fun splitIntoArtists(tracks: ArrayList<Track>): ArrayList<Artist> {
387402
val artists = arrayListOf<Artist>()
388403
val tracksGroupedByArtist = tracks.groupBy { it.artist }
@@ -425,20 +440,20 @@ class SimpleMediaScanner(private val context: Application) {
425440
// remove invalid tracks
426441
val newTrackIds = newTracks.map { it.mediaStoreId } as ArrayList<Long>
427442
val newTrackPaths = newTracks.map { it.path } as ArrayList<String>
428-
val invalidTracks = context.tracksDAO.getAll().filter { it.mediaStoreId !in newTrackIds || it.path !in newTrackPaths }
429-
context.tracksDAO.removeTracks(invalidTracks)
443+
val invalidTracks = context.audioHelper.getAllTracks().filter { it.mediaStoreId !in newTrackIds || it.path !in newTrackPaths }
444+
context.audioHelper.deleteTracks(invalidTracks)
430445
newTracks.removeAll(invalidTracks.toSet())
431446

432447
// remove invalid albums
433448
val newAlbumIds = newAlbums.map { it.id }
434-
val invalidAlbums = context.albumsDAO.getAll().filter { it.id !in newAlbumIds }.toMutableList()
449+
val invalidAlbums = context.audioHelper.getAllAlbums().filter { it.id !in newAlbumIds }.toMutableList()
435450
invalidAlbums += newAlbums.filter { album -> newTracks.none { it.albumId == album.id } }
436-
context.albumsDAO.deleteAll(invalidAlbums)
451+
context.audioHelper.deleteAlbums(invalidAlbums)
437452
newAlbums.removeAll(invalidAlbums.toSet())
438453

439454
// remove invalid artists
440455
val newArtistIds = newArtists.map { it.id }
441-
val invalidArtists = context.artistDAO.getAll().filter { it.id !in newArtistIds }.toMutableList()
456+
val invalidArtists = context.audioHelper.getAllArtists().filter { it.id !in newArtistIds }.toMutableList()
442457
for (artist in newArtists) {
443458
val artistId = artist.id
444459
val albumsByArtist = newAlbums.filter { it.artistId == artistId }
@@ -451,13 +466,13 @@ class SimpleMediaScanner(private val context: Application) {
451466
val albumCnt = albumsByArtist.size
452467
val trackCnt = albumsByArtist.sumOf { it.trackCnt }
453468
if (trackCnt != artist.trackCnt || albumCnt != artist.albumCnt) {
454-
context.artistDAO.deleteArtist(artistId)
469+
context.audioHelper.deleteArtist(artistId)
455470
val updated = artist.copy(trackCnt = trackCnt, albumCnt = albumCnt)
456-
context.artistDAO.insert(updated)
471+
context.audioHelper.insertArtists(listOf(updated))
457472
}
458473
}
459474

460-
context.artistDAO.deleteAll(invalidArtists)
475+
context.audioHelper.deleteArtists(invalidArtists)
461476
}
462477

463478
@Synchronized

app/src/main/kotlin/com/simplemobiletools/musicplayer/interfaces/AlbumsDao.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,4 @@ interface AlbumsDao {
2222

2323
@Query("DELETE FROM albums WHERE id = :id")
2424
fun deleteAlbum(id: Long)
25-
26-
@Delete
27-
fun deleteAll(albums: List<Album>)
2825
}

0 commit comments

Comments
 (0)