diff --git a/app/build.gradle b/app/build.gradle index 866001890..307b233f8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { applicationId "com.github.goldy1992.mp3player" minSdkVersion MARSHMALLOW targetSdkVersion PIE - versionCode 3 - versionName "1.0.2" + versionCode 4 + versionName "1.1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" javaCompileOptions { annotationProcessorOptions { diff --git a/app/src/main/java/com/github/goldy1992/mp3player/client/views/adapters/MyGenericRecycleViewAdapter.java b/app/src/main/java/com/github/goldy1992/mp3player/client/views/adapters/MyGenericRecycleViewAdapter.java index 1a73faca4..d3a861c31 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/client/views/adapters/MyGenericRecycleViewAdapter.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/client/views/adapters/MyGenericRecycleViewAdapter.java @@ -29,9 +29,6 @@ public abstract class MyGenericRecycleViewAdapter extends MediaItemRecyclerViewA private static final String EMPTY_MEDIA_ID = "EMPTY_MEDIA_ID"; final int EMPTY_VIEW_TYPE = -1; - - - private boolean isInitialised = false; private final MediaItem EMPTY_LIST_ITEM = buildEmptyListMediaItem(); public MyGenericRecycleViewAdapter(AlbumArtPainter albumArtPainter, Handler mainHandler) { @@ -45,15 +42,14 @@ public int getItemCount() { @Override public void onChildrenLoaded(@NonNull String parentId, @NonNull ArrayList children) { - if (!isInitialised && children.isEmpty()) { - addNoChildrenFoundItem(); - } + if (!children.isEmpty()) { - this.items.addAll(children); + this.items = children; mainHandler.post(this::notifyDataSetChanged); + } else { + addNoChildrenFoundItem(); } - this.isInitialised = true; } @Override public MediaItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { diff --git a/app/src/main/java/com/github/goldy1992/mp3player/commons/MediaItemBuilder.java b/app/src/main/java/com/github/goldy1992/mp3player/commons/MediaItemBuilder.java index 6feb647f8..8354e4525 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/commons/MediaItemBuilder.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/commons/MediaItemBuilder.java @@ -86,7 +86,7 @@ public MediaItemBuilder setMediaUri(Uri mediaUri) { return this; } - public MediaItemBuilder setFile(File file) { + public MediaItemBuilder setDirectoryFile(File file) { extras.putSerializable(META_DATA_DIRECTORY, file); return this; } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/commons/Normaliser.java b/app/src/main/java/com/github/goldy1992/mp3player/commons/Normaliser.java new file mode 100644 index 000000000..9af64d9bf --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/commons/Normaliser.java @@ -0,0 +1,17 @@ +package com.github.goldy1992.mp3player.commons; + +import androidx.annotation.NonNull; + +import org.apache.commons.lang3.StringUtils; + +public final class Normaliser { + + private Normaliser() { + + } + + public static String normalise(@NonNull String query) { + query = StringUtils.stripAccents(query); + return query.trim().toUpperCase(); + } +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/MediaPlaybackService.java b/app/src/main/java/com/github/goldy1992/mp3player/service/MediaPlaybackService.java index 2d6e9733c..8928459fa 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/MediaPlaybackService.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/MediaPlaybackService.java @@ -2,7 +2,6 @@ import android.app.Notification; import android.content.Intent; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -16,6 +15,8 @@ import androidx.media.MediaBrowserServiceCompat; import com.github.goldy1992.mp3player.service.library.ContentManager; +import com.github.goldy1992.mp3player.service.library.content.observers.MediaStoreObservers; +import com.github.goldy1992.mp3player.service.library.search.managers.SearchDatabaseManagers; import com.google.android.exoplayer2.ui.PlayerNotificationManager.NotificationListener; import java.util.List; @@ -29,12 +30,15 @@ public abstract class MediaPlaybackService extends MediaBrowserServiceCompat implements NotificationListener { private static final String LOG_TAG = "MEDIA_PLAYBACK_SERVICE"; + private ContentManager contentManager; private HandlerThread worker; private Handler handler; private MediaSessionConnectorCreator mediaSessionConnectorCreator; private MediaSessionCompat mediaSession; private RootAuthenticator rootAuthenticator; + private MediaStoreObservers mediaStoreObservers; + private SearchDatabaseManagers searchDatabaseManagers; abstract void initialiseDependencies(); @@ -42,14 +46,15 @@ public abstract class MediaPlaybackService extends MediaBrowserServiceCompat imp public void onCreate() { super.onCreate(); this.mediaSessionConnectorCreator.create(); - setSessionToken(mediaSession.getSessionToken()); + this.setSessionToken(mediaSession.getSessionToken()); + this.mediaStoreObservers.init(this); + this.searchDatabaseManagers.reindexAll(); } @Override public int onStartCommand (Intent intent, - int flags, - int startId) { - + int flags, + int startId) { Log.i(LOG_TAG, "breakpoint, on start command called"); return START_STICKY; } @@ -94,14 +99,15 @@ public void onLoadChildren(@NonNull String parentId, @NonNull Result getPlaylist(String id) { return getChildren(id); } - private String normalise(@NonNull String query) { - query = StringUtils.stripAccents(query); - return query.trim().toUpperCase(); - } } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/FoldersResultFilter.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/FolderSearchResultsFilter.java similarity index 89% rename from app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/FoldersResultFilter.java rename to app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/FolderSearchResultsFilter.java index 2b3644b66..d0e3fefb1 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/FoldersResultFilter.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/FolderSearchResultsFilter.java @@ -13,10 +13,10 @@ import javax.inject.Inject; -public class FoldersResultFilter extends ResultsFilter { +public class FolderSearchResultsFilter implements ResultsFilter { @Inject - public FoldersResultFilter() { + public FolderSearchResultsFilter() { super(); } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/ResultsFilter.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/ResultsFilter.java index 597669061..1c7f67206 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/ResultsFilter.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/ResultsFilter.java @@ -6,7 +6,7 @@ import java.util.List; -public abstract class ResultsFilter { +public interface ResultsFilter { - public abstract List filter(@NonNull String query, @NonNull List results); + List filter(@NonNull String query, @NonNull List results); } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/SongsFromFolderResultsFilter.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/SongsFromFolderResultsFilter.java new file mode 100644 index 000000000..3e80ccceb --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/filter/SongsFromFolderResultsFilter.java @@ -0,0 +1,39 @@ +package com.github.goldy1992.mp3player.service.library.content.filter; + +import android.support.v4.media.MediaBrowserCompat.MediaItem; + +import androidx.annotation.NonNull; + +import com.github.goldy1992.mp3player.commons.MediaItemUtils; + +import java.io.File; +import java.util.Iterator; +import java.util.List; + +import javax.inject.Inject; + +public class SongsFromFolderResultsFilter implements ResultsFilter { + + + @Inject + public SongsFromFolderResultsFilter() { + /* Empty constructor declared for dagger insert */ + } + + + @Override + public List filter(@NonNull String query, + @NonNull List results) { + File queryPath = new File(query); + Iterator iterator = results.listIterator(); + + while(iterator.hasNext()) { + MediaItem currentItem = iterator.next(); + String directoryPath = MediaItemUtils.getDirectoryPath(currentItem); + if (directoryPath == null || !directoryPath.equalsIgnoreCase(queryPath.getAbsolutePath().toUpperCase())) { + iterator.remove(); + } + } + return results; + } +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/AudioObserver.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/AudioObserver.java new file mode 100644 index 000000000..d47668ec4 --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/AudioObserver.java @@ -0,0 +1,139 @@ +package com.github.goldy1992.mp3player.service.library.content.observers; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.net.Uri; +import android.os.Handler; +import android.provider.MediaStore; +import android.support.v4.media.MediaBrowserCompat.MediaItem; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.github.goldy1992.mp3player.LogTagger; +import com.github.goldy1992.mp3player.commons.MediaItemType; +import com.github.goldy1992.mp3player.commons.MediaItemUtils; +import com.github.goldy1992.mp3player.service.library.ContentManager; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; +import com.github.goldy1992.mp3player.service.library.search.managers.FolderDatabaseManager; +import com.github.goldy1992.mp3player.service.library.search.managers.SongDatabaseManager; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +/** + * A listener to the android ContentRetriever from the URI: content://media/external/audio/media or the + * i.e. MediaStore.Audio.Media.EXTERNAL_CONTENT_URI constant. + * + * onChange is called when there is a change when a song indexed with the EXTERNAL_CONTENT_URI is + * added, changed or deleted, and update respective song and folder lists + */ +@Singleton +public class AudioObserver extends MediaStoreObserver implements LogTagger { + + /** Search Database Manager */ + private SongDatabaseManager songDatabaseManager; + + /** Search Database Manager */ + private FolderDatabaseManager folderDatabaseManager; + /** Content manager */ + private ContentManager contentManager; + + private static final long INVALID_ID = -1; + + /** + * Creates a content observer. + * + * @param handler The handler to run {@link #onChange} on, or null if none. + */ + @Inject + public AudioObserver(@Named("worker") Handler handler, + ContentResolver contentResolver, + ContentManager contentManager, + SongDatabaseManager songDatabaseManager, + FolderDatabaseManager folderDatabaseManager, + MediaItemTypeIds mediaItemTypeIds) { + super(handler, contentResolver, mediaItemTypeIds); + this.songDatabaseManager = songDatabaseManager; + this.folderDatabaseManager = folderDatabaseManager; + this.contentManager = contentManager; + } + + /** {@inheritDoc} */ + @Override + public void onChange(boolean selfChange) { + onChange(selfChange, null); + } + + /** {@inheritDoc} */ + @Override + public void onChange(boolean selfChange, Uri uri) { + onChange(selfChange, uri, -1); + } + + + /** + * {@inheritDoc} + * + * For the purpose of the Normalised search database we're not interested in who made the change + * therefore parameter, selfChange and userId are not used. + * + * @param selfChange not used + * @param uri the uri that has changed + * @param userId not used + * + */ + public void onChange(boolean selfChange, Uri uri, int userId) { + if (startsWithUri(uri)) { + updateSearchDatabase(uri); + mediaPlaybackService.notifyChildrenChanged(mediaItemTypeIds.getId(MediaItemType.SONGS)); + mediaPlaybackService.notifyChildrenChanged(mediaItemTypeIds.getId(MediaItemType.FOLDERS)); + } + // when there is a "change" to the meta data the exact id will given as the uri + Log.i(getLogTag(),"hit on change"); + } + + private void updateSearchDatabase(Uri uri) { + long id = INVALID_ID; + try { + id = ContentUris.parseId(uri); + } catch (Exception ex) { + Log.e(getLogTag(), ExceptionUtils.getStackTrace(ex)); + } + + // If we know the id then just get that id + if (INVALID_ID != id) { + MediaItem result = contentManager.getItem(id); + if (null != result) { + Log.i(getLogTag(), "UPDATING songs and folders index"); + songDatabaseManager.insert(result); + folderDatabaseManager.insert(result); + Log.i(getLogTag(), "UPDATED songs and folders"); + String directoryPath = MediaItemUtils.getDirectoryPath(result); + if (StringUtils.isNotEmpty(directoryPath)) { + mediaPlaybackService.notifyChildrenChanged(directoryPath); + } + } + } else { + songDatabaseManager.reindex(); + folderDatabaseManager.reindex(); + } + } + + @Override + public String getLogTag() { + return "AUDIO_OBSERVER"; + } + + @Override + @NonNull + public Uri getUri() { + return MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/MediaStoreObserver.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/MediaStoreObserver.java new file mode 100644 index 000000000..c1f0d3c66 --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/MediaStoreObserver.java @@ -0,0 +1,53 @@ +package com.github.goldy1992.mp3player.service.library.content.observers; + +import android.content.ContentResolver; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; + +import androidx.annotation.NonNull; + +import com.github.goldy1992.mp3player.LogTagger; +import com.github.goldy1992.mp3player.service.MediaPlaybackService; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; + +public abstract class MediaStoreObserver extends ContentObserver implements LogTagger { + + private final ContentResolver contentResolver; + + final MediaItemTypeIds mediaItemTypeIds; + + MediaPlaybackService mediaPlaybackService; + + public MediaStoreObserver(Handler handler, + ContentResolver contentResolver, + MediaItemTypeIds mediaItemTypeIds) { + super(handler); + this.contentResolver = contentResolver; + this.mediaItemTypeIds = mediaItemTypeIds; + } + + public void init(MediaPlaybackService mediaPlaybackService) { + this.mediaPlaybackService = mediaPlaybackService; + } + + public void register() { + contentResolver.registerContentObserver(getUri(), true, this); + } + + public void unregister() { + contentResolver.unregisterContentObserver(this); + } + + boolean startsWithUri(Uri uri) { + return uri != null && uri.toString().startsWith(getUriString()); + } + + @NonNull + public abstract Uri getUri(); + + @NonNull + public String getUriString() { + return getUri().toString(); + } +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/MediaStoreObservers.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/MediaStoreObservers.java new file mode 100644 index 000000000..4db90d3ce --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/observers/MediaStoreObservers.java @@ -0,0 +1,40 @@ +package com.github.goldy1992.mp3player.service.library.content.observers; + +import com.github.goldy1992.mp3player.service.MediaPlaybackService; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class MediaStoreObservers { + + private List mediaStoreObserversList; + + @Inject + public MediaStoreObservers(AudioObserver audioObserver) { + this.mediaStoreObserversList = new ArrayList<>(); + this.mediaStoreObserversList.add(audioObserver); + } + + public void init(MediaPlaybackService mediaPlaybackService) { + for (MediaStoreObserver mediaStoreObserver : mediaStoreObserversList) { + mediaStoreObserver.init(mediaPlaybackService); + } + registerAll(); + } + + public void registerAll() { + for (MediaStoreObserver mediaStoreObserver : mediaStoreObserversList) { + mediaStoreObserver.register(); + } + } + + public void unregisterAll() { + for (MediaStoreObserver mediaStoreObserver : mediaStoreObserversList) { + mediaStoreObserver.unregister(); + } + } +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/FolderResultsParser.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/FolderResultsParser.java index 49db93972..b43d63c70 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/FolderResultsParser.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/FolderResultsParser.java @@ -2,7 +2,7 @@ import android.database.Cursor; import android.provider.MediaStore; -import android.support.v4.media.MediaBrowserCompat; +import android.support.v4.media.MediaBrowserCompat.MediaItem; import androidx.annotation.NonNull; @@ -32,8 +32,8 @@ public FolderResultsParser() { } @Override - public List create(@NonNull Cursor cursor, String mediaIdPrefix) { - TreeSet listToReturn = new TreeSet<>(this); + public List create(@NonNull Cursor cursor, String mediaIdPrefix) { + TreeSet listToReturn = new TreeSet<>(this); Set directoryPathSet = new HashSet<>(); while (cursor.moveToNext()) { String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); @@ -45,7 +45,7 @@ public List create(@NonNull Cursor cursor, String if (null != directory) { directoryPath = directory.getAbsolutePath(); if (directoryPathSet.add(directoryPath)) { - MediaBrowserCompat.MediaItem mediaItem = createFolderMediaItem(directory, mediaIdPrefix); + MediaItem mediaItem = createFolderMediaItem(directory, mediaIdPrefix); listToReturn.add(mediaItem); } } @@ -60,7 +60,7 @@ public MediaItemType getType() { } - private MediaBrowserCompat.MediaItem createFolderMediaItem(File folder, String parentId) { + private MediaItem createFolderMediaItem(File folder, String parentId) { /* append a file separator so that folders with an "extended" name are discarded... * e.g. Folder to accept: 'folder1' * Folder to reject: 'folder1extended' */ @@ -68,13 +68,13 @@ private MediaBrowserCompat.MediaItem createFolderMediaItem(File folder, String p return new MediaItemBuilder(filePath) .setMediaItemType(MediaItemType.FOLDER) .setLibraryId(buildLibraryId(parentId, filePath)) - .setFile(folder) + .setDirectoryFile(folder) .setFlags(FLAG_BROWSABLE) .build(); } @Override - public int compare(MediaBrowserCompat.MediaItem m1, MediaBrowserCompat.MediaItem m2) { + public int compare(MediaItem m1, MediaItem m2) { return caseSensitiveStringCompare(getDirectoryPath(m1), getDirectoryPath(m2)); } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/SongResultsParser.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/SongResultsParser.java index 1ba97dfff..2f6ba6601 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/SongResultsParser.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/parser/SongResultsParser.java @@ -55,8 +55,11 @@ private MediaItem buildMediaItem(@NonNull Cursor c, String libraryIdPrefix) { final String mediaId = c.getString(c.getColumnIndex(MediaStore.Audio.Media._ID)); final String mediaFilePath = c.getString(c.getColumnIndex(MediaStore.Audio.Media.DATA)); final File mediaFile = new File(mediaFilePath); + File directory = null; if (!mediaFile.exists()) { return null; + } else { + directory = mediaFile.getParentFile(); } final Uri mediaUri = Uri.fromFile(mediaFile); final long duration = c.getLong(c.getColumnIndex(MediaStore.Audio.Media.DURATION)); @@ -74,6 +77,7 @@ private MediaItem buildMediaItem(@NonNull Cursor c, String libraryIdPrefix) { .setLibraryId(buildLibraryId(libraryIdPrefix, mediaId)) .setDuration(duration) .setFileName(fileName) + .setDirectoryFile(directory) .setArtist(artist) .setMediaItemType(MediaItemType.SONG) .setFlags(FLAG_PLAYABLE) diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetriever.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetriever.java index 379d4adf0..873895b96 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetriever.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetriever.java @@ -3,61 +3,40 @@ import android.content.ContentResolver; import android.database.Cursor; import android.os.Handler; -import android.support.v4.media.MediaBrowserCompat; import android.support.v4.media.MediaBrowserCompat.MediaItem; -import androidx.annotation.NonNull; - +import com.github.goldy1992.mp3player.service.library.content.filter.ResultsFilter; import com.github.goldy1992.mp3player.service.library.content.parser.ResultsParser; import com.github.goldy1992.mp3player.service.library.content.request.ContentRequest; -import com.github.goldy1992.mp3player.service.library.search.SearchDao; -import com.github.goldy1992.mp3player.service.library.search.SearchEntity; -import java.util.ArrayList; import java.util.List; -public abstract class ContentResolverRetriever extends ContentRetriever { +public abstract class ContentResolverRetriever extends ContentRetriever { final ContentResolver contentResolver; final ResultsParser resultsParser; - final SearchDao dao; final Handler handler; + final ResultsFilter resultsFilter; - public ContentResolverRetriever(ContentResolver contentResolver, ResultsParser resultsParser, SearchDao dao, Handler handler) { + ContentResolverRetriever(ContentResolver contentResolver, + ResultsParser resultsParser, + Handler handler, + ResultsFilter resultsFilter) { super(); this.contentResolver = contentResolver; this.resultsParser = resultsParser; - this.dao = dao; this.handler = handler; + this.resultsFilter = resultsFilter; } abstract Cursor performGetChildrenQuery(String id); - void updateSearchDatabase(List results) { - if (isSearchable()) { - handler.post(() -> { - final int resultsSize = results.size(); - final int count = dao.getCount(); - - if (count != resultsSize) { // INSERT NORMALISED VALUES - List entries = new ArrayList<>(); - for (MediaBrowserCompat.MediaItem mediaItem : results) { - T entry = createFromMediaItem(mediaItem); - entries.add(entry); - } - dao.insertAll(entries); - } - }); - } - } + abstract String[] getProjection(); - abstract T createFromMediaItem(@NonNull MediaItem item); - abstract boolean isSearchable(); @Override public List getChildren(ContentRequest request) { Cursor cursor = performGetChildrenQuery(request.getQueryString()); - List results = resultsParser.create(cursor, request.getMediaIdPrefix()); - updateSearchDatabase(results); - return results; + List results = resultsParser.create(cursor, request.getMediaIdPrefix()); + return null != resultsFilter ? resultsFilter.filter(request.getQueryString(), results) : results; } } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/FoldersRetriever.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/FoldersRetriever.java index 7bf32f9bc..569590c5b 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/FoldersRetriever.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/FoldersRetriever.java @@ -4,15 +4,9 @@ import android.database.Cursor; import android.os.Handler; import android.provider.MediaStore; -import android.support.v4.media.MediaBrowserCompat.MediaItem; - -import androidx.annotation.NonNull; import com.github.goldy1992.mp3player.commons.MediaItemType; -import com.github.goldy1992.mp3player.commons.MediaItemUtils; import com.github.goldy1992.mp3player.service.library.content.parser.FolderResultsParser; -import com.github.goldy1992.mp3player.service.library.search.Folder; -import com.github.goldy1992.mp3player.service.library.search.FolderDao; import javax.inject.Inject; import javax.inject.Named; @@ -21,14 +15,13 @@ import static com.github.goldy1992.mp3player.service.library.content.Projections.FOLDER_PROJECTION; @Singleton -public class FoldersRetriever extends ContentResolverRetriever { +public class FoldersRetriever extends ContentResolverRetriever { @Inject public FoldersRetriever(ContentResolver contentResolver, FolderResultsParser resultsParser, - FolderDao folderDao, @Named("worker") Handler handler) { - super(contentResolver, resultsParser, folderDao, handler); + super(contentResolver, resultsParser, handler, null); } @Override @@ -43,21 +36,9 @@ Cursor performGetChildrenQuery(String id) { null, null, null); } - @Override public String[] getProjection() { return FOLDER_PROJECTION.toArray(new String[0]); } - @Override - Folder createFromMediaItem(@NonNull MediaItem item) { - final String id = MediaItemUtils.getDirectoryPath(item); - final String value = MediaItemUtils.getDirectoryName(item); - return new Folder(id, value); - } - - @Override - boolean isSearchable() { - return true; - } } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/MediaItemFromIdRetriever.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/MediaItemFromIdRetriever.java new file mode 100644 index 000000000..2112b76be --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/MediaItemFromIdRetriever.java @@ -0,0 +1,51 @@ +package com.github.goldy1992.mp3player.service.library.content.retriever; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.provider.MediaStore; +import android.support.v4.media.MediaBrowserCompat; + +import androidx.annotation.Nullable; + +import com.github.goldy1992.mp3player.service.library.content.parser.SongResultsParser; + +import org.apache.commons.collections4.CollectionUtils; + +import java.util.List; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import static android.provider.BaseColumns._ID; +import static com.github.goldy1992.mp3player.service.library.content.Projections.SONG_PROJECTION; + +@Singleton +public class MediaItemFromIdRetriever { + private static final String[] PROJECTION = SONG_PROJECTION.toArray(new String[0]); + private final ContentResolver contentResolver; + private final SongResultsParser songResultsParser; + + @Inject + public MediaItemFromIdRetriever(ContentResolver contentResolver, + SongResultsParser resultsParser) { + this.contentResolver = contentResolver; + this.songResultsParser = resultsParser; + } + + @Nullable + public MediaBrowserCompat.MediaItem getItem(long id) { + final String where = _ID + " = ?"; + final String[] whereArgs = {String.valueOf(id)}; + + Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + PROJECTION, where, whereArgs, null); + + if (null != cursor) { + List results = songResultsParser.create(cursor, ""); + if (CollectionUtils.isNotEmpty(results)) { + return results.get(0); + } + } + return null; + } +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetriever.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetriever.java index d33c732ef..d1fc009c6 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetriever.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetriever.java @@ -4,28 +4,27 @@ import android.database.Cursor; import android.os.Handler; import android.provider.MediaStore; -import android.support.v4.media.MediaBrowserCompat; - -import androidx.annotation.NonNull; import com.github.goldy1992.mp3player.commons.MediaItemType; +import com.github.goldy1992.mp3player.service.library.content.filter.SongsFromFolderResultsFilter; import com.github.goldy1992.mp3player.service.library.content.parser.SongResultsParser; -import com.github.goldy1992.mp3player.service.library.search.SearchDatabase; -import com.github.goldy1992.mp3player.service.library.search.Song; import javax.inject.Inject; import javax.inject.Named; +import static android.provider.MediaStore.MediaColumns.DATA; import static com.github.goldy1992.mp3player.service.library.content.Projections.SONG_PROJECTION; -public class SongsFromFolderRetriever extends ContentResolverRetriever { +public class SongsFromFolderRetriever extends ContentResolverRetriever { + + private static final String WHERE = DATA + " LIKE ? "; @Inject public SongsFromFolderRetriever(ContentResolver contentResolver, SongResultsParser resultsParser, - SearchDatabase searchDatabase, - @Named("worker") Handler handler) { - super(contentResolver, resultsParser, searchDatabase.songDao(), handler); + @Named("worker") Handler handler, + SongsFromFolderResultsFilter songsFromFolderResultsFilter) { + super(contentResolver, resultsParser, handler, songsFromFolderResultsFilter); } @Override @@ -35,10 +34,9 @@ public MediaItemType getType() { @Override Cursor performGetChildrenQuery(String id) { - String WHERE_CLAUSE = MediaStore.Audio.Media.DATA + " LIKE ? "; - String[] WHERE_ARGS = {id + "%"}; + String[] whereArgs = {id + "%"}; return contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI ,getProjection(), - WHERE_CLAUSE , WHERE_ARGS, null); + WHERE, whereArgs, null); } @Override @@ -46,13 +44,4 @@ String[] getProjection() { return SONG_PROJECTION.toArray(new String[0]); } - @Override - Song createFromMediaItem(@NonNull MediaBrowserCompat.MediaItem item) { - return null; - } - - @Override - boolean isSearchable() { - return false; - } } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetriever.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetriever.java index d9d214744..967e8f7ee 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetriever.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetriever.java @@ -4,15 +4,9 @@ import android.database.Cursor; import android.os.Handler; import android.provider.MediaStore; -import android.support.v4.media.MediaBrowserCompat.MediaItem; - -import androidx.annotation.NonNull; import com.github.goldy1992.mp3player.commons.MediaItemType; -import com.github.goldy1992.mp3player.commons.MediaItemUtils; import com.github.goldy1992.mp3player.service.library.content.parser.SongResultsParser; -import com.github.goldy1992.mp3player.service.library.search.Song; -import com.github.goldy1992.mp3player.service.library.search.SongDao; import javax.inject.Inject; import javax.inject.Named; @@ -21,14 +15,13 @@ import static com.github.goldy1992.mp3player.service.library.content.Projections.SONG_PROJECTION; @Singleton -public class SongsRetriever extends ContentResolverRetriever { +public class SongsRetriever extends ContentResolverRetriever { @Inject public SongsRetriever(ContentResolver contentResolver, SongResultsParser resultsParser, - SongDao songDao, @Named("worker") Handler handler) { - super(contentResolver, resultsParser, songDao, handler); + super(contentResolver, resultsParser, handler, null); } @Override @@ -42,22 +35,9 @@ Cursor performGetChildrenQuery(String id) { null, null, null); } - @Override public String[] getProjection() { return SONG_PROJECTION.toArray(new String[0]); } - @Override - Song createFromMediaItem(@NonNull MediaItem item) { - final String id = MediaItemUtils.getMediaId(item); - final String value = MediaItemUtils.getTitle(item); - return new Song(id, value); - } - - @Override - boolean isSearchable() { - return true; - } - } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentResolverSearcher.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentResolverSearcher.java index 7a9c27cab..80cc68cb5 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentResolverSearcher.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentResolverSearcher.java @@ -14,19 +14,22 @@ import java.util.Collections; import java.util.List; -public abstract class ContentResolverSearcher extends ContentSearcher { +public abstract class ContentResolverSearcher implements ContentSearcher { + final ContentResolver contentResolver; final ResultsParser resultsParser; final SearchDao searchDatabase; + final ResultsFilter resultsFilter; - public ContentResolverSearcher(ContentResolver contentResolver, + ContentResolverSearcher(ContentResolver contentResolver, ResultsParser resultsParser, ResultsFilter resultsFilter, SearchDao searchDatabase) { - super(resultsFilter); + super(); this.contentResolver = contentResolver; this.resultsParser = resultsParser; this.searchDatabase = searchDatabase; + this.resultsFilter = resultsFilter; } abstract String getIdPrefix(); @@ -42,12 +45,7 @@ public List search(@NonNull String query) { return Collections.emptyList(); } List results = resultsParser.create(cursor, getIdPrefix()); - if (isFilterable()) { - /* - keep in case we need to filter in the future. - */ - } - return results; + return null != resultsFilter ? resultsFilter.filter(query, results) : results; } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentSearcher.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentSearcher.java index f5fed5531..e1f1858f9 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentSearcher.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/ContentSearcher.java @@ -5,20 +5,12 @@ import androidx.annotation.NonNull; import com.github.goldy1992.mp3player.commons.MediaItemType; -import com.github.goldy1992.mp3player.service.library.content.filter.ResultsFilter; import java.util.List; -public abstract class ContentSearcher { +public interface ContentSearcher { - protected final ResultsFilter resultsFilter; - public abstract List search(@NonNull String query); - public abstract MediaItemType getSearchCategory(); + List search(@NonNull String query); + MediaItemType getSearchCategory(); - protected ContentSearcher(ResultsFilter resultsFilter) { - this.resultsFilter = resultsFilter; - } - public boolean isFilterable() { - return resultsFilter != null; - } } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcher.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcher.java index c52281985..98a10c81f 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcher.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcher.java @@ -8,7 +8,7 @@ import com.github.goldy1992.mp3player.commons.MediaItemType; import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; -import com.github.goldy1992.mp3player.service.library.content.filter.FoldersResultFilter; +import com.github.goldy1992.mp3player.service.library.content.filter.FolderSearchResultsFilter; import com.github.goldy1992.mp3player.service.library.content.parser.FolderResultsParser; import com.github.goldy1992.mp3player.service.library.search.Folder; import com.github.goldy1992.mp3player.service.library.search.FolderDao; @@ -30,10 +30,10 @@ public class FolderSearcher extends ContentResolverSearcher { @Inject public FolderSearcher(ContentResolver contentResolver, FolderResultsParser resultsParser, - FoldersResultFilter foldersResultFilter, + FolderSearchResultsFilter folderSearchResultsFilter, MediaItemTypeIds mediaItemTypeIds, FolderDao folderDao) { - super(contentResolver, resultsParser, foldersResultFilter, folderDao); + super(contentResolver, resultsParser, folderSearchResultsFilter, folderDao); this.mediaItemTypeIds = mediaItemTypeIds; } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/FolderDao.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/FolderDao.java index ab5fdb692..f615d1c16 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/FolderDao.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/FolderDao.java @@ -11,7 +11,7 @@ public interface FolderDao extends SearchDao { @Override - @Insert + @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(Folder folder); @Override @@ -20,7 +20,12 @@ public interface FolderDao extends SearchDao { @Override @Insert(onConflict = OnConflictStrategy.REPLACE) - public void insertAll(List folders); + void insertAll(List folders); + + @Override + @Query("DELETE FROM folders WHERE id NOT IN ( :ids )") + void deleteOld(List ids); + @Override @Query("SELECT * FROM folders WHERE value like '%' || :value || '%'") diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SearchDao.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SearchDao.java index b4412c109..6c333a040 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SearchDao.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SearchDao.java @@ -10,5 +10,7 @@ public interface SearchDao { void insertAll(List songs); + void deleteOld(List ids); + List query(String query); } diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SongDao.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SongDao.java index 567daec71..e84e746fb 100644 --- a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SongDao.java +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/SongDao.java @@ -11,7 +11,7 @@ public interface SongDao extends SearchDao { @Override - @Insert + @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(Song song); @Override @@ -22,6 +22,10 @@ public interface SongDao extends SearchDao { @Insert(onConflict = OnConflictStrategy.REPLACE) public void insertAll(List songs); + @Override + @Query("DELETE FROM songs WHERE id NOT IN ( :ids )") + void deleteOld(List ids); + @Override @Query("SELECT * FROM songs WHERE value like '%' || :value || '%'") List query(String value); diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/FolderDatabaseManager.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/FolderDatabaseManager.java new file mode 100644 index 000000000..882e69bb6 --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/FolderDatabaseManager.java @@ -0,0 +1,44 @@ +package com.github.goldy1992.mp3player.service.library.search.managers; + +import android.os.Handler; +import android.support.v4.media.MediaBrowserCompat; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.github.goldy1992.mp3player.commons.MediaItemType; +import com.github.goldy1992.mp3player.commons.MediaItemUtils; +import com.github.goldy1992.mp3player.service.library.ContentManager; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; +import com.github.goldy1992.mp3player.service.library.search.Folder; +import com.github.goldy1992.mp3player.service.library.search.SearchDatabase; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import static com.github.goldy1992.mp3player.commons.Normaliser.normalise; + +@Singleton +public class FolderDatabaseManager extends SearchDatabaseManager { + + @Inject + public FolderDatabaseManager(ContentManager contentManager, + @Named("worker") Handler handler, + MediaItemTypeIds mediaItemTypeIds, + SearchDatabase searchDatabase) { + super(contentManager, handler, searchDatabase.folderDao(), mediaItemTypeIds.getId(MediaItemType.FOLDERS)); + } + + @Override + @Nullable + Folder createFromMediaItem(@NonNull MediaBrowserCompat.MediaItem item) { + final String id = MediaItemUtils.getDirectoryPath(item); + final String value = MediaItemUtils.getDirectoryName(item); + + if (null != value) { + return new Folder(id, normalise(value)); + } + return null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManager.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManager.java new file mode 100644 index 000000000..e7dead556 --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManager.java @@ -0,0 +1,73 @@ +package com.github.goldy1992.mp3player.service.library.search.managers; + +import android.os.Handler; +import android.support.v4.media.MediaBrowserCompat.MediaItem; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.github.goldy1992.mp3player.service.library.ContentManager; +import com.github.goldy1992.mp3player.service.library.search.SearchDao; +import com.github.goldy1992.mp3player.service.library.search.SearchEntity; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Named; + +public abstract class SearchDatabaseManager { + + private final ContentManager contentManager; + private final Handler handler; + private final SearchDao dao; + private final String rootCategoryId; + + public SearchDatabaseManager(ContentManager contentManager, + @Named("worker") Handler handler, + SearchDao dao, + String rootCategoryId) { + this.contentManager = contentManager; + this.handler = handler; + this.dao = dao; + this.rootCategoryId = rootCategoryId; + } + + @Nullable + abstract T createFromMediaItem(@NonNull MediaItem item); + + public void insert(MediaItem item) { + T t = createFromMediaItem(item); + dao.insert(t); + } + + public void reindex() { + handler.post(() -> { + List results = contentManager.getChildren(rootCategoryId); + List entries = buildResults(results); + deleteOld(entries); + // replace any new entries + dao.insertAll(entries); + }); + } + + private void deleteOld(List entries) { + // Delete old entries i.e. files that have been deleted. + List ids = new ArrayList<>(); + for (T entry : entries) { + ids.add(entry.getId()); + } + // remove old entries + dao.deleteOld(ids); + } + + private List buildResults(List mediaItems) { + List entries = new ArrayList<>(); + for (MediaItem mediaItem : mediaItems) { + T entry = createFromMediaItem(mediaItem); + if (null != entry) { + entries.add(entry); + } + } + return entries; + } +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManagers.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManagers.java new file mode 100644 index 000000000..cadf4793b --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManagers.java @@ -0,0 +1,36 @@ +package com.github.goldy1992.mp3player.service.library.search.managers; + +import com.github.goldy1992.mp3player.commons.MediaItemType; + +import java.util.EnumMap; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class SearchDatabaseManagers { + + final EnumMap dbManagerMap; + + /** + * Constructor + * @param songDatabaseManager SongDatabaseManager + * @param folderDatabaseManager FolderDatabaseManager + */ + @Inject + public SearchDatabaseManagers(SongDatabaseManager songDatabaseManager, + FolderDatabaseManager folderDatabaseManager) { + this.dbManagerMap = new EnumMap<>(MediaItemType.class); + this.dbManagerMap.put(MediaItemType.SONGS, songDatabaseManager); + this.dbManagerMap.put(MediaItemType.FOLDERS, folderDatabaseManager); + } + + /** + * reindexes all of the search database tables. + */ + public void reindexAll() { + for (SearchDatabaseManager manager : dbManagerMap.values()) { + manager.reindex(); + } + } +} diff --git a/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SongDatabaseManager.java b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SongDatabaseManager.java new file mode 100644 index 000000000..8be91253f --- /dev/null +++ b/app/src/main/java/com/github/goldy1992/mp3player/service/library/search/managers/SongDatabaseManager.java @@ -0,0 +1,45 @@ +package com.github.goldy1992.mp3player.service.library.search.managers; + +import android.os.Handler; +import android.support.v4.media.MediaBrowserCompat; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.github.goldy1992.mp3player.commons.MediaItemType; +import com.github.goldy1992.mp3player.commons.MediaItemUtils; +import com.github.goldy1992.mp3player.service.library.ContentManager; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; +import com.github.goldy1992.mp3player.service.library.search.SearchDatabase; +import com.github.goldy1992.mp3player.service.library.search.Song; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import static com.github.goldy1992.mp3player.commons.Normaliser.normalise; + +@Singleton +public class SongDatabaseManager extends SearchDatabaseManager { + + @Inject + public SongDatabaseManager(ContentManager contentManager, + @Named("worker") Handler handler, + MediaItemTypeIds mediaItemTypeIds, + SearchDatabase searchDatabase) { + super(contentManager, handler, searchDatabase.songDao(), mediaItemTypeIds.getId(MediaItemType.SONGS)); + } + + @Override + @Nullable + Song createFromMediaItem(@NonNull MediaBrowserCompat.MediaItem item) { + + final String id = MediaItemUtils.getMediaId(item); + final String value = MediaItemUtils.getTitle(item); + + if (null != value) { + return new Song(id, normalise(value)); + } + return null; + } +} diff --git a/app/src/test/java/com/github/goldy1992/mp3player/client/activities/FolderActivityTest.java b/app/src/test/java/com/github/goldy1992/mp3player/client/activities/FolderActivityTest.java index 15e13de53..aa911db9b 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/client/activities/FolderActivityTest.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/client/activities/FolderActivityTest.java @@ -32,7 +32,7 @@ public void setup() { File folder = new File("/a/b/xyz"); MediaBrowserCompat.MediaItem mediaItem = new MediaItemBuilder("id") .setLibraryId("xyz") - .setFile(folder) + .setDirectoryFile(folder) .build(); intent.putExtra(MEDIA_ITEM, mediaItem); this.scenario = Robolectric.buildActivity(FolderActivityInjectorTestImpl.class, intent).setup(); diff --git a/app/src/test/java/com/github/goldy1992/mp3player/commons/MediaItemUtilsTest.java b/app/src/test/java/com/github/goldy1992/mp3player/commons/MediaItemUtilsTest.java index c97c08734..dc639faa9 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/commons/MediaItemUtilsTest.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/commons/MediaItemUtilsTest.java @@ -106,7 +106,7 @@ public void testGetDirectoryNameNull() { public void testGetDirectoryNameNotNull() { final String directoryName = "directoryName"; MediaItem mediaItem = new MediaItemBuilder("id") - .setFile(new File("/sdsad/" + directoryName )) + .setDirectoryFile(new File("/sdsad/" + directoryName )) .build(); assertEquals(directoryName, MediaItemUtils.getDirectoryName(mediaItem)); } diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/ContentManagerTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/ContentManagerTest.java index 207d59dbe..91b261176 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/service/library/ContentManagerTest.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/ContentManagerTest.java @@ -7,6 +7,7 @@ import com.github.goldy1992.mp3player.service.library.content.request.ContentRequest; import com.github.goldy1992.mp3player.service.library.content.request.ContentRequestParser; import com.github.goldy1992.mp3player.service.library.content.retriever.ContentRetriever; +import com.github.goldy1992.mp3player.service.library.content.retriever.MediaItemFromIdRetriever; import com.github.goldy1992.mp3player.service.library.content.retriever.RootRetriever; import com.github.goldy1992.mp3player.service.library.content.retriever.SongFromUriRetriever; import com.github.goldy1992.mp3player.service.library.content.searcher.ContentSearcher; @@ -52,6 +53,9 @@ public class ContentManagerTest { @Mock private MediaItem rootItem; + @Mock + private MediaItemFromIdRetriever mediaItemFromIdRetriever; + @Mock private SongFromUriRetriever songFromUriRetriever; @@ -65,10 +69,10 @@ public void setup() { this.contentManager = new ContentManager(contentRetrievers, contentSearchers, contentRequestParser, - songFromUriRetriever); + songFromUriRetriever, + mediaItemFromIdRetriever); } - @SuppressWarnings("unchecked") @Test public void testGetChildren() { final String contentRetrieverId = "id"; diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/FoldersResultFilterTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/FolderSearchResultsFilterTest.java similarity index 77% rename from app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/FoldersResultFilterTest.java rename to app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/FolderSearchResultsFilterTest.java index 8798eb349..44997cac2 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/FoldersResultFilterTest.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/FolderSearchResultsFilterTest.java @@ -17,13 +17,13 @@ import static org.junit.Assert.assertTrue; @RunWith(RobolectricTestRunner.class) -public class FoldersResultFilterTest { +public class FolderSearchResultsFilterTest { - private FoldersResultFilter foldersResultFilter; + private FolderSearchResultsFilter folderSearchResultsFilter; @Before public void setup() { - this.foldersResultFilter = new FoldersResultFilter(); + this.folderSearchResultsFilter = new FolderSearchResultsFilter(); } @Test @@ -32,23 +32,23 @@ public void testFilterTwoItems() { final int expectedResultsSize = 2; File file1ToKeep = new File("/a/b/abc101"); MediaItem item1Keep = new MediaItemBuilder("id") - .setFile(file1ToKeep) + .setDirectoryFile(file1ToKeep) .build(); File file2ToThrow = new File("/a/b/1ac101"); MediaItem item2Throw = new MediaItemBuilder("id") - .setFile(file2ToThrow) + .setDirectoryFile(file2ToThrow) .build(); File file3ToThrow = new File("/a/abc/101"); MediaItem item3Throw = new MediaItemBuilder("id") - .setFile(file3ToThrow) + .setDirectoryFile(file3ToThrow) .build(); File file4ToKeep = new File("/a/abc/abc10abc1"); MediaItem item4Keep = new MediaItemBuilder("id") - .setFile(file4ToKeep) + .setDirectoryFile(file4ToKeep) .build(); List resultsToProcess = new ArrayList<>(); @@ -57,7 +57,7 @@ public void testFilterTwoItems() { resultsToProcess.add(item3Throw); resultsToProcess.add(item4Keep); - List results = foldersResultFilter.filter(filterQuery, resultsToProcess); + List results = folderSearchResultsFilter.filter(filterQuery, resultsToProcess); assertEquals(expectedResultsSize, results.size()); assertTrue(results.contains(item1Keep)); assertTrue(results.contains(item4Keep)); diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/SongsFromFolderResultsFilterTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/SongsFromFolderResultsFilterTest.java new file mode 100644 index 000000000..e86b4ebd4 --- /dev/null +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/filter/SongsFromFolderResultsFilterTest.java @@ -0,0 +1,54 @@ +package com.github.goldy1992.mp3player.service.library.content.filter; + +import android.support.v4.media.MediaBrowserCompat; +import android.support.v4.media.MediaBrowserCompat.MediaItem; + +import com.github.goldy1992.mp3player.commons.MediaItemBuilder; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(RobolectricTestRunner.class) +public class SongsFromFolderResultsFilterTest { + + private SongsFromFolderResultsFilter songsFromFolderResultsFilter; + + @Before + public void setup() { + this.songsFromFolderResultsFilter = new SongsFromFolderResultsFilter(); + } + + @Test + public void testFilterValidQuery() { + final String query = "/a/b/c"; + final File expectedDirectory = new File(query); + + MediaItem dontFilter = new MediaItemBuilder("fds") + .setDirectoryFile(expectedDirectory) + .build(); + + MediaItem toFilter = new MediaItemBuilder("fds") + .setDirectoryFile(new File("/a/otherDir")) + .build(); + + List items = new ArrayList<>(); + items.add(dontFilter); + items.add(toFilter); + + List results = songsFromFolderResultsFilter.filter(query, items); + assertEquals(1, results.size()); + assertTrue(results.contains(dontFilter)); + assertFalse(results.contains(toFilter)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/observers/AudioObserverTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/observers/AudioObserverTest.java new file mode 100644 index 000000000..611132d41 --- /dev/null +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/observers/AudioObserverTest.java @@ -0,0 +1,110 @@ +package com.github.goldy1992.mp3player.service.library.content.observers; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.provider.MediaStore; +import android.support.v4.media.MediaBrowserCompat.MediaItem; + +import com.github.goldy1992.mp3player.commons.MediaItemBuilder; +import com.github.goldy1992.mp3player.commons.MediaItemType; +import com.github.goldy1992.mp3player.service.MediaPlaybackService; +import com.github.goldy1992.mp3player.service.library.ContentManager; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; +import com.github.goldy1992.mp3player.service.library.search.managers.FolderDatabaseManager; +import com.github.goldy1992.mp3player.service.library.search.managers.SongDatabaseManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +import java.io.File; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +public class AudioObserverTest { + + private AudioObserver audioObserver; + + private MediaItemTypeIds mediaItemTypeIds; + + @Mock + private ContentResolver contentResolver; + + @Mock + private ContentManager contentManager; + + @Mock + private SongDatabaseManager songDatabaseManager; + + @Mock + private FolderDatabaseManager folderDatabaseManager; + + @Mock + private MediaPlaybackService mediaPlaybackService; + + private Handler handler; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + this.handler = new Handler(Looper.getMainLooper()); + this.mediaItemTypeIds = new MediaItemTypeIds(); + this.audioObserver = new AudioObserver( + handler, + contentResolver, + contentManager, + songDatabaseManager, + folderDatabaseManager, + mediaItemTypeIds); + this.audioObserver.init(mediaPlaybackService); + } + + @Test + public void testNullUri() { + audioObserver.onChange(true); + verify(contentManager, never()).getItem(anyLong()); + } + + @Test + public void testOnChangeParsableUriValidIdNoContent() { + final long expectedId = 2334L; + Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + uri = ContentUris.withAppendedId(uri, expectedId); + when(contentManager.getItem(expectedId)).thenReturn(null); + this.audioObserver.onChange(true, uri); + verify(contentManager, times(1)).getItem(expectedId); + verify(songDatabaseManager, never()).insert(any(MediaItem.class)); + verify(folderDatabaseManager, never()).insert(any(MediaItem.class)); + } + + @Test + public void testOnChangeParsableUriWithValidId() { + final long expectedId = 2334L; + final File expectedDir = new File("/a/b/c"); + Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + uri = ContentUris.withAppendedId(uri, expectedId); + MediaItem result = new MediaItemBuilder("sf") + .setDirectoryFile(expectedDir) + .build(); + when(contentManager.getItem(expectedId)).thenReturn(result); + this.audioObserver.onChange(true, uri); + verify(contentManager, times(1)).getItem(expectedId); + verify(songDatabaseManager, times(1)).insert(result); + verify(folderDatabaseManager, times(1)).insert(result); + verify(mediaPlaybackService, times(1)).notifyChildrenChanged(expectedDir.getAbsolutePath()); + verify(mediaPlaybackService, times(1)).notifyChildrenChanged(mediaItemTypeIds.getId(MediaItemType.FOLDERS)); + verify(mediaPlaybackService, times(1)).notifyChildrenChanged(mediaItemTypeIds.getId(MediaItemType.SONGS)); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetrieverTestBase.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetrieverTestBase.java index 5d1a7a2fc..84767ae07 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetrieverTestBase.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/ContentResolverRetrieverTestBase.java @@ -7,7 +7,6 @@ import android.support.v4.media.MediaBrowserCompat.MediaItem; import com.github.goldy1992.mp3player.service.library.content.request.ContentRequest; -import com.github.goldy1992.mp3player.service.library.search.SearchDatabase; import org.mockito.Mock; @@ -21,9 +20,6 @@ public abstract class ContentResolverRetrieverTestBase { - @Mock - FolderDao folderDao; @Mock FolderResultsParser resultsParser; @@ -48,7 +43,7 @@ public class FoldersRetrieverTest extends ContentResolverRetrieverTestBase result = retriever.getChildren(contentRequest); @@ -79,13 +71,6 @@ public void testGetChildren() { // assert results are the expected ones assertEquals(expectedResult, result); - // verify database call - verify(folderDao, times(1)).insertAll(captor.capture()); - List folders = captor.getValue(); - assertEquals(1, folders.size()); - Folder folder = folders.get(0); - assertEquals(folder.getId(), directoryPath); - assertEquals(folder.getValue(), directoryName); } @Test diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/MediaItemFromIdRetrieverTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/MediaItemFromIdRetrieverTest.java new file mode 100644 index 000000000..13090a212 --- /dev/null +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/MediaItemFromIdRetrieverTest.java @@ -0,0 +1,69 @@ +package com.github.goldy1992.mp3player.service.library.content.retriever; + +import android.content.ContentResolver; +import android.database.Cursor; +import android.support.v4.media.MediaBrowserCompat.MediaItem; + +import com.github.goldy1992.mp3player.commons.MediaItemBuilder; +import com.github.goldy1992.mp3player.service.library.content.parser.SongResultsParser; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(RobolectricTestRunner.class) +public class MediaItemFromIdRetrieverTest { + + private MediaItemFromIdRetriever mediaItemFromIdRetriever; + + @Mock + private ContentResolver contentResolver; + + @Mock + SongResultsParser songResultsParser; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + this.mediaItemFromIdRetriever = new MediaItemFromIdRetriever(contentResolver, songResultsParser); + } + + @Test + public void testNullCursor() { + final long id = 23L; + when(contentResolver.query(any(), any(), any(), any(), any())).thenReturn(null); + MediaItem result = mediaItemFromIdRetriever.getItem(id); + assertNull(result); + verify(songResultsParser, never()).create(any(),any()); + } + + @Test + public void testGetItemWithResult() { + final long id = 5464L; + final Cursor cursor = mock(Cursor.class); + final MediaItem expectedMediaItem = new MediaItemBuilder("anId") + .build(); + final List listToReturn = Collections.singletonList(expectedMediaItem); + when(contentResolver.query(any(), any(), any(), any(), any())).thenReturn(cursor); + when(songResultsParser.create(eq(cursor), anyString())).thenReturn(listToReturn); + MediaItem result = mediaItemFromIdRetriever.getItem(id); + assertEquals(expectedMediaItem, result); + } + +} \ No newline at end of file diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetrieverTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetrieverTest.java index 0f0979506..0ae45f831 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetrieverTest.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsFromFolderRetrieverTest.java @@ -3,6 +3,7 @@ import android.support.v4.media.MediaBrowserCompat; import com.github.goldy1992.mp3player.commons.MediaItemBuilder; +import com.github.goldy1992.mp3player.service.library.content.filter.SongsFromFolderResultsFilter; import com.github.goldy1992.mp3player.service.library.content.parser.SongResultsParser; import com.github.goldy1992.mp3player.service.library.content.request.ContentRequest; import com.github.goldy1992.mp3player.service.library.search.SongDao; @@ -37,8 +38,7 @@ public class SongsFromFolderRetrieverTest extends ContentResolverRetrieverTestBa @Before public void setup() { MockitoAnnotations.initMocks(this); - when(searchDatabase.songDao()).thenReturn(songDao); - this.retriever = spy(new SongsFromFolderRetriever(contentResolver, resultsParser, searchDatabase, handler)); + this.retriever = spy(new SongsFromFolderRetriever(contentResolver, resultsParser, handler, new SongsFromFolderResultsFilter())); } @Test diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetrieverTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetrieverTest.java index d9a29ac9f..1233e90e8 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetrieverTest.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/retriever/SongsRetrieverTest.java @@ -6,7 +6,6 @@ import com.github.goldy1992.mp3player.service.library.content.parser.SongResultsParser; import com.github.goldy1992.mp3player.service.library.content.request.ContentRequest; import com.github.goldy1992.mp3player.service.library.search.Song; -import com.github.goldy1992.mp3player.service.library.search.SongDao; import org.junit.Before; import org.junit.Test; @@ -24,17 +23,12 @@ import static com.github.goldy1992.mp3player.commons.MediaItemType.SONG; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; @RunWith(RobolectricTestRunner.class) public class SongsRetrieverTest extends ContentResolverRetrieverTestBase { - @Mock - SongDao songDao; - @Mock SongResultsParser resultsParser; @@ -44,7 +38,7 @@ public class SongsRetrieverTest extends ContentResolverRetrieverTestBase result = retriever.getChildren(contentRequest); @@ -71,13 +60,6 @@ public void testGetChildren() { // assert results are the expected ones assertEquals(expectedResult, result); - // verify database call - verify(songDao, times(1)).insertAll(captor.capture()); - List songs = captor.getValue(); - assertEquals(1, songs.size()); - Song song = songs.get(0); - assertEquals(song.getId(), id); - assertEquals(song.getValue(), title); } @Test diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcherTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcherTest.java index 4467a8db3..e063fb46f 100644 --- a/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcherTest.java +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/content/searcher/FolderSearcherTest.java @@ -5,7 +5,7 @@ import com.github.goldy1992.mp3player.commons.MediaItemType; import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; -import com.github.goldy1992.mp3player.service.library.content.filter.FoldersResultFilter; +import com.github.goldy1992.mp3player.service.library.content.filter.FolderSearchResultsFilter; import com.github.goldy1992.mp3player.service.library.content.parser.FolderResultsParser; import com.github.goldy1992.mp3player.service.library.search.Folder; import com.github.goldy1992.mp3player.service.library.search.FolderDao; @@ -29,7 +29,7 @@ @RunWith(RobolectricTestRunner.class) public class FolderSearcherTest extends ContentResolverSearcherTestBase { - private FoldersResultFilter filter; + private FolderSearchResultsFilter filter; @Mock FolderResultsParser resultsParser; @@ -44,7 +44,7 @@ public void setup() { MockitoAnnotations.initMocks(this); this.mediaItemTypeIds = new MediaItemTypeIds(); this.idPrefix = mediaItemTypeIds.getId(MediaItemType.FOLDER); - this.filter = mock(FoldersResultFilter.class); + this.filter = mock(FolderSearchResultsFilter.class); when(filter.filter(VALID_QUERY, expectedResult)).thenReturn(expectedResult); this.searcher = spy(new FolderSearcher(contentResolver, resultsParser, filter, mediaItemTypeIds, folderDao)); } diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/FolderDatabaseManagerTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/FolderDatabaseManagerTest.java new file mode 100644 index 000000000..4af35efed --- /dev/null +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/FolderDatabaseManagerTest.java @@ -0,0 +1,120 @@ +package com.github.goldy1992.mp3player.service.library.search.managers; + + +import android.support.v4.media.MediaBrowserCompat; + +import com.github.goldy1992.mp3player.commons.MediaItemBuilder; +import com.github.goldy1992.mp3player.commons.MediaItemType; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; +import com.github.goldy1992.mp3player.service.library.search.Folder; +import com.github.goldy1992.mp3player.service.library.search.FolderDao; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.LooperMode; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; + +@LooperMode(LooperMode.Mode.PAUSED) +@RunWith(RobolectricTestRunner.class) +public class FolderDatabaseManagerTest extends SearchDatabaseManagerTestBase { + + private FolderDatabaseManager folderDatabaseManager; + + private static final String TEST_DIRECTORY_NAME = "fileName"; + + private static final String EXPECTED_DIRECTORY_NAME = TEST_DIRECTORY_NAME.toUpperCase(); + + private static final String TEST_DIRECTORY_PATH = File.separator + + "a" + File.separator + + "b" + File.separator + + TEST_DIRECTORY_NAME; + + private static final File TEST_FILE = new File(TEST_DIRECTORY_PATH); + + @Captor + ArgumentCaptor folderCaptor; + + @Captor + ArgumentCaptor> deleteCaptor; + + @Captor + ArgumentCaptor> insertAllCaptor; + + + @Mock + private FolderDao folderDao; + + + + + @Before + public void setup() { + super.setup(); + MockitoAnnotations.initMocks(this); + when(searchDatabase.folderDao()).thenReturn(folderDao); + this.mediaItemTypeIds = new MediaItemTypeIds(); + this.folderDatabaseManager = new FolderDatabaseManager( + contentManager, + handler, + mediaItemTypeIds, + searchDatabase); + } + + @Override + @Test + public void testInsert() { + + + final String expectedId = TEST_FILE.getAbsolutePath(); + MediaBrowserCompat.MediaItem mediaItem = new MediaItemBuilder(expectedId) + .setDirectoryFile(TEST_FILE) + .build(); + folderDatabaseManager.insert(mediaItem); + verify(folderDao, times(1)).insert(folderCaptor.capture()); + Folder folder = folderCaptor.getValue(); + assertEquals(expectedId, folder.getId()); + assertEquals(EXPECTED_DIRECTORY_NAME, folder.getValue()); + } + + @Override + @Test + public void testReindex() { + final String expectedId = TEST_FILE.getAbsolutePath(); + MediaBrowserCompat.MediaItem mediaItem = new MediaItemBuilder(expectedId) + .setDirectoryFile(TEST_FILE) + .build(); + + MediaBrowserCompat.MediaItem toReturn = new MediaItemBuilder(expectedId) + .setDirectoryFile(TEST_FILE) + .build(); + when(contentManager.getChildren(mediaItemTypeIds.getId(MediaItemType.FOLDERS))) + .thenReturn(Collections.singletonList(toReturn)); + + folderDatabaseManager.reindex(); + shadowOf(handler.getLooper()).idle(); + + verify(folderDao, times(1)).deleteOld(deleteCaptor.capture()); + List idsToDelete = deleteCaptor.getValue(); + assertEquals(expectedId, idsToDelete.get(0)); + + verify(folderDao, times(1)).insertAll(insertAllCaptor.capture()); + Folder insertedFolder = insertAllCaptor.getValue().get(0); + assertEquals(expectedId, insertedFolder.getId()); + assertEquals(EXPECTED_DIRECTORY_NAME, insertedFolder.getValue()); + } +} \ No newline at end of file diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManagerTestBase.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManagerTestBase.java new file mode 100644 index 000000000..bb458173d --- /dev/null +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/SearchDatabaseManagerTestBase.java @@ -0,0 +1,31 @@ +package com.github.goldy1992.mp3player.service.library.search.managers; + +import android.os.Handler; + +import com.github.goldy1992.mp3player.service.library.ContentManager; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; +import com.github.goldy1992.mp3player.service.library.search.SearchDatabase; + +import org.mockito.Mock; + +public abstract class SearchDatabaseManagerTestBase { + + @Mock + ContentManager contentManager; + + Handler handler; + + @Mock + SearchDatabase searchDatabase; + + MediaItemTypeIds mediaItemTypeIds; + + + public void setup() { + this.handler = new Handler(); + } + + public abstract void testInsert(); + + public abstract void testReindex(); +} diff --git a/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/SongDatabaseManagerTest.java b/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/SongDatabaseManagerTest.java new file mode 100644 index 000000000..869ca0be5 --- /dev/null +++ b/app/src/test/java/com/github/goldy1992/mp3player/service/library/search/managers/SongDatabaseManagerTest.java @@ -0,0 +1,105 @@ +package com.github.goldy1992.mp3player.service.library.search.managers; + +import android.support.v4.media.MediaBrowserCompat; + +import com.github.goldy1992.mp3player.commons.MediaItemBuilder; +import com.github.goldy1992.mp3player.commons.MediaItemType; +import com.github.goldy1992.mp3player.service.library.MediaItemTypeIds; +import com.github.goldy1992.mp3player.service.library.search.Song; +import com.github.goldy1992.mp3player.service.library.search.SongDao; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.LooperMode; + +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.robolectric.Shadows.shadowOf; + +@LooperMode(LooperMode.Mode.PAUSED) +@RunWith(RobolectricTestRunner.class) +public class SongDatabaseManagerTest extends SearchDatabaseManagerTestBase { + + private SongDatabaseManager songDatabaseManager; + + @Captor + ArgumentCaptor songCaptor; + + @Captor + ArgumentCaptor> deleteCaptor; + + @Captor + ArgumentCaptor> insertAllCaptor; + + @Mock + private SongDao songDao; + + + @Before + public void setup() { + super.setup(); + MockitoAnnotations.initMocks(this); + when(searchDatabase.songDao()).thenReturn(songDao); + this.mediaItemTypeIds = new MediaItemTypeIds(); + this.songDatabaseManager = new SongDatabaseManager( + contentManager, + handler, + mediaItemTypeIds, + searchDatabase); + } + + @Override + @Test + public void testInsert() { + final String expectedId = "23fsdf"; + final String songTitle = "songTitle"; + final String expectedValue = songTitle.toUpperCase(); + + MediaBrowserCompat.MediaItem mediaItem = new MediaItemBuilder(expectedId) + .setTitle(expectedValue) + .build(); + songDatabaseManager.insert(mediaItem); + verify(songDao, times(1)).insert(songCaptor.capture()); + Song song = songCaptor.getValue(); + assertEquals(expectedId, song.getId()); + assertEquals(expectedValue, song.getValue()); + } + + @Test + @Override + public void testReindex() { + final String expectedId = "sdkjdsf"; + final String title = "expectedTitle"; + final String expectedTitle = title.toUpperCase(); + + MediaBrowserCompat.MediaItem toReturn = new MediaItemBuilder(expectedId) + .setTitle(title) + .build(); + + when(contentManager.getChildren(mediaItemTypeIds.getId(MediaItemType.SONGS))) + .thenReturn(Collections.singletonList(toReturn)); + + songDatabaseManager.reindex(); + shadowOf(handler.getLooper()).idle(); + + verify(songDao, times(1)).deleteOld(deleteCaptor.capture()); + List idsToDelete = deleteCaptor.getValue(); + assertEquals(expectedId, idsToDelete.get(0)); + + verify(songDao, times(1)).insertAll(insertAllCaptor.capture()); + Song insertedFolder = insertAllCaptor.getValue().get(0); + assertEquals(expectedId, insertedFolder.getId()); + assertEquals(expectedTitle, insertedFolder.getValue()); + } +} \ No newline at end of file