diff --git a/app/src/main/java/de/arcus/playmusicexporter2/TrackListActivity.java b/app/src/main/java/de/arcus/playmusicexporter2/TrackListActivity.java index 3536881..0de25f0 100644 --- a/app/src/main/java/de/arcus/playmusicexporter2/TrackListActivity.java +++ b/app/src/main/java/de/arcus/playmusicexporter2/TrackListActivity.java @@ -33,14 +33,17 @@ import java.util.List; import de.arcus.framework.logger.Logger; import de.arcus.framework.crashhandler.CrashHandler; import de.arcus.framework.superuser.SuperUser; +import de.arcus.framework.utils.FileTools; import de.arcus.playmusiclib.PlayMusicManager; import de.arcus.playmusiclib.datasources.AlbumDataSource; import de.arcus.playmusiclib.datasources.MusicTrackDataSource; +import de.arcus.playmusiclib.datasources.PlaylistDataSource; import de.arcus.playmusiclib.exceptions.CouldNotOpenDatabase; import de.arcus.playmusiclib.exceptions.NoSuperUserException; import de.arcus.playmusiclib.exceptions.PlayMusicNotFound; import de.arcus.playmusiclib.items.Album; import de.arcus.playmusiclib.items.MusicTrack; +import de.arcus.playmusiclib.items.Playlist; /** * An activity representing a list of Tracks. This activity @@ -106,10 +109,14 @@ public class TrackListActivity extends ActionBarActivity playMusicManager.setOfflineOnly(true); AlbumDataSource albumDataSource = new AlbumDataSource(playMusicManager); - albumDataSource.setSerchKey("A bird story"); + PlaylistDataSource playlistDataSource = new PlaylistDataSource(playMusicManager); + + albumDataSource.setSerchKey("Ed Sheeran"); + playlistDataSource.setSerchKey("Playlist 1"); // Load all albums List albums = albumDataSource.getAll(); + List playlists = playlistDataSource.getAll(); if (albums.size() > 0) { // Gets the first album @@ -129,6 +136,14 @@ public class TrackListActivity extends ActionBarActivity } } + if (playlists.size() > 0) { + Playlist playlist = playlists.get(0); + + List musicTracks = playlist.getMusicTrackList(); + + Log.d("Debug", "Breakpoint"); + } + } catch (PlayMusicNotFound playMusicNotFound) { playMusicNotFound.printStackTrace(); } catch (NoSuperUserException e) { diff --git a/framework/src/main/java/de/arcus/framework/utils/FileTools.java b/framework/src/main/java/de/arcus/framework/utils/FileTools.java new file mode 100644 index 0000000..6b09cc9 --- /dev/null +++ b/framework/src/main/java/de/arcus/framework/utils/FileTools.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2015 David Schulte + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.arcus.framework.utils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import de.arcus.framework.logger.Logger; + +/** + * Help function for files + */ +public class FileTools { + /** + * Private constructor + */ + private FileTools() {} + + /** + * Creates a directory if it not exists + * @param dir Directory path + * @return Returns true if the directory was created or already exists + */ + public static boolean directoryCreate(String dir) { + File fileDirectory = new File(dir); + try { + if (!fileDirectory.exists()) { + Logger.getInstance().logVerbose("DirectoryCreate", "Create directory: " + dir); + + // Creates the directory + if (fileDirectory.mkdirs()) + return true; + else + Logger.getInstance().logWarning("DirectoryCreate", "MkDir failed"); + } else { + // Directory exists + Logger.getInstance().logDebug("DirectoryCreate", "Directory already exists"); + + return true; + } + } catch (Exception e) { + // Failed + Logger.getInstance().logError("DirectoryCreate", "Failed: " + e.getMessage()); + } + return false; + } + + /** + * Checks if the directory exists + * @param dir Path of the file + * @return Return whether the directory exists + */ + public static boolean directoryExists(String dir) { + File tmp = new File(dir); + + // Checks whether the directory exists and whether it is a directory + return (tmp.isDirectory() && tmp.exists()); + } + + /** + * Creates an empty file + * @param file File path + * @return Returns true if the file was successfully created + */ + public static boolean fileCreate(String file) { + Logger.getInstance().logVerbose("FileCreate", "File: " + file); + + try { + // Create the file + return (new File(file)).createNewFile(); + } catch (IOException e) { + // Failed + Logger.getInstance().logError("FileCreate", "Could not create file: " + e.getMessage()); + + return false; + } + } + + /** + * Moves a file + * @param src Soruce path + * @param dest Destination path + * @return Return whether the moving was successful + */ + public static boolean fileMove(String src, String dest) { + Logger.getInstance().logVerbose("FileMove", "From " + src + " to " + dest); + + File fileSrc = new File(src); + File fileDest = new File(dest); + + // Move the file + return fileSrc.renameTo(fileDest); + } + + /** + * Deletes a file + * @param file Path of the file + * @return Returns whether the deleting was successful + */ + public static boolean fileDelete(String file) { + // Delete the file + return (new File(file)).delete(); + } + + /** + * Checks if the file exists + * @param file Path of the file + * @return Return whether the file exists + */ + public static boolean fileExists(String file) { + File tmp = new File(file); + + // Checks whether the file exists and whether it is a file + return (tmp.isFile() && tmp.exists()); + } + + /** + * Checks whether the file or directory is a link + * @param path Path of the file / directory + * @return Returns whether the file or directory is a link + */ + public static boolean pathIsSymbolicLink(String path) { + File file = new File(path); + + try { + // Checks whether the file / directory is a symbolic link + return (file.getAbsolutePath() == file.getCanonicalPath()); + } catch (IOException e) { + e.printStackTrace(); + } + + return false; + } + + /** + * Gets the root canonical file of a symbolic link + * @param path The path + * @return The root file + */ + public static File getRootCanonicalFile(String path) { + return getRootCanonicalFile(new File(path)); + } + + /** + * Gets the root canonical file of a symbolic link + * @param file The file + * @return The root file + */ + public static File getRootCanonicalFile(File file) { + try { + // Gets the canonical file + File canonicalFile = file.getCanonicalFile(); + + // Differences between the canonical and the absolute file + while (!file.getAbsolutePath().equals(canonicalFile.getAbsolutePath())) { + file = canonicalFile; + + // Go deeper + canonicalFile = file.getCanonicalFile(); + } + } catch (IOException e) { + // Failed + e.printStackTrace(); + } + + return file; + } + + /** + * Gets all storages; eg. all sdcards + * @return List of all storages + */ + public static String[] getStorages() { + List storages = new ArrayList<>(); + + // Hard coded mount points + final String[] mountPointBlacklist = new String[] { "/mnt/tmp", "/mnt/factory", "/mnt/obb", "/mnt/asec", "/mnt/secure", "/mnt/media_rw", "/mnt/shell" }; + final String[] mountPointDirectories = new String[] { "/mnt", "/storage" }; + final String[] mountPoints = new String[] { "/sdcard", "/external_sd" }; + + + // Adds all mount point directories + for(String mountPointDirectory : mountPointDirectories) { + // Checks all subdirectories + File dir = getRootCanonicalFile(mountPointDirectory); + if (dir.exists() && dir.isDirectory()) { + File[] files = dir.listFiles(); + if (files != null) { + for (File subDir : files) { + subDir = getRootCanonicalFile(subDir); + // Is directory + if (subDir.isDirectory()) { + // Add mount point to list + if (!storages.contains(subDir.getAbsolutePath())) + storages.add(subDir.getAbsolutePath()); + } + } + } + } + } + + // Adds all direct moint points + for(String mointPoint : mountPoints) { + File file = getRootCanonicalFile(mointPoint); + if (file.isDirectory()) { + if (!storages.contains(file.getAbsolutePath())) + storages.add(file.getAbsolutePath()); + } + } + + // Remove all blacklisted paths + for (String blacklistPath : mountPointBlacklist) { + storages.remove(blacklistPath); + } + + // Returns the array + return storages.toArray(new String[storages.size()]); + } +} diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java index a2d772b..9dea640 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java @@ -29,8 +29,12 @@ import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.text.TextUtils; +import java.util.ArrayList; +import java.util.List; + import de.arcus.framework.superuser.SuperUser; import de.arcus.framework.superuser.SuperUserTools; +import de.arcus.framework.utils.FileTools; import de.arcus.playmusiclib.exceptions.CouldNotOpenDatabase; import de.arcus.playmusiclib.exceptions.NoSuperUserException; import de.arcus.playmusiclib.exceptions.PlayMusicNotFound; @@ -137,7 +141,10 @@ public class PlayMusicManager { /** - * Loads all needed information + * Loads all needed information and opens the database + * @throws PlayMusicNotFound PlayMusic is not installed + * @throws NoSuperUserException No super user permissions + * @throws CouldNotOpenDatabase Could not open the database */ public void startUp() throws PlayMusicNotFound, NoSuperUserException, CouldNotOpenDatabase { // Gets the package manager @@ -151,29 +158,59 @@ public class PlayMusicManager { throw new PlayMusicNotFound(); } + // Path to the private data mPathPrivateData = mPlayMusicApplicationInfo.dataDir; - mPathPublicData = new String[] {}; // TODO: Get sdcards + List publicDataList = new ArrayList<>(); + // Search on all sdcards + for (String storage : FileTools.getStorages()) { + String publicData = storage + "/Android/data/com.google.android.music"; + + // Directory exists + if (FileTools.directoryExists(publicData)) + publicDataList.add(publicData); + } + // Convert to array + mPathPublicData = publicDataList.toArray(new String[publicDataList.size()]); + + // Loads the database + loadDatabase(); + } + + /** + * Copies the database to a temp directory and opens it + * @throws NoSuperUserException No super user permissions + * @throws CouldNotOpenDatabase Could not open the database + */ + private void loadDatabase() throws NoSuperUserException, CouldNotOpenDatabase { // Ask for super user if (!SuperUser.askForPermissions()) throw new NoSuperUserException(); + // Close the database + closeDatabase(); + // Copy the database to the temp folder if (!SuperUserTools.fileCopy(getDatabasePath(), getTempDatabasePath())) throw new CouldNotOpenDatabase(); // Opens the database try { - // Close the database - closeDatabase(); - mDatabase = SQLiteDatabase.openDatabase(getTempDatabasePath(), null, SQLiteDatabase.OPEN_READONLY); } catch (SQLException e) { throw new CouldNotOpenDatabase(); } } + /** + * Reloads the database from playmusic + * @throws NoSuperUserException No super user permissions + * @throws CouldNotOpenDatabase Could not open the database + */ + public void realoadDatabase() throws NoSuperUserException, CouldNotOpenDatabase { + loadDatabase(); + } /** * Closes the database if it's open @@ -205,6 +242,13 @@ public class PlayMusicManager { // Music file exists if (SuperUserTools.fileExists(path)) return path; + // Search in the public data + for (String publicData : mPathPublicData) { + path = publicData + "/files/music/" + localCopyPath; + + if (FileTools.fileExists(path)) return path; + } + return null; } @@ -224,11 +268,18 @@ public class PlayMusicManager { // Artwork path is empty if (TextUtils.isEmpty(artworkPath)) return null; - // Private music path + // Private artwork path String path = getPrivateFilesPath() + "/" + artworkPath; - // Music file exists + // Artwork file exists if (SuperUserTools.fileExists(path)) return path; + // Search in the public data + for (String publicData : mPathPublicData) { + path = publicData + "/files/" + artworkPath; + + if (FileTools.fileExists(path)) return path; + } + return null; } diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/AlbumDataSource.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/AlbumDataSource.java index 440f9ee..de345a7 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/AlbumDataSource.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/AlbumDataSource.java @@ -23,6 +23,7 @@ package de.arcus.playmusiclib.datasources; import android.database.Cursor; +import android.database.DatabaseUtils; import android.text.TextUtils; import java.util.List; @@ -34,16 +35,19 @@ import de.arcus.playmusiclib.items.Album; * Data source for albums */ public class AlbumDataSource extends DataSource { + // Tables private final static String TABLE_MUSIC = "MUSIC"; - private final static String COLUMN_ALBUMID = "AlbumId"; - private final static String COLUMN_ALBUM = "Album"; - private final static String COLUMN_ALBUMARTIST = "AlbumArtist"; - private final static String COLUMN_ALBUM_ARTWORKFILE = "(SELECT ARTWORK_CACHE.LocalLocation FROM MUSIC AS MUSIC2 LEFT JOIN ARTWORK_CACHE ON MUSIC2.AlbumArtLocation = ARTWORK_CACHE.RemoteLocation WHERE MUSIC2.AlbumID = MUSIC.AlbumID AND ARTWORK_CACHE.RemoteLocation IS NOT NULL LIMIT 1) AS ArtistArtworkPath"; + // All fields + private final static String COLUMN_ALBUMID = "MUSIC.AlbumId"; + private final static String COLUMN_ALBUM = "MUSIC.Album"; + private final static String COLUMN_ALBUMARTIST = "MUSIC.AlbumArtist"; + private final static String COLUMN_ALBUM_ARTWORKFILE = "(SELECT ARTWORK_CACHE.LocalLocation FROM MUSIC AS MUSIC2 LEFT JOIN ARTWORK_CACHE ON MUSIC2.AlbumArtLocation = ARTWORK_CACHE.RemoteLocation WHERE MUSIC2.AlbumID = MUSIC.AlbumID AND ARTWORK_CACHE.RemoteLocation IS NOT NULL LIMIT 1) AS ArtistArtworkPath"; - private final static String COLUMN_TITLE = "Title"; - private final static String COLUMN_ARTIST = "Artist"; + private final static String COLUMN_TITLE = "MUSIC.Title"; + private final static String COLUMN_ARTIST = "MUSIC.Artist"; + // All columns private final static String[] COLUMNS_ALL = { COLUMN_ALBUMID, COLUMN_ALBUM, COLUMN_ALBUMARTIST, COLUMN_ALBUM_ARTWORKFILE}; @@ -102,28 +106,25 @@ public class AlbumDataSource extends DataSource { * @return The new where command */ private String prepareWhere(String where) { - // The new where - String newWhere = "LocalCopyType != 300"; + // Ignore non-PlayMusic tracks + where = combineWhere(where, "LocalCopyType != 300"); // Loads only offline tracks if (mOfflineOnly) - newWhere += " AND LocalCopyPath IS NOT NULL"; + where = combineWhere(where, "LocalCopyPath IS NOT NULL"); // Search only items which contains the key if (!TextUtils.isEmpty(mSearchKey)) { - String searchKey = mSearchKey.replace("'", "''"); + String searchKey = DatabaseUtils.sqlEscapeString("%" + mSearchKey + "%"); - newWhere += " AND (" + COLUMN_ALBUM + " LIKE '%" + searchKey + "%'"; - newWhere += " OR " + COLUMN_TITLE + " LIKE '%" + searchKey + "%'"; - newWhere += " OR " + COLUMN_ALBUMARTIST + " LIKE '%" + searchKey + "%'"; - newWhere += " OR " + COLUMN_ARTIST + " LIKE '%" + searchKey + "%')"; + String searchWhere = COLUMN_ALBUM + " LIKE " + searchKey; + searchWhere += " OR " + COLUMN_TITLE + " LIKE " + searchKey; + searchWhere += " OR " + COLUMN_ALBUMARTIST + " LIKE " + searchKey; + searchWhere += " OR " + COLUMN_ARTIST + " LIKE " + searchKey; + + where = combineWhere(where, searchWhere); } - // Adds an 'and' if needed - if (!TextUtils.isEmpty(where)) where = "(" + where + ") AND "; - - where += newWhere; - return where; } @@ -151,7 +152,7 @@ public class AlbumDataSource extends DataSource { * @return Returns the album or null */ public Album getById(long id) { - return getItem(TABLE_MUSIC, COLUMNS_ALL, prepareWhere("AlbumID = " + id)); + return getItem(TABLE_MUSIC, COLUMNS_ALL, prepareWhere(COLUMN_ALBUMID + " = " + id)); } /** diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/DataSource.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/DataSource.java index 17d8a6a..9e4bbc6 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/DataSource.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/DataSource.java @@ -24,6 +24,7 @@ package de.arcus.playmusiclib.datasources; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; +import android.text.TextUtils; import java.util.LinkedList; import java.util.List; @@ -150,4 +151,38 @@ public abstract class DataSource { else return null; } + + /** + * Combines two SQL where commands with an AND operator + * @param whereA Where command A + * @param whereB Where command B + * @return Returns a combined where command + */ + protected static String combineWhere(String whereA, String whereB) { + return combineWhere(whereA, whereB, "AND"); + } + + /** + * Combines two SQL where commands + * @param whereA Where command A + * @param whereB Where command B + * @param operator The operator word to use (AND or OR) + * @return Returns a combined where command + */ + protected static String combineWhere(String whereA, String whereB, String operator) { + // Combine both + if (!TextUtils.isEmpty(whereA) && !TextUtils.isEmpty(whereB)) + return "((" + whereA + ") " + operator + " (" + whereB + "))"; + + // Use only whereA + if (!TextUtils.isEmpty(whereA) && TextUtils.isEmpty(whereB)) + return whereA; + + // Use only whereB + if (TextUtils.isEmpty(whereA) && !TextUtils.isEmpty(whereB)) + return whereB; + + // No where is set + return ""; + } } diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/MusicTrackDataSource.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/MusicTrackDataSource.java index bc57599..809e6d3 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/MusicTrackDataSource.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/MusicTrackDataSource.java @@ -23,6 +23,7 @@ package de.arcus.playmusiclib.datasources; import android.database.Cursor; +import android.database.DatabaseUtils; import android.text.TextUtils; import java.util.List; @@ -41,24 +42,24 @@ public class MusicTrackDataSource extends DataSource { private final static String TABLE_MUSIC_PLAYLIST = "MUSIC LEFT JOIN LISTITEMS ON MUSIC.ID = LISTITEMS.MusicID"; // All fields - private final static String COLUMN_ID = "Id"; - private final static String COLUMN_SIZE = "Size"; - private final static String COLUMN_LOCALCOPYPATH = "LocalCopyPath"; - private final static String COLUMN_LOCALCOPYTYPE = "LocalCopyType"; - private final static String COLUMN_LOCALCOPYSTORAGETYPE = "LocalCopyStorageType"; - private final static String COLUMN_TITLE = "Title"; - private final static String COLUMN_ARTIST = "Artist"; - private final static String COLUMN_ALBUMARTIST = "AlbumArtist"; - private final static String COLUMN_ALBUM = "Album"; - private final static String COLUMN_GENRE = "Genre"; - private final static String COLUMN_YEAR = "Year"; - private final static String COLUMN_TRACKNUMBER = "TrackNumber"; - private final static String COLUMN_DISCNUMBER = "DiscNumber"; - private final static String COLUMN_DURATION = "Duration"; - private final static String COLUMN_ALBUMID = "AlbumId"; - private final static String COLUMN_CLIENTID = "ClientId"; - private final static String COLUMN_SOURCEID = "SourceId"; - private final static String COLUMN_CPDATA = "CpData"; + private final static String COLUMN_ID = "MUSIC.Id"; + private final static String COLUMN_SIZE = "MUSIC.Size"; + private final static String COLUMN_LOCALCOPYPATH = "MUSIC.LocalCopyPath"; + private final static String COLUMN_LOCALCOPYTYPE = "MUSIC.LocalCopyType"; + private final static String COLUMN_LOCALCOPYSTORAGETYPE = "MUSIC.LocalCopyStorageType"; + private final static String COLUMN_TITLE = "MUSIC.Title"; + private final static String COLUMN_ARTIST = "MUSIC.Artist"; + private final static String COLUMN_ALBUMARTIST = "MUSIC.AlbumArtist"; + private final static String COLUMN_ALBUM = "MUSIC.Album"; + private final static String COLUMN_GENRE = "MUSIC.Genre"; + private final static String COLUMN_YEAR = "MUSIC.Year"; + private final static String COLUMN_TRACKNUMBER = "MUSIC.TrackNumber"; + private final static String COLUMN_DISCNUMBER = "MUSIC.DiscNumber"; + private final static String COLUMN_DURATION = "MUSIC.Duration"; + private final static String COLUMN_ALBUMID = "MUSIC.AlbumId"; + private final static String COLUMN_CLIENTID = "MUSIC.ClientId"; + private final static String COLUMN_SOURCEID = "MUSIC.SourceId"; + private final static String COLUMN_CPDATA = "MUSIC.CpData"; private final static String COLUMN_ARTWORKFILE = "(SELECT LocalLocation FROM artwork_cache WHERE artwork_cache.RemoteLocation = AlbumArtLocation) AS ArtworkFile"; // All columns @@ -122,28 +123,25 @@ public class MusicTrackDataSource extends DataSource { * @return The new where command */ private String prepareWhere(String where) { - // The new where - String newWhere = "LocalCopyType != 300"; + // Ignore non-PlayMusic tracks + where = combineWhere(where, "LocalCopyType != 300"); // Loads only offline tracks if (mOfflineOnly) - newWhere += " AND LocalCopyPath IS NOT NULL"; + where = combineWhere(where, "LocalCopyPath IS NOT NULL"); // Search only items which contains the key if (!TextUtils.isEmpty(mSearchKey)) { - String searchKey = mSearchKey.replace("'", "''"); + String searchKey = DatabaseUtils.sqlEscapeString("%" + mSearchKey + "%"); - newWhere += " AND (" + COLUMN_ALBUM + " LIKE '%" + searchKey + "%'"; - newWhere += " OR " + COLUMN_TITLE + " LIKE '%" + searchKey + "%'"; - newWhere += " OR " + COLUMN_ALBUMARTIST + " LIKE '%" + searchKey + "%'"; - newWhere += " OR " + COLUMN_ARTIST + " LIKE '%" + searchKey + "%')"; + String searchWhere = COLUMN_ALBUM + " LIKE " + searchKey; + searchWhere += " OR " + COLUMN_TITLE + " LIKE " + searchKey; + searchWhere += " OR " + COLUMN_ALBUMARTIST + " LIKE " + searchKey; + searchWhere += " OR " + COLUMN_ARTIST + " LIKE " + searchKey; + + where = combineWhere(where, searchWhere); } - // Adds an 'and' if needed - if (!TextUtils.isEmpty(where)) where = "(" + where + ") AND "; - - where += newWhere; - return where; } @@ -205,6 +203,6 @@ public class MusicTrackDataSource extends DataSource { * @return Returns the track list */ public List getByPlaylist(Playlist playlist) { - return getItems(TABLE_MUSIC, COLUMNS_ALL, prepareWhere("ListId = " + playlist.getId()), "LISTITEMS.ID"); + return getItems(TABLE_MUSIC_PLAYLIST, COLUMNS_ALL, prepareWhere("ListId = " + playlist.getId()), "LISTITEMS.ID"); } } diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/PlaylistDataSource.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/PlaylistDataSource.java new file mode 100644 index 0000000..208a6f6 --- /dev/null +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/datasources/PlaylistDataSource.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015 David Schulte + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.arcus.playmusiclib.datasources; + +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.text.TextUtils; + +import java.util.List; + +import de.arcus.playmusiclib.PlayMusicManager; +import de.arcus.playmusiclib.items.Playlist; + +/** + * Data source for playlists + */ +public class PlaylistDataSource extends DataSource { + // Tables + private final static String TABLE_LIST = "LISTS"; + + // All fields + private final static String COLUMN_ID = "LISTS.Id"; + private final static String COLUMN_NAME = "LISTS.Name"; + private final static String COLUMN_LISTTYPE = "LISTS.ListType"; + private final static String COLUMN_OWNERNAME = "LISTS.OwnerName"; + private final static String COLUMN_ARTWORKFILE = "(SELECT ARTWORK_CACHE.LocalLocation FROM LISTITEMS LEFT JOIN MUSIC ON MUSIC.Id = LISTITEMS.MusicId LEFT JOIN ARTWORK_CACHE ON ARTWORK_CACHE.RemoteLocation = MUSIC.AlbumArtLocation WHERE LISTITEMS.ListId = LISTS.Id AND ARTWORK_CACHE.LocalLocation IS NOT NULL LIMIT 1) AS ArtworkFile"; + + // All columns + private final static String[] COLUMNS_ALL = { COLUMN_ID, COLUMN_NAME, + COLUMN_LISTTYPE, COLUMN_OWNERNAME, COLUMN_ARTWORKFILE}; + + + /** + * If this is set the data source will only load offline tracks + */ + private boolean mOfflineOnly; // TODO: Offline only has no effects on the playlist data sources + + /** + * If the search key is set, this data source will only load items which contains this text + */ + private String mSearchKey; + + /** + * @return Returns whether the data source should only load offline tracks + */ + public boolean getOfflineOnly() { + return mOfflineOnly; + } + + /** + * @param offlineOnly Sets whether the data source should only load offline tracks + */ + public void setOfflineOnly(boolean offlineOnly) { + mOfflineOnly = offlineOnly; + } + + /** + * @return Gets the search key + */ + public String getSearchKey() { + return mSearchKey; + } + + /** + * @param searchKey Sets the search key + */ + public void setSerchKey(String searchKey) { + mSearchKey = searchKey; + } + + /** + * Creates a new data source + * @param playMusicManager The manager + */ + public PlaylistDataSource(PlayMusicManager playMusicManager) { + super(playMusicManager); + + // Load global settings + setOfflineOnly(playMusicManager.getOfflineOnly()); + } + + /** + * Prepare the where command and adds the global settings + * @param where The where command + * @return The new where command + */ + private String prepareWhere(String where) { + // Search only items which contains the key + if (!TextUtils.isEmpty(mSearchKey)) { + String searchKey = DatabaseUtils.sqlEscapeString("%" + mSearchKey + "%"); + + where = combineWhere(where, "(" + COLUMN_NAME + " LIKE " + searchKey + ")"); + } + + return where; + } + + @Override + /** + * Gets the data object from a data row + * @param cursor Data row + * @return Data object + */ + protected Playlist getDataObject(Cursor cursor) { + Playlist instance = new Playlist(mPlayMusicManager); + + // Read all properties from the data row + instance.setId(cursor.getLong(getColumnsIndex(COLUMNS_ALL, COLUMN_ID))); + instance.setName(cursor.getString(getColumnsIndex(COLUMNS_ALL, COLUMN_NAME))); + instance.setListType(cursor.getLong(getColumnsIndex(COLUMNS_ALL, COLUMN_LISTTYPE))); + instance.setOwnerName(cursor.getString(getColumnsIndex(COLUMNS_ALL, COLUMN_OWNERNAME))); + instance.setArtworkFile(cursor.getString(getColumnsIndex(COLUMNS_ALL, COLUMN_ARTWORKFILE))); + + return instance; + } + + /** + * Loads a playlist by Id + * @param id The playlist id + * @return Returns the playlist or null + */ + public Playlist getById(long id) { + return getItem(TABLE_LIST, COLUMNS_ALL, prepareWhere(COLUMN_ID + " = " + id)); + } + + /** + * Gets a list of all playlists + * @return Returns all playlists + */ + public List getAll() { + return getItems(TABLE_LIST, COLUMNS_ALL, prepareWhere(COLUMN_LISTTYPE + " != " + Playlist.TYPE_QUEUE), COLUMN_NAME); + } +} diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/items/Playlist.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/items/Playlist.java index df583d2..33a8082 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/items/Playlist.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/items/Playlist.java @@ -36,8 +36,10 @@ public class Playlist extends MusicList { private String mOwnerName; private String mArtworkFile; - private final static long TYPE_QUEUE = 10; - private final static long TYPE_RADIO = 50; + public final static long TYPE_USER = 0; + public final static long TYPE_QUEUE = 10; + public final static long TYPE_RADIO = 50; + public final static long TYPE_PUBLIC = 71; private String mArtworkPath;