Merge pull request #250 from poisdeux/issue/#7
Fixed issue showing songs without an album or artist
This commit is contained in:
commit
466996f34e
|
@ -41,6 +41,7 @@ public class MediaContract {
|
|||
public static final String PATH_ALBUMS = "albums";
|
||||
public static final String PATH_AUDIO_GENRES = "audio_genres";
|
||||
public static final String PATH_SONGS = "songs";
|
||||
public static final String PATH_SONG_ARTISTS = "song_artists";
|
||||
public static final String PATH_ALBUM_ARTISTS = "album_artists";
|
||||
public static final String PATH_ALBUM_GENRES = "album_genres";
|
||||
public static final String PATH_MUSIC_VIDEOS = "music_videos";
|
||||
|
@ -701,6 +702,36 @@ public class MediaContract {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Columns for SongArtists table
|
||||
* All Other IDs refer to XBMC Ids, not Internal ones
|
||||
*/
|
||||
public interface SongArtistsColumns {
|
||||
String HOST_ID = "host_id";
|
||||
String SONGID = "songid";
|
||||
String ARTISTID = "artistid";
|
||||
}
|
||||
|
||||
public static class SongArtists implements BaseColumns, SongArtistsColumns {
|
||||
public static final Uri CONTENT_URI =
|
||||
BASE_CONTENT_URI.buildUpon().appendPath(PATH_SONG_ARTISTS).build();
|
||||
public static final String CONTENT_TYPE =
|
||||
"vnd.android.cursor.dir/vnd.org.xbmc." + PATH_SONG_ARTISTS;
|
||||
|
||||
/** Build {@link Uri} for requested {@link #_ID}. */
|
||||
public static Uri buildSongsForArtistListUri(long hostId, long artistId) {
|
||||
return Hosts.buildHostUri(hostId).buildUpon()
|
||||
.appendPath(PATH_ARTISTS)
|
||||
.appendPath(String.valueOf(artistId))
|
||||
.appendPath(PATH_SONGS)
|
||||
.build();
|
||||
}
|
||||
|
||||
public final static String[] ALL_COLUMNS = {
|
||||
_ID, HOST_ID, SONGID, ARTISTID,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Columns for AlbumGenres table
|
||||
* All Other IDs refer to XBMC Ids, not Internal ones
|
||||
|
|
|
@ -32,7 +32,7 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
|
||||
private static final String DB_NAME = "xbmc.sqlite";
|
||||
private static final int DB_VERSION_PRE_EVENT_SERVER = 4,
|
||||
DB_VERSION = 5;
|
||||
DB_VERSION_PRE_SONG_ARTISTS = 5, DB_VERSION = 6;
|
||||
|
||||
/**
|
||||
* Tables exposed
|
||||
|
@ -48,6 +48,7 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
String ARTISTS = "artists";
|
||||
String ALBUMS = "albums";
|
||||
String SONGS = "songs";
|
||||
String SONG_ARTISTS = "song_artists";
|
||||
String AUDIO_GENRES = "audio_genres";
|
||||
String ALBUM_ARTISTS = "album_artists";
|
||||
String ALBUM_GENRES = "album_genres";
|
||||
|
@ -90,25 +91,25 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
ALBUM_GENRES + "." + MediaContract.AlbumGenres.GENREID + "=" + AUDIO_GENRES + "." + MediaContract.AudioGenres.GENREID;
|
||||
|
||||
/**
|
||||
* Join to get Songs for an Artist
|
||||
* Join to get Songs for an Artist or Album with artist info and album info only if available
|
||||
*/
|
||||
String SONGS_FOR_ARTIST_JOIN =
|
||||
SONGS + " JOIN " + ALBUM_ARTISTS + " ON " +
|
||||
SONGS + "." + MediaContract.Songs.HOST_ID + "=" + ALBUM_ARTISTS + "." + MediaContract.AlbumArtists.HOST_ID +
|
||||
String SONGS_FOR_ARTIST_AND_OR_ALBUM_JOIN =
|
||||
SONG_ARTISTS + " JOIN " + SONGS + " ON " +
|
||||
SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID + "=" + SONGS + "." + MediaContract.Songs.HOST_ID +
|
||||
" AND " +
|
||||
SONGS + "." + MediaContract.Songs.ALBUMID + "=" + ALBUM_ARTISTS + "." + MediaContract.AlbumArtists.ALBUMID +
|
||||
" JOIN " + ALBUMS + " ON " +
|
||||
SONGS + "." + MediaContract.Songs.HOST_ID + "=" + ALBUMS + "." + MediaContract.Albums.HOST_ID +
|
||||
SONG_ARTISTS + "." + MediaContract.SongArtists.SONGID + "=" + SONGS + "." + MediaContract.Songs.SONGID +
|
||||
" LEFT JOIN " + ARTISTS + " ON " +
|
||||
SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID + "=" + ARTISTS + "." + MediaContract.Artists.HOST_ID +
|
||||
" AND " +
|
||||
SONGS + "." + MediaContract.Songs.ALBUMID + "=" + ALBUMS + "." + MediaContract.Albums.ALBUMID;
|
||||
|
||||
String SONGS_AND_ALBUM_JOIN =
|
||||
SONGS + " JOIN " + ALBUMS + " ON " +
|
||||
SONGS + "." + MediaContract.Songs.HOST_ID + "=" + ALBUMS + "." + MediaContract.Albums.HOST_ID +
|
||||
SONG_ARTISTS + "." + MediaContract.SongArtists.ARTISTID + "=" + ARTISTS + "." + MediaContract.Artists.ARTISTID +
|
||||
" LEFT JOIN " + ALBUMS + " ON " +
|
||||
SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID + "=" + ALBUMS + "." + MediaContract.Albums.HOST_ID +
|
||||
" AND " +
|
||||
SONGS + "." + MediaContract.Songs.ALBUMID + "=" + ALBUMS + "." + MediaContract.Albums.ALBUMID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private interface References {
|
||||
String HOST_ID =
|
||||
"REFERENCES " + Tables.HOSTS + "(" + BaseColumns._ID + ")";
|
||||
|
@ -118,6 +119,8 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
"REFERENCES " + Tables.ARTISTS + "(" + MediaContract.ArtistsColumns.ARTISTID + ")";
|
||||
String GENREID =
|
||||
"REFERENCES " + Tables.AUDIO_GENRES + "(" + MediaContract.AudioGenresColumns.GENREID + ")";
|
||||
String SONGID =
|
||||
"REFERENCES " + Tables.SONGS + "(" + MediaContract.Songs.SONGID + ")";
|
||||
}
|
||||
|
||||
public MediaDatabase(Context context) {
|
||||
|
@ -359,6 +362,8 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
") ON CONFLICT REPLACE)"
|
||||
);
|
||||
|
||||
createSongArtistsTable(db);
|
||||
|
||||
// AudioGenres
|
||||
db.execSQL("CREATE TABLE " + Tables.AUDIO_GENRES + "(" +
|
||||
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
|
@ -378,7 +383,7 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
MediaContract.AlbumArtistsColumns.HOST_ID + " INTEGER NOT NULL " + References.HOST_ID + ", " +
|
||||
MediaContract.AlbumArtistsColumns.ALBUMID + " INTEGER NOT NULL " + References.ALBUMID + ", " +
|
||||
MediaContract.AlbumArtistsColumns.ARTISTID + " INTEGER NOT NULL " + References .ARTISTID + ", " +
|
||||
MediaContract.AlbumArtistsColumns.ARTISTID + " INTEGER NOT NULL " + References.ARTISTID + ", " +
|
||||
"UNIQUE (" +
|
||||
MediaContract.AlbumArtistsColumns.HOST_ID + ", " +
|
||||
MediaContract.AlbumArtistsColumns.ALBUMID + ", " +
|
||||
|
@ -471,6 +476,8 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
db.execSQL("ALTER TABLE " + Tables.HOSTS +
|
||||
" ADD COLUMN " + MediaContract.HostsColumns.EVENT_SERVER_PORT +
|
||||
" INTEGER DEFAULT " + HostInfo.DEFAULT_EVENT_SERVER_PORT + ";");
|
||||
case DB_VERSION_PRE_SONG_ARTISTS:
|
||||
createSongArtistsTable(db);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -515,5 +522,19 @@ public class MediaDatabase extends SQLiteOpenHelper {
|
|||
|
||||
return order.toString();
|
||||
}
|
||||
|
||||
private void createSongArtistsTable(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE " + Tables.SONG_ARTISTS + "(" +
|
||||
BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
MediaContract.SongArtistsColumns.HOST_ID + " INTEGER NOT NULL " + References.HOST_ID + ", " +
|
||||
MediaContract.SongArtistsColumns.SONGID + " INTEGER NOT NULL " + References.SONGID + ", " +
|
||||
MediaContract.SongArtistsColumns.ARTISTID + " INTEGER NOT NULL " + References .ARTISTID + ", " +
|
||||
"UNIQUE (" +
|
||||
MediaContract.SongArtistsColumns.HOST_ID + ", " +
|
||||
MediaContract.SongArtistsColumns.SONGID + ", " +
|
||||
MediaContract.SongArtistsColumns.ARTISTID +
|
||||
") ON CONFLICT REPLACE)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ public class MediaProvider extends ContentProvider {
|
|||
private static final int ARTISTS_LIST = 601;
|
||||
private static final int ARTISTS_ID = 602;
|
||||
private static final int ARTIST_ALBUMS_LIST = 610;
|
||||
private static final int ARTIST_SONGS_LIST = 611;
|
||||
|
||||
private static final int ALBUMS_ALL = 700;
|
||||
private static final int ALBUMS_LIST = 701;
|
||||
|
@ -81,7 +82,6 @@ public class MediaProvider extends ContentProvider {
|
|||
private static final int ALBUM_GENRES_LIST = 711;
|
||||
|
||||
private static final int SONGS_ALL = 800;
|
||||
private static final int SONGS_ARTIST = 801;
|
||||
private static final int SONGS_ALBUM = 802;
|
||||
private static final int SONGS_ID = 803;
|
||||
private static final int SONGS_LIST = 804;
|
||||
|
@ -93,6 +93,7 @@ public class MediaProvider extends ContentProvider {
|
|||
|
||||
private static final int ALBUM_ARTISTS_ALL = 1000;
|
||||
private static final int ALBUM_GENRES_ALL = 1001;
|
||||
private static final int SONG_ARTISTS_ALL = 1002;
|
||||
|
||||
private static final int MUSIC_VIDEOS_ALL = 1100;
|
||||
private static final int MUSIC_VIDEOS_LIST = 1101;
|
||||
|
@ -169,6 +170,9 @@ public class MediaProvider extends ContentProvider {
|
|||
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
|
||||
MediaContract.PATH_ARTISTS + "/*/" +
|
||||
MediaContract.PATH_ALBUMS, ARTIST_ALBUMS_LIST);
|
||||
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
|
||||
MediaContract.PATH_ARTISTS + "/*/" +
|
||||
MediaContract.PATH_SONGS, ARTIST_SONGS_LIST);
|
||||
|
||||
// Albums
|
||||
matcher.addURI(authority, MediaContract.PATH_ALBUMS, ALBUMS_ALL);
|
||||
|
@ -193,9 +197,6 @@ public class MediaProvider extends ContentProvider {
|
|||
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
|
||||
MediaContract.PATH_ALBUMS + "/*/" +
|
||||
MediaContract.PATH_SONGS + "/*", SONGS_ID);
|
||||
matcher.addURI(authority, MediaContract.PATH_HOSTS + "/*/" +
|
||||
MediaContract.PATH_ARTISTS + "/*/" +
|
||||
MediaContract.PATH_SONGS, SONGS_ARTIST);
|
||||
|
||||
// Genres
|
||||
matcher.addURI(authority, MediaContract.PATH_AUDIO_GENRES, AUDIO_GENRES_ALL);
|
||||
|
@ -211,6 +212,8 @@ public class MediaProvider extends ContentProvider {
|
|||
matcher.addURI(authority, MediaContract.PATH_ALBUM_ARTISTS, ALBUM_ARTISTS_ALL);
|
||||
// AlbumGenres
|
||||
matcher.addURI(authority, MediaContract.PATH_ALBUM_GENRES, ALBUM_GENRES_ALL);
|
||||
// SongArtists
|
||||
matcher.addURI(authority, MediaContract.PATH_SONG_ARTISTS, SONG_ARTISTS_ALL);
|
||||
|
||||
// Music Videos
|
||||
matcher.addURI(authority, MediaContract.PATH_MUSIC_VIDEOS, MUSIC_VIDEOS_ALL);
|
||||
|
@ -288,7 +291,7 @@ public class MediaProvider extends ContentProvider {
|
|||
return MediaContract.Albums.CONTENT_ITEM_TYPE;
|
||||
case SONGS_ALL:
|
||||
case SONGS_LIST:
|
||||
case SONGS_ARTIST:
|
||||
case ARTIST_SONGS_LIST:
|
||||
case SONGS_ALBUM:
|
||||
return MediaContract.Songs.CONTENT_TYPE;
|
||||
case SONGS_ID:
|
||||
|
@ -303,6 +306,8 @@ public class MediaProvider extends ContentProvider {
|
|||
return MediaContract.AlbumArtists.CONTENT_TYPE;
|
||||
case ALBUM_GENRES_ALL:
|
||||
return MediaContract.AlbumGenres.CONTENT_TYPE;
|
||||
case SONG_ARTISTS_ALL:
|
||||
return MediaContract.SongArtists.CONTENT_TYPE;
|
||||
case MUSIC_VIDEOS_ALL:
|
||||
case MUSIC_VIDEOS_LIST:
|
||||
return MediaContract.MusicVideos.CONTENT_TYPE;
|
||||
|
@ -326,7 +331,6 @@ public class MediaProvider extends ContentProvider {
|
|||
default: {
|
||||
// Most cases are handled with simple SelectionBuilder
|
||||
final SelectionBuilder builder = buildQuerySelection(uri, match);
|
||||
|
||||
cursor = builder.where(selection, selectionArgs)
|
||||
.query(db, projection, sortOrder);
|
||||
}
|
||||
|
@ -413,6 +417,10 @@ public class MediaProvider extends ContentProvider {
|
|||
table = MediaDatabase.Tables.ALBUM_ARTISTS;
|
||||
break;
|
||||
}
|
||||
case SONG_ARTISTS_ALL: {
|
||||
table = MediaDatabase.Tables.SONG_ARTISTS;
|
||||
break;
|
||||
}
|
||||
case MUSIC_VIDEOS_ALL: {
|
||||
table = MediaDatabase.Tables.MUSIC_VIDEOS;
|
||||
break;
|
||||
|
@ -430,6 +438,7 @@ public class MediaProvider extends ContentProvider {
|
|||
switch (match) {
|
||||
case ALBUM_GENRES_ALL:
|
||||
case ALBUM_ARTISTS_ALL:
|
||||
case SONG_ARTISTS_ALL:
|
||||
// Nothing to add to these tables
|
||||
break;
|
||||
default:
|
||||
|
@ -658,8 +667,15 @@ public class MediaProvider extends ContentProvider {
|
|||
}
|
||||
case SONGS_LIST: {
|
||||
final String hostId = MediaContract.Hosts.getHostId(uri);
|
||||
return builder.table(MediaDatabase.Tables.SONGS_AND_ALBUM_JOIN)
|
||||
.where(Qualified.SONGS_HOST_ID + "=?", hostId);
|
||||
return builder.table(MediaDatabase.Tables.SONGS_FOR_ARTIST_AND_OR_ALBUM_JOIN)
|
||||
.mapToTable(MediaContract.Songs.SONGID, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.TITLE, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.ALBUMID, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.UPDATED, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.THUMBNAIL, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.SongArtists.ARTISTID, MediaDatabase.Tables.SONG_ARTISTS)
|
||||
.where(Qualified.SONGS_HOST_ID + "=?", hostId)
|
||||
.groupBy(Qualified.SONGS_SONGID);
|
||||
}
|
||||
case SONGS_ALBUM: {
|
||||
final String hostId = MediaContract.Hosts.getHostId(uri);
|
||||
|
@ -668,14 +684,6 @@ public class MediaProvider extends ContentProvider {
|
|||
.where(MediaContract.Songs.HOST_ID + "=?", hostId)
|
||||
.where(MediaContract.Songs.ALBUMID + "=?", albumId);
|
||||
}
|
||||
case SONGS_ARTIST: {
|
||||
final String hostId = MediaContract.Hosts.getHostId(uri);
|
||||
final String artistId = MediaContract.Artists.getArtistId(uri);
|
||||
LogUtils.LOGD(TAG, "buildQuerySelection: SONGS_ARTIST: "+MediaDatabase.Tables.SONGS_FOR_ARTIST_JOIN);
|
||||
return builder.table(MediaDatabase.Tables.SONGS_FOR_ARTIST_JOIN)
|
||||
.where(Qualified.SONGS_HOST_ID + "=?", hostId)
|
||||
.where(Qualified.ALBUM_ARTISTS_ARTISTID + "=?", artistId);
|
||||
}
|
||||
case SONGS_ID: {
|
||||
final String hostId = MediaContract.Hosts.getHostId(uri);
|
||||
final String albumId = MediaContract.Albums.getAlbumId(uri);
|
||||
|
@ -703,6 +711,9 @@ public class MediaProvider extends ContentProvider {
|
|||
case ALBUM_ARTISTS_ALL: {
|
||||
return builder.table(MediaDatabase.Tables.ALBUM_ARTISTS);
|
||||
}
|
||||
case SONG_ARTISTS_ALL: {
|
||||
return builder.table(MediaDatabase.Tables.SONG_ARTISTS);
|
||||
}
|
||||
case ALBUM_GENRES_ALL: {
|
||||
return builder.table(MediaDatabase.Tables.ALBUM_GENRES);
|
||||
}
|
||||
|
@ -718,6 +729,20 @@ public class MediaProvider extends ContentProvider {
|
|||
.where(Qualified.ALBUM_ARTISTS_HOST_ID + "=?", hostId)
|
||||
.where(Qualified.ALBUM_ARTISTS_ARTISTID + "=?", artistId);
|
||||
}
|
||||
case ARTIST_SONGS_LIST: {
|
||||
// Songs for Artists
|
||||
final String hostId = MediaContract.Hosts.getHostId(uri);
|
||||
final String artistId = MediaContract.Artists.getArtistId(uri);
|
||||
return builder.table(MediaDatabase.Tables.SONGS_FOR_ARTIST_AND_OR_ALBUM_JOIN)
|
||||
.mapToTable(MediaContract.Songs.SONGID, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.TITLE, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.ALBUMID, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.UPDATED, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.Songs.THUMBNAIL, MediaDatabase.Tables.SONGS)
|
||||
.mapToTable(MediaContract.SongArtists.ARTISTID, MediaDatabase.Tables.SONG_ARTISTS)
|
||||
.where(Qualified.SONG_ARTISTS_HOST_ID + "=?", hostId)
|
||||
.where(Qualified.SONG_ARTISTS_ARTISTID + "=?", artistId);
|
||||
}
|
||||
case ALBUM_ARTISTS_LIST: {
|
||||
// Artists for Album
|
||||
final String hostId = MediaContract.Hosts.getHostId(uri);
|
||||
|
@ -795,5 +820,11 @@ public class MediaProvider extends ContentProvider {
|
|||
MediaDatabase.Tables.ALBUM_GENRES + "." + MediaContract.AlbumGenres.ALBUMID;
|
||||
String SONGS_HOST_ID =
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.HOST_ID;
|
||||
String SONGS_SONGID =
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.SONGID;
|
||||
String SONG_ARTISTS_HOST_ID =
|
||||
MediaDatabase.Tables.SONG_ARTISTS + "." + MediaContract.SongArtists.HOST_ID;
|
||||
String SONG_ARTISTS_ARTISTID =
|
||||
MediaDatabase.Tables.SONG_ARTISTS + "." + MediaContract.SongArtists.ARTISTID;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,7 +317,8 @@ public class SyncMusic extends SyncItem {
|
|||
AudioType.FieldsSong.THUMBNAIL, AudioType.FieldsSong.FILE,
|
||||
AudioType.FieldsSong.ALBUMID,
|
||||
//AudioType.FieldsSong.LASTPLAYED, AudioType.FieldsSong.DISC,
|
||||
//AudioType.FieldsSong.GENREID, AudioType.FieldsSong.ARTISTID,
|
||||
//AudioType.FieldsSong.GENREID,
|
||||
AudioType.FieldsSong.ARTISTID,
|
||||
//AudioType.FieldsSong.DISPLAYARTIST, AudioType.FieldsSong.ALBUMARTISTID
|
||||
};
|
||||
|
||||
|
@ -345,14 +346,30 @@ public class SyncMusic extends SyncItem {
|
|||
limitsReturned = result.limits;
|
||||
}
|
||||
|
||||
int totalArtistsCount = 0;
|
||||
// Save partial results to DB
|
||||
ContentValues songValuesBatch[] = new ContentValues[items.size()];
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
AudioType.DetailsSong song = items.get(i);
|
||||
songValuesBatch[i] = SyncUtils.contentValuesFromSong(hostId, song);
|
||||
totalArtistsCount += song.artistid.size();
|
||||
}
|
||||
contentResolver.bulkInsert(MediaContract.Songs.CONTENT_URI, songValuesBatch);
|
||||
|
||||
// Iterate on each song, collect the artists and insert them
|
||||
ContentValues songArtistsValuesBatch[] = new ContentValues[totalArtistsCount];
|
||||
int artistCount = 0;
|
||||
for (AudioType.DetailsSong song : items) {
|
||||
for (int artistId : song.artistid) {
|
||||
songArtistsValuesBatch[artistCount] = new ContentValues();
|
||||
songArtistsValuesBatch[artistCount].put(MediaContract.SongArtists.HOST_ID, hostId);
|
||||
songArtistsValuesBatch[artistCount].put(MediaContract.SongArtists.SONGID, song.songid);
|
||||
songArtistsValuesBatch[artistCount].put(MediaContract.SongArtists.ARTISTID, artistId);
|
||||
artistCount++;
|
||||
}
|
||||
}
|
||||
contentResolver.bulkInsert(MediaContract.SongArtists.CONTENT_URI, songArtistsValuesBatch);
|
||||
|
||||
if (moreItemsAvailable(limitsReturned)) {
|
||||
LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing.");
|
||||
result = null; // Help the GC?
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.xbmc.kore.jsonrpc.type.VideoType;
|
|||
import org.xbmc.kore.jsonrpc.type.AudioType;
|
||||
import org.xbmc.kore.jsonrpc.type.LibraryType;
|
||||
import org.xbmc.kore.provider.MediaContract;
|
||||
import org.xbmc.kore.service.library.LibrarySyncService;
|
||||
import org.xbmc.kore.utils.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -42,7 +41,7 @@ public class SyncUtils {
|
|||
void onServiceConnected(LibrarySyncService librarySyncService);
|
||||
}
|
||||
|
||||
public static final String LIST_DELIMETER = ", ";
|
||||
public static final String LIST_DELIMITER = ", ";
|
||||
|
||||
/**
|
||||
* Returns {@link android.content.ContentValues} from a {@link org.xbmc.kore.jsonrpc.type.VideoType.DetailsMovie} movie
|
||||
|
@ -61,7 +60,7 @@ public class SyncUtils {
|
|||
movieValues.put(MediaContract.MoviesColumns.TITLE, movie.title);
|
||||
movieValues.put(MediaContract.MoviesColumns.FILE, movie.file);
|
||||
movieValues.put(MediaContract.MoviesColumns.PLOT, movie.plot);
|
||||
movieValues.put(MediaContract.MoviesColumns.DIRECTOR, Utils.listStringConcat(movie.director, LIST_DELIMETER));
|
||||
movieValues.put(MediaContract.MoviesColumns.DIRECTOR, Utils.listStringConcat(movie.director, LIST_DELIMITER));
|
||||
movieValues.put(MediaContract.MoviesColumns.RUNTIME, movie.runtime);
|
||||
if (movie.streamdetails != null) {
|
||||
if (movie.streamdetails.audio.size() > 0) {
|
||||
|
@ -78,7 +77,7 @@ public class SyncUtils {
|
|||
movieValues.put(MediaContract.MoviesColumns.AUDIO_CHANNELS, selectedStream.channels);
|
||||
movieValues.put(MediaContract.MoviesColumns.AUDIO_CODEC, selectedStream.codec);
|
||||
movieValues.put(MediaContract.MoviesColumns.AUDIO_LANGUAGE,
|
||||
Utils.listStringConcat(languages, LIST_DELIMETER));
|
||||
Utils.listStringConcat(languages, LIST_DELIMITER));
|
||||
}
|
||||
if (movie.streamdetails.subtitle.size() > 0) {
|
||||
// Concat all subtitle languages
|
||||
|
@ -87,7 +86,7 @@ public class SyncUtils {
|
|||
subtitles.add(movie.streamdetails.subtitle.get(j).language);
|
||||
}
|
||||
movieValues.put(MediaContract.MoviesColumns.SUBTITLES_LANGUAGES,
|
||||
Utils.listStringConcat(subtitles, LIST_DELIMETER));
|
||||
Utils.listStringConcat(subtitles, LIST_DELIMITER));
|
||||
}
|
||||
if (movie.streamdetails.video.size() > 0) {
|
||||
// We're only getting the first video channel...
|
||||
|
@ -102,22 +101,22 @@ public class SyncUtils {
|
|||
}
|
||||
}
|
||||
movieValues.put(MediaContract.MoviesColumns.COUNTRIES,
|
||||
Utils.listStringConcat(movie.country, LIST_DELIMETER));
|
||||
Utils.listStringConcat(movie.country, LIST_DELIMITER));
|
||||
movieValues.put(MediaContract.MoviesColumns.GENRES,
|
||||
Utils.listStringConcat(movie.genre, LIST_DELIMETER));
|
||||
Utils.listStringConcat(movie.genre, LIST_DELIMITER));
|
||||
movieValues.put(MediaContract.MoviesColumns.IMDBNUMBER, movie.imdbnumber);
|
||||
movieValues.put(MediaContract.MoviesColumns.MPAA, movie.mpaa);
|
||||
movieValues.put(MediaContract.MoviesColumns.RATING, movie.rating);
|
||||
movieValues.put(MediaContract.MoviesColumns.SET, movie.set);
|
||||
movieValues.put(MediaContract.MoviesColumns.SETID, movie.setid);
|
||||
movieValues.put(MediaContract.MoviesColumns.STUDIOS,
|
||||
Utils.listStringConcat(movie.studio, LIST_DELIMETER));
|
||||
Utils.listStringConcat(movie.studio, LIST_DELIMITER));
|
||||
movieValues.put(MediaContract.MoviesColumns.TAGLINE, movie.tagline);
|
||||
movieValues.put(MediaContract.MoviesColumns.TOP250, movie.top250);
|
||||
movieValues.put(MediaContract.MoviesColumns.TRAILER, movie.trailer);
|
||||
movieValues.put(MediaContract.MoviesColumns.VOTES, movie.votes);
|
||||
movieValues.put(MediaContract.MoviesColumns.WRITERS,
|
||||
Utils.listStringConcat(movie.writer, LIST_DELIMETER));
|
||||
Utils.listStringConcat(movie.writer, LIST_DELIMITER));
|
||||
movieValues.put(MediaContract.MoviesColumns.YEAR, movie.year);
|
||||
|
||||
return movieValues;
|
||||
|
@ -164,10 +163,10 @@ public class SyncUtils {
|
|||
tvshowValues.put(MediaContract.TVShowsColumns.PREMIERED, tvshow.premiered);
|
||||
tvshowValues.put(MediaContract.TVShowsColumns.RATING, tvshow.rating);
|
||||
tvshowValues.put(MediaContract.TVShowsColumns.STUDIO,
|
||||
Utils.listStringConcat(tvshow.studio, LIST_DELIMETER));
|
||||
Utils.listStringConcat(tvshow.studio, LIST_DELIMITER));
|
||||
tvshowValues.put(MediaContract.TVShowsColumns.WATCHEDEPISODES, tvshow.watchedepisodes);
|
||||
tvshowValues.put(MediaContract.TVShowsColumns.GENRES,
|
||||
Utils.listStringConcat(tvshow.genre, LIST_DELIMETER));
|
||||
Utils.listStringConcat(tvshow.genre, LIST_DELIMITER));
|
||||
|
||||
return tvshowValues;
|
||||
}
|
||||
|
@ -215,12 +214,12 @@ public class SyncUtils {
|
|||
episodeValues.put(MediaContract.EpisodesColumns.TITLE, episode.title);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.FILE, episode.file);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.PLOT, episode.plot);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.DIRECTOR, Utils.listStringConcat(episode.director, LIST_DELIMETER));
|
||||
episodeValues.put(MediaContract.EpisodesColumns.DIRECTOR, Utils.listStringConcat(episode.director, LIST_DELIMITER));
|
||||
episodeValues.put(MediaContract.EpisodesColumns.RUNTIME, episode.runtime);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.FIRSTAIRED, episode.firstaired);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.RATING, episode.rating);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.SHOWTITLE, episode.showtitle);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.WRITER, Utils.listStringConcat(episode.writer, LIST_DELIMETER));
|
||||
episodeValues.put(MediaContract.EpisodesColumns.WRITER, Utils.listStringConcat(episode.writer, LIST_DELIMITER));
|
||||
|
||||
if (episode.streamdetails.audio.size() > 0) {
|
||||
// Get the stream with the most channels and concat all the languages
|
||||
|
@ -235,7 +234,7 @@ public class SyncUtils {
|
|||
}
|
||||
episodeValues.put(MediaContract.EpisodesColumns.AUDIO_CHANNELS, selectedStream.channels);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.AUDIO_CODEC, selectedStream.codec);
|
||||
episodeValues.put(MediaContract.EpisodesColumns.AUDIO_LANGUAGE, Utils.listStringConcat(languages, LIST_DELIMETER));
|
||||
episodeValues.put(MediaContract.EpisodesColumns.AUDIO_LANGUAGE, Utils.listStringConcat(languages, LIST_DELIMITER));
|
||||
}
|
||||
if (episode.streamdetails.subtitle.size() > 0) {
|
||||
// Concat all subtitle languages
|
||||
|
@ -243,7 +242,7 @@ public class SyncUtils {
|
|||
for (int j = 0; j < episode.streamdetails.subtitle.size(); j++) {
|
||||
subtitles.add(episode.streamdetails.subtitle.get(j).language);
|
||||
}
|
||||
episodeValues.put(MediaContract.EpisodesColumns.SUBTITLES_LANGUAGES, Utils.listStringConcat(subtitles, LIST_DELIMETER));
|
||||
episodeValues.put(MediaContract.EpisodesColumns.SUBTITLES_LANGUAGES, Utils.listStringConcat(subtitles, LIST_DELIMITER));
|
||||
}
|
||||
if (episode.streamdetails.video.size() > 0) {
|
||||
// We're only getting the first video channel...
|
||||
|
@ -273,7 +272,7 @@ public class SyncUtils {
|
|||
castValues.put(MediaContract.ArtistsColumns.ARTIST, artist.artist);
|
||||
castValues.put(MediaContract.ArtistsColumns.DESCRIPTION, artist.description);
|
||||
castValues.put(MediaContract.ArtistsColumns.GENRE,
|
||||
Utils.listStringConcat(artist.genre, LIST_DELIMETER));
|
||||
Utils.listStringConcat(artist.genre, LIST_DELIMITER));
|
||||
castValues.put(MediaContract.ArtistsColumns.FANART, artist.fanart);
|
||||
castValues.put(MediaContract.ArtistsColumns.THUMBNAIL, artist.thumbnail);
|
||||
|
||||
|
@ -315,7 +314,7 @@ public class SyncUtils {
|
|||
castValues.put(MediaContract.Albums.ALBUMLABEL, album.albumlabel);
|
||||
castValues.put(MediaContract.Albums.DESCRIPTION, album.description);
|
||||
castValues.put(MediaContract.Albums.PLAYCOUNT, album.playcount);
|
||||
castValues.put(MediaContract.Albums.GENRE, Utils.listStringConcat(album.genre, LIST_DELIMETER));
|
||||
castValues.put(MediaContract.Albums.GENRE, Utils.listStringConcat(album.genre, LIST_DELIMITER));
|
||||
|
||||
return castValues;
|
||||
}
|
||||
|
@ -357,7 +356,7 @@ public class SyncUtils {
|
|||
musicVideoValues.put(MediaContract.MusicVideosColumns.TITLE, musicVideo.title);
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.FILE, musicVideo.file);
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.PLOT, musicVideo.plot);
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.DIRECTOR, Utils.listStringConcat(musicVideo.director, LIST_DELIMETER));
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.DIRECTOR, Utils.listStringConcat(musicVideo.director, LIST_DELIMITER));
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.RUNTIME, musicVideo.runtime);
|
||||
if (musicVideo.streamdetails != null) {
|
||||
if (musicVideo.streamdetails.audio.size() > 0) {
|
||||
|
@ -374,7 +373,7 @@ public class SyncUtils {
|
|||
musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_CHANNELS, selectedStream.channels);
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_CODEC, selectedStream.codec);
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.AUDIO_LANGUAGE,
|
||||
Utils.listStringConcat(languages, LIST_DELIMETER));
|
||||
Utils.listStringConcat(languages, LIST_DELIMITER));
|
||||
}
|
||||
if (musicVideo.streamdetails.subtitle.size() > 0) {
|
||||
// Concat all subtitle languages
|
||||
|
@ -383,7 +382,7 @@ public class SyncUtils {
|
|||
subtitles.add(musicVideo.streamdetails.subtitle.get(j).language);
|
||||
}
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.SUBTITLES_LANGUAGES,
|
||||
Utils.listStringConcat(subtitles, LIST_DELIMETER));
|
||||
Utils.listStringConcat(subtitles, LIST_DELIMITER));
|
||||
}
|
||||
if (musicVideo.streamdetails.video.size() > 0) {
|
||||
// We're only getting the first video channel...
|
||||
|
@ -399,13 +398,13 @@ public class SyncUtils {
|
|||
}
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.ALBUM, musicVideo.album);
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.ARTIST,
|
||||
Utils.listStringConcat(musicVideo.artist, LIST_DELIMETER));
|
||||
Utils.listStringConcat(musicVideo.artist, LIST_DELIMITER));
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.GENRES,
|
||||
Utils.listStringConcat(musicVideo.genre, LIST_DELIMETER));
|
||||
Utils.listStringConcat(musicVideo.genre, LIST_DELIMITER));
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.STUDIOS,
|
||||
Utils.listStringConcat(musicVideo.studio, LIST_DELIMETER));
|
||||
Utils.listStringConcat(musicVideo.studio, LIST_DELIMITER));
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.TAG,
|
||||
Utils.listStringConcat(musicVideo.tag, LIST_DELIMETER));
|
||||
Utils.listStringConcat(musicVideo.tag, LIST_DELIMITER));
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.TRACK, musicVideo.track);
|
||||
musicVideoValues.put(MediaContract.MusicVideosColumns.YEAR, musicVideo.year);
|
||||
|
||||
|
|
|
@ -229,7 +229,7 @@ public class ArtistOverviewFragment extends AbstractDetailsFragment
|
|||
case LOADER_SONGS:
|
||||
uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), artistId);
|
||||
return new CursorLoader(getActivity(), uri,
|
||||
AlbumSongsListQuery.PROJECTION, null, null, AlbumSongsListQuery.SORT);
|
||||
SongsListQuery.PROJECTION, null, null, SongsListQuery.SORT);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -299,16 +299,16 @@ public class ArtistOverviewFragment extends AbstractDetailsFragment
|
|||
|
||||
private FileDownloadHelper.SongInfo createSongInfo(Cursor cursor) {
|
||||
FileDownloadHelper.SongInfo songInfo = null;
|
||||
String albumTitle = albumTitles.get(cursor.getInt(AlbumSongsListQuery.ALBUMID));
|
||||
String albumTitle = albumTitles.get(cursor.getInt(SongsListQuery.ALBUMID));
|
||||
if (albumTitle != null) {
|
||||
// Add this song to the list
|
||||
songInfo = new FileDownloadHelper.SongInfo(
|
||||
artistTitle,
|
||||
albumTitle,
|
||||
cursor.getInt(AlbumSongsListQuery.SONGID),
|
||||
cursor.getInt(AlbumSongsListQuery.TRACK),
|
||||
cursor.getString(AlbumSongsListQuery.TITLE),
|
||||
cursor.getString(AlbumSongsListQuery.FILE));
|
||||
cursor.getInt(SongsListQuery.SONGID),
|
||||
cursor.getInt(SongsListQuery.TRACK),
|
||||
cursor.getString(SongsListQuery.TITLE),
|
||||
cursor.getString(SongsListQuery.FILE));
|
||||
}
|
||||
return songInfo;
|
||||
}
|
||||
|
@ -457,7 +457,7 @@ public class ArtistOverviewFragment extends AbstractDetailsFragment
|
|||
/**
|
||||
* Song list query parameters.
|
||||
*/
|
||||
private interface AlbumSongsListQuery {
|
||||
private interface SongsListQuery {
|
||||
String[] PROJECTION = {
|
||||
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,
|
||||
|
|
|
@ -49,6 +49,8 @@ import org.xbmc.kore.utils.LogUtils;
|
|||
import org.xbmc.kore.utils.MediaPlayerUtils;
|
||||
import org.xbmc.kore.utils.UIUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Fragment that presents the songs list
|
||||
*/
|
||||
|
@ -94,7 +96,7 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
}
|
||||
|
||||
return new CursorLoader(getActivity(), uri,
|
||||
SongsAlbumsListQuery.PROJECTION, selection, selectionArgs, SongsAlbumsListQuery.SORT);
|
||||
SongsListQuery.PROJECTION, selection, selectionArgs, SongsListQuery.SORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -129,35 +131,10 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
/**
|
||||
* Song list query parameters.
|
||||
*/
|
||||
private interface SongsListQuery {
|
||||
String[] PROJECTION = {
|
||||
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TRACK,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.DURATION,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.FILE,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.SONGID,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.ALBUMID,
|
||||
};
|
||||
|
||||
String SORT = MediaContract.Songs.TRACK + " ASC";
|
||||
|
||||
int ID = 0;
|
||||
int TITLE = 1;
|
||||
int TRACK = 2;
|
||||
int DURATION = 3;
|
||||
int FILE = 4;
|
||||
int SONGID = 5;
|
||||
int ALBUMID = 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Album songs list query parameters.
|
||||
*/
|
||||
private interface SongsAlbumsListQuery {
|
||||
private interface SongsListQuery {
|
||||
String[] PROJECTION = {
|
||||
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
|
||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,
|
||||
|
@ -170,6 +147,7 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.GENRE,
|
||||
MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.YEAR,
|
||||
MediaDatabase.Tables.ALBUMS + "." + MediaContract.Albums.THUMBNAIL,
|
||||
MediaDatabase.Tables.ARTISTS + "." + MediaContract.Artists.ARTIST
|
||||
};
|
||||
|
||||
String SORT = MediaDatabase.sortCommonTokens(MediaDatabase.Tables.SONGS
|
||||
|
@ -187,6 +165,7 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
int GENRE = 8;
|
||||
int YEAR = 9;
|
||||
int THUMBNAIL = 10;
|
||||
int ARTIST = 11;
|
||||
}
|
||||
|
||||
private class SongsAdapter extends CursorAdapter {
|
||||
|
@ -229,25 +208,30 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
final ViewHolder viewHolder = (ViewHolder)view.getTag();
|
||||
|
||||
String title = cursor.getString(SongsAlbumsListQuery.TITLE);
|
||||
viewHolder.songId = cursor.getInt(SongsAlbumsListQuery.SONGID);
|
||||
String title = cursor.getString(SongsListQuery.TITLE);
|
||||
viewHolder.songId = cursor.getInt(SongsListQuery.SONGID);
|
||||
|
||||
viewHolder.title.setText(title);
|
||||
viewHolder.artist.setText(String.valueOf(cursor.getString(SongsAlbumsListQuery.ALBUMARTIST)));
|
||||
|
||||
int year = cursor.getInt(SongsAlbumsListQuery.YEAR);
|
||||
String artist = cursor.getString(SongsListQuery.ALBUMARTIST);
|
||||
if (TextUtils.isEmpty(artist))
|
||||
artist = cursor.getString(SongsListQuery.ARTIST);
|
||||
|
||||
viewHolder.artist.setText(artist);
|
||||
|
||||
int year = cursor.getInt(SongsListQuery.YEAR);
|
||||
if (year > 0) {
|
||||
setDetails(viewHolder.details,
|
||||
cursor.getString(SongsAlbumsListQuery.ALBUMTITLE),
|
||||
cursor.getString(SongsListQuery.ALBUMTITLE),
|
||||
String.valueOf(year),
|
||||
cursor.getString(SongsAlbumsListQuery.GENRE));
|
||||
cursor.getString(SongsListQuery.GENRE));
|
||||
} else {
|
||||
setDetails(viewHolder.details,
|
||||
cursor.getString(SongsAlbumsListQuery.ALBUMTITLE),
|
||||
cursor.getString(SongsAlbumsListQuery.GENRE));
|
||||
cursor.getString(SongsListQuery.ALBUMTITLE),
|
||||
cursor.getString(SongsListQuery.GENRE));
|
||||
}
|
||||
|
||||
String thumbnail = cursor.getString(SongsAlbumsListQuery.THUMBNAIL);
|
||||
String thumbnail = cursor.getString(SongsListQuery.THUMBNAIL);
|
||||
UIUtils.loadImageWithCharacterAvatar(context, hostManager,
|
||||
thumbnail, title,
|
||||
viewHolder.art, artWidth, artHeight);
|
||||
|
@ -306,21 +290,12 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
|||
return;
|
||||
}
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
int i = 0;
|
||||
int size = elements.length - 1;
|
||||
for (; i < size; i++) {
|
||||
if (!TextUtils.isEmpty(elements[i])) {
|
||||
stringBuilder.append(elements[i]);
|
||||
stringBuilder.append(" | ");
|
||||
}
|
||||
ArrayList<String> details = new ArrayList<>();
|
||||
for (int i = 0; i < elements.length; i++) {
|
||||
if (!TextUtils.isEmpty(elements[i]))
|
||||
details.add(elements[i]);
|
||||
}
|
||||
|
||||
if (elements.length > 0) {
|
||||
stringBuilder.append(elements[i]);
|
||||
}
|
||||
|
||||
textView.setText(stringBuilder.toString());
|
||||
textView.setText(TextUtils.join(" | ", details.toArray()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class SelectionBuilder {
|
|||
private Map<String, String> mProjectionMap = new HashMap<String, String>();
|
||||
private StringBuilder mSelection = new StringBuilder();
|
||||
private ArrayList<String> mSelectionArgs = new ArrayList<String>();
|
||||
|
||||
private StringBuilder mGroupBy = new StringBuilder();
|
||||
/**
|
||||
* Reset any internal state, allowing this builder to be recycled.
|
||||
*/
|
||||
|
@ -56,6 +56,20 @@ public class SelectionBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public SelectionBuilder groupBy(String... groupByArgs) {
|
||||
if (groupByArgs != null) {
|
||||
if (mGroupBy.length() > 0)
|
||||
mGroupBy.append(", ");
|
||||
|
||||
int size = groupByArgs.length - 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
mGroupBy.append(groupByArgs[i] + ", ");
|
||||
}
|
||||
mGroupBy.append(groupByArgs[size]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the given selection clause to the internal state. Each clause is
|
||||
* surrounded with parenthesis and combined using {@code AND}.
|
||||
|
@ -141,7 +155,7 @@ public class SelectionBuilder {
|
|||
* Execute query using the current internal state as {@code WHERE} clause.
|
||||
*/
|
||||
public Cursor query(SQLiteDatabase db, String[] columns, String orderBy) {
|
||||
return query(db, columns, null, null, orderBy, null);
|
||||
return query(db, columns, mGroupBy.toString(), null, orderBy, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue