Unittest/mediaprovider (#251)
Implemented integration tests for music items
This commit is contained in:
parent
d746f6643f
commit
080b5809f3
|
@ -30,6 +30,7 @@ import org.xbmc.kore.jsonrpc.type.LibraryType;
|
||||||
import org.xbmc.kore.jsonrpc.type.VideoType;
|
import org.xbmc.kore.jsonrpc.type.VideoType;
|
||||||
import org.xbmc.kore.provider.MediaContract;
|
import org.xbmc.kore.provider.MediaContract;
|
||||||
import org.xbmc.kore.provider.MediaProvider;
|
import org.xbmc.kore.provider.MediaProvider;
|
||||||
|
import org.xbmc.kore.service.library.SyncMusic;
|
||||||
import org.xbmc.kore.service.library.SyncUtils;
|
import org.xbmc.kore.service.library.SyncUtils;
|
||||||
import org.xbmc.kore.utils.LogUtils;
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
|
|
||||||
|
@ -45,12 +46,12 @@ public class Database {
|
||||||
mediaProvider.onCreate();
|
mediaProvider.onCreate();
|
||||||
|
|
||||||
HostInfo hostInfo = addHost(context);
|
HostInfo hostInfo = addHost(context);
|
||||||
|
SyncMusic syncMusic = new SyncMusic(hostInfo.getId(), null);
|
||||||
insertMovies(context, hostInfo.getId());
|
insertMovies(context, hostInfo.getId());
|
||||||
insertArtists(context, hostInfo.getId());
|
insertArtists(context, syncMusic);
|
||||||
insertGenres(context, hostInfo.getId());
|
insertGenres(context, syncMusic);
|
||||||
insertAlbums(context, hostInfo.getId());
|
insertAlbums(context, syncMusic);
|
||||||
insertSongs(context, hostInfo.getId());
|
insertSongs(context, syncMusic);
|
||||||
|
|
||||||
return hostInfo;
|
return hostInfo;
|
||||||
}
|
}
|
||||||
|
@ -96,86 +97,34 @@ public class Database {
|
||||||
context.getContentResolver().bulkInsert(MediaContract.MovieCast.CONTENT_URI, movieCastValuesBatch);
|
context.getContentResolver().bulkInsert(MediaContract.MovieCast.CONTENT_URI, movieCastValuesBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void insertArtists(Context context, int hostId) throws ApiException, IOException {
|
private static void insertArtists(Context context, SyncMusic syncMusic) throws ApiException, IOException {
|
||||||
AudioLibrary.GetArtists getArtists = new AudioLibrary.GetArtists(false);
|
AudioLibrary.GetArtists getArtists = new AudioLibrary.GetArtists(false);
|
||||||
String result = Utils.readFile(context, "AudioLibrary.GetArtists.json");
|
String result = Utils.readFile(context, "AudioLibrary.GetArtists.json");
|
||||||
ArrayList<AudioType.DetailsArtist> artistList = (ArrayList) getArtists.resultFromJson(result).items;
|
ArrayList<AudioType.DetailsArtist> artistList = (ArrayList) getArtists.resultFromJson(result).items;
|
||||||
|
|
||||||
ContentValues artistValuesBatch[] = new ContentValues[artistList.size()];
|
syncMusic.insertArtists(artistList, context.getContentResolver());
|
||||||
for (int i = 0; i < artistList.size(); i++) {
|
|
||||||
AudioType.DetailsArtist artist = artistList.get(i);
|
|
||||||
artistValuesBatch[i] = SyncUtils.contentValuesFromArtist(hostId, artist);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.getContentResolver().bulkInsert(MediaContract.Artists.CONTENT_URI, artistValuesBatch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void insertGenres(Context context, int hostId) throws ApiException, IOException {
|
private static void insertGenres(Context context, SyncMusic syncMusic) throws ApiException, IOException {
|
||||||
AudioLibrary.GetGenres getGenres = new AudioLibrary.GetGenres();
|
AudioLibrary.GetGenres getGenres = new AudioLibrary.GetGenres();
|
||||||
ArrayList<LibraryType.DetailsGenre> genreList = (ArrayList) getGenres.resultFromJson(Utils.readFile(context, "AudioLibrary.GetGenres.json"));
|
ArrayList<LibraryType.DetailsGenre> genreList = (ArrayList) getGenres.resultFromJson(Utils.readFile(context, "AudioLibrary.GetGenres.json"));
|
||||||
|
|
||||||
ContentValues genresValuesBatch[] = new ContentValues[genreList.size()];
|
syncMusic.insertGenresItems(genreList, context.getContentResolver());
|
||||||
for (int i = 0; i < genreList.size(); i++) {
|
|
||||||
LibraryType.DetailsGenre genre = genreList.get(i);
|
|
||||||
genresValuesBatch[i] = SyncUtils.contentValuesFromAudioGenre(hostId, genre);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.getContentResolver().bulkInsert(MediaContract.AudioGenres.CONTENT_URI, genresValuesBatch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void insertAlbums(Context context, int hostId) throws ApiException, IOException {
|
private static void insertAlbums(Context context, SyncMusic syncMusic) throws ApiException, IOException {
|
||||||
AudioLibrary.GetAlbums getAlbums = new AudioLibrary.GetAlbums();
|
AudioLibrary.GetAlbums getAlbums = new AudioLibrary.GetAlbums();
|
||||||
String result = Utils.readFile(context, "AudioLibrary.GetAlbums.json");
|
String result = Utils.readFile(context, "AudioLibrary.GetAlbums.json");
|
||||||
ArrayList<AudioType.DetailsAlbum> albumList = (ArrayList) getAlbums.resultFromJson(result).items;
|
ArrayList<AudioType.DetailsAlbum> albumList = (ArrayList) getAlbums.resultFromJson(result).items;
|
||||||
|
|
||||||
ContentResolver contentResolver = context.getContentResolver();
|
syncMusic.insertAlbumsItems(albumList, context.getContentResolver());
|
||||||
|
|
||||||
ContentValues albumValuesBatch[] = new ContentValues[albumList.size()];
|
|
||||||
int artistsCount = 0, genresCount = 0;
|
|
||||||
for (int i = 0; i < albumList.size(); i++) {
|
|
||||||
AudioType.DetailsAlbum album = albumList.get(i);
|
|
||||||
albumValuesBatch[i] = SyncUtils.contentValuesFromAlbum(hostId, album);
|
|
||||||
|
|
||||||
artistsCount += album.artistid.size();
|
|
||||||
genresCount += album.genreid.size();
|
|
||||||
}
|
|
||||||
contentResolver.bulkInsert(MediaContract.Albums.CONTENT_URI, albumValuesBatch);
|
|
||||||
|
|
||||||
// Iterate on each album, collect the artists and the genres and insert them
|
|
||||||
ContentValues albumArtistsValuesBatch[] = new ContentValues[artistsCount];
|
|
||||||
ContentValues albumGenresValuesBatch[] = new ContentValues[genresCount];
|
|
||||||
int artistCount = 0, genreCount = 0;
|
|
||||||
for (AudioType.DetailsAlbum album : albumList) {
|
|
||||||
for (int artistId : album.artistid) {
|
|
||||||
albumArtistsValuesBatch[artistCount] = new ContentValues();
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.HOST_ID, hostId);
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ALBUMID, album.albumid);
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ARTISTID, artistId);
|
|
||||||
artistCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int genreId : album.genreid) {
|
|
||||||
albumGenresValuesBatch[genreCount] = new ContentValues();
|
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.HOST_ID, hostId);
|
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.ALBUMID, album.albumid);
|
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.GENREID, genreId);
|
|
||||||
genreCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contentResolver.bulkInsert(MediaContract.AlbumArtists.CONTENT_URI, albumArtistsValuesBatch);
|
|
||||||
contentResolver.bulkInsert(MediaContract.AlbumGenres.CONTENT_URI, albumGenresValuesBatch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void insertSongs(Context context, int hostId) throws ApiException, IOException {
|
private static void insertSongs(Context context, SyncMusic syncMusic) throws ApiException, IOException {
|
||||||
AudioLibrary.GetSongs getSongs = new AudioLibrary.GetSongs();
|
AudioLibrary.GetSongs getSongs = new AudioLibrary.GetSongs();
|
||||||
ArrayList<AudioType.DetailsSong> songList = (ArrayList) getSongs.resultFromJson(Utils.readFile(context, "AudioLibrary.GetSongs.json")).items;
|
ArrayList<AudioType.DetailsSong> songList = (ArrayList)
|
||||||
|
getSongs.resultFromJson(Utils.readFile(context, "AudioLibrary.GetSongs.json")).items;
|
||||||
|
|
||||||
ContentValues songValuesBatch[] = new ContentValues[songList.size()];
|
syncMusic.insertSongsItems(songList, context.getContentResolver());
|
||||||
for (int i = 0; i < songList.size(); i++) {
|
|
||||||
AudioType.DetailsSong song = songList.get(i);
|
|
||||||
songValuesBatch[i] = SyncUtils.contentValuesFromSong(hostId, song);
|
|
||||||
}
|
|
||||||
context.getContentResolver().bulkInsert(MediaContract.Songs.CONTENT_URI, songValuesBatch);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Martijn Brekhof. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.xbmc.kore.testhelpers;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
import org.xbmc.kore.ui.SongsListFragment;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class TestUtils {
|
||||||
|
/**
|
||||||
|
* Tests if cursor contains all numbers from ids given column index.
|
||||||
|
* @param cursor
|
||||||
|
* @param columnIndex
|
||||||
|
* @param numbers
|
||||||
|
*/
|
||||||
|
public static void testCursorContainsNumbers(Cursor cursor, int columnIndex, int... numbers) {
|
||||||
|
HashMap<Integer, Boolean> idsFound = new HashMap<>();
|
||||||
|
for(int number : numbers) {
|
||||||
|
idsFound.put(number, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
do {
|
||||||
|
idsFound.put(cursor.getInt(columnIndex), true);
|
||||||
|
} while(cursor.moveToNext());
|
||||||
|
|
||||||
|
for(Map.Entry<Integer, Boolean> entry : idsFound.entrySet() ) {
|
||||||
|
int key = entry.getKey();
|
||||||
|
assertTrue("Id " + key + " not found", entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if cursor contains all numbers from start until end for given column index.
|
||||||
|
* @param columnIndex
|
||||||
|
* @param cursor
|
||||||
|
* @param start
|
||||||
|
* @param end
|
||||||
|
*/
|
||||||
|
public static void testCursorContainsRange(Cursor cursor, int columnIndex, int start, int end) {
|
||||||
|
HashMap<Integer, Boolean> idsFound = new HashMap<>();
|
||||||
|
for(int i = start; i <= end; i++) {
|
||||||
|
idsFound.put(i, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
do {
|
||||||
|
idsFound.put(cursor.getInt(columnIndex), true);
|
||||||
|
} while(cursor.moveToNext());
|
||||||
|
|
||||||
|
for(Map.Entry<Integer, Boolean> entry : idsFound.entrySet() ) {
|
||||||
|
int key = entry.getKey();
|
||||||
|
assertTrue("Id " + key + " not found", entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ package org.xbmc.kore.testhelpers;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.Cursor;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.test.rule.ActivityTestRule;
|
import android.support.test.rule.ActivityTestRule;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
|
@ -92,6 +93,15 @@ public class Utils {
|
||||||
isInitialized = false;
|
isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String cursorToString(Cursor cursor) {
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
for (String name : cursor.getColumnNames()) {
|
||||||
|
int index = cursor.getColumnIndex(name);
|
||||||
|
stringBuffer.append(name + "=" + cursor.getString(index) + "\n");
|
||||||
|
}
|
||||||
|
return stringBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private static void disableAnimations() {
|
private static void disableAnimations() {
|
||||||
int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION);
|
int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION);
|
||||||
if (permStatus == PackageManager.PERMISSION_GRANTED) {
|
if (permStatus == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
@ -127,4 +137,16 @@ public class Utils {
|
||||||
Log.e("SystemAnimations", "Could not change animation scale to " + animationScale + " :'(");
|
Log.e("SystemAnimations", "Could not change animation scale to " + animationScale + " :'(");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean moveCursorTo(Cursor cursor, int index, int item) {
|
||||||
|
if (( cursor == null ) || ( ! cursor.moveToFirst() ))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ( cursor.getInt(index) == item )
|
||||||
|
return true;
|
||||||
|
} while (cursor.moveToNext());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Martijn Brekhof. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.xbmc.kore.tests.mediaprovider;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.support.test.rule.ActivityTestRule;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.xbmc.kore.host.HostInfo;
|
||||||
|
import org.xbmc.kore.provider.MediaContract;
|
||||||
|
import org.xbmc.kore.testhelpers.Database;
|
||||||
|
import org.xbmc.kore.testhelpers.TestUtils;
|
||||||
|
import org.xbmc.kore.testhelpers.Utils;
|
||||||
|
import org.xbmc.kore.ui.MoviesActivity;
|
||||||
|
import org.xbmc.kore.utils.LogUtils;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class MediaProviderMusicTest {
|
||||||
|
private static HostInfo hostInfo;
|
||||||
|
private static Context context;
|
||||||
|
private ContentResolver contentResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that the activity MoviesActivity is only needed for context and is not tested
|
||||||
|
*/
|
||||||
|
@Rule
|
||||||
|
public ActivityTestRule<MoviesActivity> mActivityRule = new ActivityTestRule<>(
|
||||||
|
MoviesActivity.class);
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
context = mActivityRule.getActivity();
|
||||||
|
|
||||||
|
if (hostInfo == null) // We only need to fill the database the first time
|
||||||
|
hostInfo = Database.fill(context);
|
||||||
|
|
||||||
|
contentResolver = mActivityRule.getActivity().getContentResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanup() {
|
||||||
|
Database.flush(context, hostInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAllArtistsTest() {
|
||||||
|
Uri uri = MediaContract.Artists.buildArtistsListUri(hostInfo.getId());
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.Artist.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 227, cursor.getCount());
|
||||||
|
TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.ArtistsColumns.ARTISTID),
|
||||||
|
1, 94);
|
||||||
|
//Artist id 95 should be missing
|
||||||
|
TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.ArtistsColumns.ARTISTID),
|
||||||
|
96, 228);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryArtistTest() {
|
||||||
|
Uri uri = MediaContract.Artists.buildArtistUri(hostInfo.getId(), TestValues.Artist.artistId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.Artist.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.Artist.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAllAlbumsTest() {
|
||||||
|
Uri uri = MediaContract.Albums.buildAlbumsListUri(hostInfo.getId());
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 232, cursor.getCount());
|
||||||
|
int columnIndex = cursor.getColumnIndex(MediaContract.AlbumsColumns.ALBUMID);
|
||||||
|
TestUtils.testCursorContainsRange(cursor, columnIndex, 1, 75);
|
||||||
|
TestUtils.testCursorContainsRange(cursor, columnIndex, 77, 82);
|
||||||
|
TestUtils.testCursorContainsRange(cursor, columnIndex, 84, 234);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAlbumTest() {
|
||||||
|
Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(), TestValues.Album.albumId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.Album.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAlbumsForArtistTest() {
|
||||||
|
Uri uri = MediaContract.AlbumArtists.buildAlbumsForArtistListUri(hostInfo.getId(),
|
||||||
|
TestValues.Artist.artistId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.Album.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAlbumsForGenreTest() {
|
||||||
|
int genreId = 13;
|
||||||
|
Uri uri = MediaContract.AlbumGenres.buildAlbumsForGenreListUri(hostInfo.getId(), genreId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.Album.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 31, cursor.getCount());
|
||||||
|
TestUtils.testCursorContainsNumbers(cursor, cursor.getColumnIndex(MediaContract.Albums.ALBUMID),
|
||||||
|
28, 43, 47, 66, 100);
|
||||||
|
TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.Albums.ALBUMID),
|
||||||
|
50, 55);
|
||||||
|
TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.Albums.ALBUMID),
|
||||||
|
201, 220);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAlbumSongsTest() {
|
||||||
|
Uri uri = MediaContract.Songs.buildAlbumSongsListUri(hostInfo.getId(), TestValues.Album.albumId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, new String[] {MediaContract.Songs.SONGID}, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 17, cursor.getCount());
|
||||||
|
TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.SongsColumns.SONGID),
|
||||||
|
96, 112);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAlbumWithoutArtist() {
|
||||||
|
Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(),
|
||||||
|
TestValues.AlbumWithoutArtist.albumId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.AlbumWithoutArtist.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.AlbumWithoutArtist.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAlbumWithMultipleArtists() {
|
||||||
|
Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(),
|
||||||
|
TestValues.AlbumWithMultipleArtists.albumId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.AlbumWithMultipleArtists.PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.AlbumWithMultipleArtists.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryArtistSongsTest() {
|
||||||
|
Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(), TestValues.ArtistSong.artistId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.ArtistSong.PROJECTION, null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 17, cursor.getCount());
|
||||||
|
TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.SongsColumns.SONGID),
|
||||||
|
96, 112);
|
||||||
|
assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID),
|
||||||
|
TestValues.ArtistSong.songId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void querySongWithArtistWithoutAlbumTest() {
|
||||||
|
Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(),
|
||||||
|
TestValues.SongWithArtistWithoutAlbum.artistId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.SongWithArtistWithoutAlbum.PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
Utils.cursorToString(cursor);
|
||||||
|
TestValues.SongWithArtistWithoutAlbum.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryFirstArtistSongWithMultipleArtistsTest() {
|
||||||
|
Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(),
|
||||||
|
TestValues.SongWithMultipleArtists.firstArtistId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.SongWithMultipleArtists.PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.SongWithMultipleArtists.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void querySecondArtistSongWithMultipleArtistsTest() {
|
||||||
|
Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(),
|
||||||
|
TestValues.SongWithMultipleArtists.secondArtistId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri, TestValues.SongWithMultipleArtists.PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.SongWithMultipleArtists.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryThirdArtistSongWithMultipleArtistsTest() {
|
||||||
|
Uri uri = MediaContract.Songs.buildArtistSongsListUri(hostInfo.getId(),
|
||||||
|
TestValues.SongWithMultipleArtists.thirdArtistId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri,
|
||||||
|
TestValues.SongWithMultipleArtists.PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
TestValues.SongWithMultipleArtists.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAllSongsTest() {
|
||||||
|
Uri uri = MediaContract.Songs.buildSongsListUri(hostInfo.getId());
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri,
|
||||||
|
TestValues.ArtistSong.PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1804, cursor.getCount());
|
||||||
|
TestUtils.testCursorContainsRange(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID),
|
||||||
|
1, 1804);
|
||||||
|
|
||||||
|
//Test if list also contains a song WITH an album AND an artist
|
||||||
|
assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID),
|
||||||
|
TestValues.SongWithAlbumAndArtist.songId));
|
||||||
|
TestValues.SongWithAlbumAndArtist.test(cursor);
|
||||||
|
|
||||||
|
//Test if list also contains a song WITHOUT an album but WITH an artist
|
||||||
|
assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID),
|
||||||
|
TestValues.SongWithArtistWithoutAlbum.songId));
|
||||||
|
TestValues.SongWithArtistWithoutAlbum.test(cursor);
|
||||||
|
|
||||||
|
//Test if list also contains a song WITH an album but WITHOUT an artist
|
||||||
|
assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID),
|
||||||
|
TestValues.SongWithAlbumWithoutArtist.songId));
|
||||||
|
TestValues.SongWithAlbumWithoutArtist.test(cursor);
|
||||||
|
|
||||||
|
//Test if list contains a song WITH MULTIPLE artists
|
||||||
|
assertTrue(Utils.moveCursorTo(cursor, cursor.getColumnIndex(MediaContract.Songs.SONGID),
|
||||||
|
TestValues.SongWithMultipleArtists.songId));
|
||||||
|
TestValues.SongWithMultipleArtists.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAlbumWithMultipleArtistsTest() {
|
||||||
|
Uri uri = MediaContract.Albums.buildAlbumUri(hostInfo.getId(),
|
||||||
|
TestValues.AlbumWithMultipleArtists.albumId);
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri,
|
||||||
|
TestValues.AlbumWithMultipleArtists.PROJECTION,
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 1, cursor.getCount());
|
||||||
|
assertTrue(cursor.moveToFirst());
|
||||||
|
LogUtils.LOGD("MediaProviderMusicTest", Utils.cursorToString(cursor));
|
||||||
|
TestValues.AlbumWithMultipleArtists.test(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryAllGenresTest() {
|
||||||
|
Uri uri = MediaContract.AudioGenres.buildAudioGenresListUri(hostInfo.getId());
|
||||||
|
|
||||||
|
Cursor cursor = contentResolver.query(uri,
|
||||||
|
new String[] {MediaContract.AudioGenresColumns.GENREID},
|
||||||
|
null, null, null);
|
||||||
|
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals("cursor size ", 39, cursor.getCount());
|
||||||
|
TestUtils.testCursorContainsRange(cursor,
|
||||||
|
cursor.getColumnIndex(MediaContract.AudioGenresColumns.GENREID),
|
||||||
|
1, 39);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Martijn Brekhof. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.xbmc.kore.tests.mediaprovider;
|
||||||
|
|
||||||
|
import android.database.Cursor;
|
||||||
|
|
||||||
|
import org.xbmc.kore.provider.MediaContract;
|
||||||
|
import org.xbmc.kore.provider.MediaDatabase;
|
||||||
|
import org.xbmc.kore.provider.MediaProvider;
|
||||||
|
import org.xbmc.kore.ui.AlbumListFragment;
|
||||||
|
import org.xbmc.kore.ui.ArtistListFragment;
|
||||||
|
import org.xbmc.kore.ui.ArtistOverviewFragment;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class TestValues {
|
||||||
|
public static class Artist {
|
||||||
|
public static int artistId = 13;
|
||||||
|
public static String artist = "Bernstein, Charles";
|
||||||
|
|
||||||
|
public static String[] PROJECTION = MediaContract.Artists.ALL_COLUMNS;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
assertEquals(TestValues.Artist.artistId, cursor.getInt(cursor.getColumnIndex(MediaContract.ArtistsColumns.ARTISTID)));
|
||||||
|
assertEquals(TestValues.Artist.artist, cursor.getString(cursor.getColumnIndex(MediaContract.ArtistsColumns.ARTIST)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Album {
|
||||||
|
public static int albumId = 13;
|
||||||
|
public static String title = "The Entity";
|
||||||
|
public static String displayArtist = "Bernstein, Charles";
|
||||||
|
public static int year = 1982;
|
||||||
|
public static String genre = "Soundtrack";
|
||||||
|
|
||||||
|
public static String[] PROJECTION = MediaContract.Albums.ALL_COLUMNS;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
int resultAlbumId = cursor.getInt(cursor.getColumnIndex(MediaContract.AlbumsColumns.ALBUMID));
|
||||||
|
assertEquals(albumId, resultAlbumId);
|
||||||
|
String resultTitle = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.TITLE));
|
||||||
|
assertEquals(title, resultTitle);
|
||||||
|
String resultArtist = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.DISPLAYARTIST));
|
||||||
|
assertEquals(displayArtist, resultArtist);
|
||||||
|
String resultGenre = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.GENRE));
|
||||||
|
assertEquals(genre, resultGenre);
|
||||||
|
int resultYear = cursor.getInt(cursor.getColumnIndex(MediaContract.AlbumsColumns.YEAR));
|
||||||
|
assertEquals(year, resultYear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AlbumWithoutArtist {
|
||||||
|
public static int albumId = 82;
|
||||||
|
public static String title = "The Album";
|
||||||
|
public static String displayArtist = "";
|
||||||
|
public static int year = 0;
|
||||||
|
public static String genre = "";
|
||||||
|
|
||||||
|
public static String[] PROJECTION = MediaContract.Albums.ALL_COLUMNS;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
int resultAlbumId = cursor.getInt(cursor.getColumnIndex(MediaContract.AlbumsColumns.ALBUMID));
|
||||||
|
assertEquals(albumId, resultAlbumId);
|
||||||
|
String resultTitle = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.TITLE));
|
||||||
|
assertEquals(title, resultTitle);
|
||||||
|
String resultArtist = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.DISPLAYARTIST));
|
||||||
|
assertEquals(displayArtist, resultArtist);
|
||||||
|
String resultGenre = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.GENRE));
|
||||||
|
assertEquals(genre, resultGenre);
|
||||||
|
int resultYear = cursor.getInt(cursor.getColumnIndex(MediaContract.AlbumsColumns.YEAR));
|
||||||
|
assertEquals(year, resultYear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AlbumWithMultipleArtists {
|
||||||
|
public static int albumId = 234;
|
||||||
|
public static String title = "ThreeArtistsAlbum";
|
||||||
|
public static String displayArtist = "First artist / Second artist / Third artist";
|
||||||
|
public static int year = 0;
|
||||||
|
public static String genre = "";
|
||||||
|
|
||||||
|
public static String[] PROJECTION = MediaContract.Albums.ALL_COLUMNS;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
int resultAlbumId = cursor.getInt(cursor.getColumnIndex(MediaContract.AlbumsColumns.ALBUMID));
|
||||||
|
assertEquals(albumId, resultAlbumId);
|
||||||
|
String resultTitle = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.TITLE));
|
||||||
|
assertEquals(title, resultTitle);
|
||||||
|
String resultArtist = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.DISPLAYARTIST));
|
||||||
|
assertEquals(displayArtist, resultArtist);
|
||||||
|
String resultGenre = cursor.getString(cursor.getColumnIndex(MediaContract.AlbumsColumns.GENRE));
|
||||||
|
assertEquals(genre, resultGenre);
|
||||||
|
int resultYear = cursor.getInt(cursor.getColumnIndex(MediaContract.AlbumsColumns.YEAR));
|
||||||
|
assertEquals(year, resultYear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ArtistSong {
|
||||||
|
public static int songId = 96;
|
||||||
|
public static int artistId = Artist.artistId;
|
||||||
|
public static int albumId = Album.albumId;
|
||||||
|
public static String title = "Intro & Main Title";
|
||||||
|
public static String[] PROJECTION = new String[] { MediaContract.Songs.SONGID,
|
||||||
|
MediaContract.Songs.TITLE,
|
||||||
|
MediaContract.Songs.ALBUMID,
|
||||||
|
MediaContract.SongArtists.ARTISTID,
|
||||||
|
MediaContract.Artists.ARTIST };
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
assertEquals(songId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.SONGID)));
|
||||||
|
assertEquals(title, cursor.getString(cursor.getColumnIndex(MediaContract.Songs.TITLE)));
|
||||||
|
assertEquals(albumId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.ALBUMID)));
|
||||||
|
assertEquals(artistId, cursor.getInt(cursor.getColumnIndex(MediaContract.SongArtists.ARTISTID)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SongWithAlbumAndArtist {
|
||||||
|
public static int songId = 1487;
|
||||||
|
public static int artistId = 195;
|
||||||
|
public static int albumId = 201;
|
||||||
|
public static String title = "The Lone Ranger (William Tell Overture)";
|
||||||
|
|
||||||
|
public static String[] PROJECTION = ArtistSong.PROJECTION;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
assertEquals(songId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.SONGID)));
|
||||||
|
assertEquals(title, cursor.getString(cursor.getColumnIndex(MediaContract.Songs.TITLE)));
|
||||||
|
assertEquals(albumId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.ALBUMID)));
|
||||||
|
assertEquals(artistId, cursor.getInt(cursor.getColumnIndex(MediaContract.SongArtists.ARTISTID)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SongWithAlbumWithoutArtist {
|
||||||
|
public static int songId = 1219;
|
||||||
|
public static int artistId = 0;
|
||||||
|
public static String title = "Unknown";
|
||||||
|
public static int albumId = 82;
|
||||||
|
|
||||||
|
public static String[] PROJECTION = ArtistSong.PROJECTION;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
assertEquals(songId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.SONGID)));
|
||||||
|
assertEquals(title, cursor.getString(cursor.getColumnIndex(MediaContract.Songs.TITLE)));
|
||||||
|
assertEquals(albumId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.ALBUMID)));
|
||||||
|
assertEquals(artistId, cursor.getInt(cursor.getColumnIndex(MediaContract.SongArtists.ARTISTID)));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SongWithArtistWithoutAlbum {
|
||||||
|
public static int songId = 1128;
|
||||||
|
public static int artistId = 73;
|
||||||
|
public static int albumId = 76;
|
||||||
|
public static String title = "Unknown";
|
||||||
|
|
||||||
|
public static String[] PROJECTION = ArtistSong.PROJECTION;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
assertEquals(songId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.SONGID)));
|
||||||
|
assertEquals(title, cursor.getString(cursor.getColumnIndex(MediaContract.Songs.TITLE)));
|
||||||
|
assertEquals(albumId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.ALBUMID)));
|
||||||
|
assertEquals(artistId, cursor.getInt(cursor.getColumnIndex(MediaContract.SongArtists.ARTISTID)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SongWithMultipleArtists {
|
||||||
|
public static int songId = 1804;
|
||||||
|
public static int firstArtistId = 226;
|
||||||
|
public static int secondArtistId = 227;
|
||||||
|
public static int thirdArtistId = 228;
|
||||||
|
public static int albumId = 234;
|
||||||
|
public static String title = "threeartists";
|
||||||
|
|
||||||
|
public static String[] PROJECTION = ArtistSong.PROJECTION;
|
||||||
|
|
||||||
|
public static void test(Cursor cursor) {
|
||||||
|
assertEquals(songId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.SONGID)));
|
||||||
|
assertEquals(title, cursor.getString(cursor.getColumnIndex(MediaContract.Songs.TITLE)));
|
||||||
|
assertEquals(albumId, cursor.getInt(cursor.getColumnIndex(MediaContract.Songs.ALBUMID)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,8 +49,8 @@ public class RestoreSearchQueryViewPagerTest {
|
||||||
private final int ARTIST_SEARCH_QUERY_LIST_SIZE = 2;
|
private final int ARTIST_SEARCH_QUERY_LIST_SIZE = 2;
|
||||||
private final String ALBUMS_SEARCH_QUERY = "tes";
|
private final String ALBUMS_SEARCH_QUERY = "tes";
|
||||||
private final int ALBUM_SEARCH_QUERY_LIST_SIZE = 3;
|
private final int ALBUM_SEARCH_QUERY_LIST_SIZE = 3;
|
||||||
private final int ARTIST_COMPLETE_LIST_SIZE = 224;
|
private final int ARTIST_COMPLETE_LIST_SIZE = 227;
|
||||||
private final int ALBUM_COMPLETE_LIST_SIZE = 231;
|
private final int ALBUM_COMPLETE_LIST_SIZE = 232;
|
||||||
|
|
||||||
private LoaderIdlingResource loaderIdlingResource;
|
private LoaderIdlingResource loaderIdlingResource;
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
"jsonrpc" : "2.0",
|
"jsonrpc" : "2.0",
|
||||||
"result" : {
|
"result" : {
|
||||||
"limits" : {
|
"limits" : {
|
||||||
"total" : 231,
|
"total" : 232,
|
||||||
"start" : 0,
|
"start" : 0,
|
||||||
"end" : 231
|
"end" : 234
|
||||||
},
|
},
|
||||||
"albums" : [
|
"albums" : [
|
||||||
{
|
{
|
||||||
|
@ -7538,6 +7538,41 @@
|
||||||
"theme" : [],
|
"theme" : [],
|
||||||
"musicbrainzalbumid" : "",
|
"musicbrainzalbumid" : "",
|
||||||
"playcount" : 0
|
"playcount" : 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"musicbrainzalbumid" : "",
|
||||||
|
"description" : "",
|
||||||
|
"artist" : [
|
||||||
|
"First artist",
|
||||||
|
"Second artist",
|
||||||
|
"Third artist"
|
||||||
|
],
|
||||||
|
"type" : "",
|
||||||
|
"title" : "ThreeArtistsAlbum",
|
||||||
|
"label" : "ThreeArtistsAlbum",
|
||||||
|
"rating" : 0,
|
||||||
|
"albumlabel" : "",
|
||||||
|
"playcount" : 0,
|
||||||
|
"albumid" : 234,
|
||||||
|
"thumbnail" : "",
|
||||||
|
"genreid" : [],
|
||||||
|
"artistid" : [
|
||||||
|
226,
|
||||||
|
227,
|
||||||
|
228
|
||||||
|
],
|
||||||
|
"mood" : [],
|
||||||
|
"theme" : [],
|
||||||
|
"genre" : [],
|
||||||
|
"displayartist" : "First artist / Second artist / Third artist",
|
||||||
|
"style" : [],
|
||||||
|
"fanart" : "",
|
||||||
|
"year" : 0,
|
||||||
|
"musicbrainzalbumartistid" : [
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -4482,11 +4482,71 @@
|
||||||
"fanart" : "",
|
"fanart" : "",
|
||||||
"mood" : [],
|
"mood" : [],
|
||||||
"style" : []
|
"style" : []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description" : "",
|
||||||
|
"disbanded" : "",
|
||||||
|
"artist" : "First artist",
|
||||||
|
"instrument" : [],
|
||||||
|
"label" : "First artist",
|
||||||
|
"born" : "",
|
||||||
|
"yearsactive" : [],
|
||||||
|
"genre" : [],
|
||||||
|
"thumbnail" : "",
|
||||||
|
"mood" : [],
|
||||||
|
"artistid" : 226,
|
||||||
|
"musicbrainzartistid" : [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"died" : "",
|
||||||
|
"formed" : "",
|
||||||
|
"style" : [],
|
||||||
|
"fanart" : ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description" : "",
|
||||||
|
"disbanded" : "",
|
||||||
|
"artist" : "Second artist",
|
||||||
|
"instrument" : [],
|
||||||
|
"label" : "Second artist",
|
||||||
|
"born" : "",
|
||||||
|
"yearsactive" : [],
|
||||||
|
"genre" : [],
|
||||||
|
"thumbnail" : "",
|
||||||
|
"mood" : [],
|
||||||
|
"artistid" : 227,
|
||||||
|
"musicbrainzartistid" : [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"died" : "",
|
||||||
|
"formed" : "",
|
||||||
|
"style" : [],
|
||||||
|
"fanart" : ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description" : "",
|
||||||
|
"disbanded" : "",
|
||||||
|
"artist" : "Third artist",
|
||||||
|
"instrument" : [],
|
||||||
|
"label" : "Third artist",
|
||||||
|
"born" : "",
|
||||||
|
"yearsactive" : [],
|
||||||
|
"genre" : [],
|
||||||
|
"thumbnail" : "",
|
||||||
|
"mood" : [],
|
||||||
|
"artistid" : 228,
|
||||||
|
"musicbrainzartistid" : [
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"died" : "",
|
||||||
|
"formed" : "",
|
||||||
|
"style" : [],
|
||||||
|
"fanart" : ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"limits" : {
|
"limits" : {
|
||||||
"total" : 224,
|
"total" : 227,
|
||||||
"end" : 224,
|
"end" : 228,
|
||||||
"start" : 0
|
"start" : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75109,12 +75109,58 @@
|
||||||
"songid" : 1618,
|
"songid" : 1618,
|
||||||
"title" : "Reel - Upstairs in a Tent",
|
"title" : "Reel - Upstairs in a Tent",
|
||||||
"album" : "Ireland's Best Fiddle Tunes Disk 2"
|
"album" : "Ireland's Best Fiddle Tunes Disk 2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"musicbrainzalbumartistid" : [],
|
||||||
|
"year" : 0,
|
||||||
|
"albumartistid" : [
|
||||||
|
226,
|
||||||
|
227,
|
||||||
|
228
|
||||||
|
],
|
||||||
|
"disc" : 0,
|
||||||
|
"musicbrainztrackid" : "",
|
||||||
|
"fanart" : "",
|
||||||
|
"file" : "/Users/martijn/Projects/dummymediafiles/media/music/ThreeArtists/ThreeArtistsAlbum/01-threeartists.mp3",
|
||||||
|
"genre" : [],
|
||||||
|
"displayartist" : "First artist / Second artist / Third artist",
|
||||||
|
"comment" : "",
|
||||||
|
"musicbrainzartistid" : [],
|
||||||
|
"artistid" : [
|
||||||
|
226,
|
||||||
|
227,
|
||||||
|
228
|
||||||
|
],
|
||||||
|
"lastplayed" : "",
|
||||||
|
"songid" : 1804,
|
||||||
|
"playcount" : 0,
|
||||||
|
"thumbnail" : "",
|
||||||
|
"albumartist" : [
|
||||||
|
"First artist",
|
||||||
|
"Second artist",
|
||||||
|
"Third artist"
|
||||||
|
],
|
||||||
|
"albumid" : 234,
|
||||||
|
"genreid" : [],
|
||||||
|
"track" : 1,
|
||||||
|
"label" : "threeartists",
|
||||||
|
"title" : "threeartists",
|
||||||
|
"rating" : 0,
|
||||||
|
"artist" : [
|
||||||
|
"First artist",
|
||||||
|
"Second artist",
|
||||||
|
"Third artist"
|
||||||
|
],
|
||||||
|
"lyrics" : "",
|
||||||
|
"duration" : 5,
|
||||||
|
"album" : "ThreeArtistsAlbum",
|
||||||
|
"musicbrainzalbumid" : ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"limits" : {
|
"limits" : {
|
||||||
"end" : 1803,
|
"end" : 1804,
|
||||||
"start" : 0,
|
"start" : 0,
|
||||||
"total" : 1803
|
"total" : 1804
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jsonrpc" : "2.0"
|
"jsonrpc" : "2.0"
|
||||||
|
|
|
@ -805,7 +805,7 @@ public class MediaProvider extends ContentProvider {
|
||||||
* {@link MediaContract} fields that are fully qualified with a specific
|
* {@link MediaContract} fields that are fully qualified with a specific
|
||||||
* parent {@link MediaDatabase.Tables}. Used when needed to work around SQL ambiguity.
|
* parent {@link MediaDatabase.Tables}. Used when needed to work around SQL ambiguity.
|
||||||
*/
|
*/
|
||||||
private interface Qualified {
|
public interface Qualified {
|
||||||
String ALBUM_ARTISTS_HOST_ID =
|
String ALBUM_ARTISTS_HOST_ID =
|
||||||
MediaDatabase.Tables.ALBUM_ARTISTS + "." + MediaContract.AlbumArtists.HOST_ID;
|
MediaDatabase.Tables.ALBUM_ARTISTS + "." + MediaContract.AlbumArtists.HOST_ID;
|
||||||
String ALBUM_ARTISTS_ARTISTID =
|
String ALBUM_ARTISTS_ARTISTID =
|
||||||
|
|
|
@ -86,6 +86,7 @@ public class SyncMusic extends SyncItem {
|
||||||
AudioType.FieldsArtists.FANART,
|
AudioType.FieldsArtists.FANART,
|
||||||
AudioType.FieldsArtists.THUMBNAIL
|
AudioType.FieldsArtists.THUMBNAIL
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all artists recursively and forwards the call to Genres
|
* Gets all artists recursively and forwards the call to Genres
|
||||||
* Genres->Albums->Songs
|
* Genres->Albums->Songs
|
||||||
|
@ -115,13 +116,7 @@ public class SyncMusic extends SyncItem {
|
||||||
// First delete all music info
|
// First delete all music info
|
||||||
if (startIdx == 0) deleteMusicInfo(contentResolver, hostId);
|
if (startIdx == 0) deleteMusicInfo(contentResolver, hostId);
|
||||||
|
|
||||||
// Insert artists
|
insertArtists(items, contentResolver);
|
||||||
ContentValues artistValuesBatch[] = new ContentValues[items.size()];
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
|
||||||
AudioType.DetailsArtist artist = items.get(i);
|
|
||||||
artistValuesBatch[i] = SyncUtils.contentValuesFromArtist(hostId, artist);
|
|
||||||
}
|
|
||||||
contentResolver.bulkInsert(MediaContract.Artists.CONTENT_URI, artistValuesBatch);
|
|
||||||
|
|
||||||
if (moreItemsAvailable(limitsReturned)) {
|
if (moreItemsAvailable(limitsReturned)) {
|
||||||
LogUtils.LOGD(TAG, "chainCallSyncArtists: More results on media center, recursing.");
|
LogUtils.LOGD(TAG, "chainCallSyncArtists: More results on media center, recursing.");
|
||||||
|
@ -151,6 +146,8 @@ public class SyncMusic extends SyncItem {
|
||||||
where, new String[]{String.valueOf(hostId)});
|
where, new String[]{String.valueOf(hostId)});
|
||||||
contentResolver.delete(MediaContract.AlbumGenres.CONTENT_URI,
|
contentResolver.delete(MediaContract.AlbumGenres.CONTENT_URI,
|
||||||
where, new String[]{String.valueOf(hostId)});
|
where, new String[]{String.valueOf(hostId)});
|
||||||
|
contentResolver.delete(MediaContract.SongArtists.CONTENT_URI,
|
||||||
|
where, new String[]{String.valueOf(hostId)});
|
||||||
contentResolver.delete(MediaContract.Songs.CONTENT_URI,
|
contentResolver.delete(MediaContract.Songs.CONTENT_URI,
|
||||||
where, new String[]{String.valueOf(hostId)});
|
where, new String[]{String.valueOf(hostId)});
|
||||||
contentResolver.delete(MediaContract.AudioGenres.CONTENT_URI,
|
contentResolver.delete(MediaContract.AudioGenres.CONTENT_URI,
|
||||||
|
@ -178,16 +175,9 @@ public class SyncMusic extends SyncItem {
|
||||||
action.execute(hostConnection, new ApiCallback<List<LibraryType.DetailsGenre>>() {
|
action.execute(hostConnection, new ApiCallback<List<LibraryType.DetailsGenre>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<LibraryType.DetailsGenre> result) {
|
public void onSuccess(List<LibraryType.DetailsGenre> result) {
|
||||||
if (result == null) result = new ArrayList<>(0); // Safeguard
|
if (result != null)
|
||||||
ContentValues genresValuesBatch[] = new ContentValues[result.size()];
|
insertGenresItems(result, contentResolver);
|
||||||
|
|
||||||
for (int i = 0; i < result.size(); i++) {
|
|
||||||
LibraryType.DetailsGenre genre = result.get(i);
|
|
||||||
genresValuesBatch[i] = SyncUtils.contentValuesFromAudioGenre(hostId, genre);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the genres and proceed to albums
|
|
||||||
contentResolver.bulkInsert(MediaContract.AudioGenres.CONTENT_URI, genresValuesBatch);
|
|
||||||
chainCallSyncAlbums(orchestrator, hostConnection, callbackHandler, contentResolver, 0);
|
chainCallSyncAlbums(orchestrator, hostConnection, callbackHandler, contentResolver, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,44 +230,7 @@ public class SyncMusic extends SyncItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the partial results
|
// Insert the partial results
|
||||||
ContentValues albumValuesBatch[] = new ContentValues[items.size()];
|
insertAlbumsItems(items, contentResolver);
|
||||||
int artistsCount = 0, genresCount = 0;
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
|
||||||
AudioType.DetailsAlbum album = items.get(i);
|
|
||||||
albumValuesBatch[i] = SyncUtils.contentValuesFromAlbum(hostId, album);
|
|
||||||
|
|
||||||
artistsCount += album.artistid.size();
|
|
||||||
genresCount += album.genreid.size();
|
|
||||||
}
|
|
||||||
contentResolver.bulkInsert(MediaContract.Albums.CONTENT_URI, albumValuesBatch);
|
|
||||||
|
|
||||||
LogUtils.LOGD(TAG, "Finished inserting albums in: " +
|
|
||||||
(System.currentTimeMillis() - albumSyncStartTime));
|
|
||||||
|
|
||||||
// Iterate on each album, collect the artists and the genres and insert them
|
|
||||||
ContentValues albumArtistsValuesBatch[] = new ContentValues[artistsCount];
|
|
||||||
ContentValues albumGenresValuesBatch[] = new ContentValues[genresCount];
|
|
||||||
int artistCount = 0, genreCount = 0;
|
|
||||||
for (AudioType.DetailsAlbum album : items) {
|
|
||||||
for (int artistId : album.artistid) {
|
|
||||||
albumArtistsValuesBatch[artistCount] = new ContentValues();
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.HOST_ID, hostId);
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ALBUMID, album.albumid);
|
|
||||||
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ARTISTID, artistId);
|
|
||||||
artistCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int genreId : album.genreid) {
|
|
||||||
albumGenresValuesBatch[genreCount] = new ContentValues();
|
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.HOST_ID, hostId);
|
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.ALBUMID, album.albumid);
|
|
||||||
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.GENREID, genreId);
|
|
||||||
genreCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contentResolver.bulkInsert(MediaContract.AlbumArtists.CONTENT_URI, albumArtistsValuesBatch);
|
|
||||||
contentResolver.bulkInsert(MediaContract.AlbumGenres.CONTENT_URI, albumGenresValuesBatch);
|
|
||||||
|
|
||||||
LogUtils.LOGD(TAG, "Finished inserting artists and genres in: " +
|
LogUtils.LOGD(TAG, "Finished inserting artists and genres in: " +
|
||||||
(System.currentTimeMillis() - albumSyncStartTime));
|
(System.currentTimeMillis() - albumSyncStartTime));
|
||||||
|
@ -346,29 +299,8 @@ public class SyncMusic extends SyncItem {
|
||||||
limitsReturned = result.limits;
|
limitsReturned = result.limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
int totalArtistsCount = 0;
|
|
||||||
// Save partial results to DB
|
// Save partial results to DB
|
||||||
ContentValues songValuesBatch[] = new ContentValues[items.size()];
|
insertSongsItems(items, contentResolver);
|
||||||
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)) {
|
if (moreItemsAvailable(limitsReturned)) {
|
||||||
LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing.");
|
LogUtils.LOGD(TAG, "chainCallSyncSongs: More results on media center, recursing.");
|
||||||
|
@ -384,12 +316,98 @@ public class SyncMusic extends SyncItem {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(int errorCode, String description) {
|
public void onError(int errorCode, String description) {
|
||||||
// Ok, something bad happend, just quit
|
// Ok, something bad happened, just quit
|
||||||
orchestrator.syncItemFailed(errorCode, description);
|
orchestrator.syncItemFailed(errorCode, description);
|
||||||
}
|
}
|
||||||
}, callbackHandler);
|
}, callbackHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void insertArtists(List<AudioType.DetailsArtist> items, ContentResolver contentResolver) {
|
||||||
|
ContentValues artistValuesBatch[] = new ContentValues[items.size()];
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
AudioType.DetailsArtist artist = items.get(i);
|
||||||
|
artistValuesBatch[i] = SyncUtils.contentValuesFromArtist(hostId, artist);
|
||||||
|
}
|
||||||
|
contentResolver.bulkInsert(MediaContract.Artists.CONTENT_URI, artistValuesBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertGenresItems(List<LibraryType.DetailsGenre> items, ContentResolver contentResolver) {
|
||||||
|
ContentValues genresValuesBatch[] = new ContentValues[items.size()];
|
||||||
|
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
LibraryType.DetailsGenre genre = items.get(i);
|
||||||
|
genresValuesBatch[i] = SyncUtils.contentValuesFromAudioGenre(hostId, genre);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the genres and proceed to albums
|
||||||
|
contentResolver.bulkInsert(MediaContract.AudioGenres.CONTENT_URI, genresValuesBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertAlbumsItems(List<AudioType.DetailsAlbum> items, ContentResolver contentResolver) {
|
||||||
|
ContentValues albumValuesBatch[] = new ContentValues[items.size()];
|
||||||
|
int artistsCount = 0, genresCount = 0;
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
AudioType.DetailsAlbum album = items.get(i);
|
||||||
|
albumValuesBatch[i] = SyncUtils.contentValuesFromAlbum(hostId, album);
|
||||||
|
|
||||||
|
artistsCount += album.artistid.size();
|
||||||
|
genresCount += album.genreid.size();
|
||||||
|
}
|
||||||
|
contentResolver.bulkInsert(MediaContract.Albums.CONTENT_URI, albumValuesBatch);
|
||||||
|
|
||||||
|
// Iterate on each album, collect the artists and the genres and insert them
|
||||||
|
ContentValues albumArtistsValuesBatch[] = new ContentValues[artistsCount];
|
||||||
|
ContentValues albumGenresValuesBatch[] = new ContentValues[genresCount];
|
||||||
|
int artistCount = 0, genreCount = 0;
|
||||||
|
for (AudioType.DetailsAlbum album : items) {
|
||||||
|
for (int artistId : album.artistid) {
|
||||||
|
albumArtistsValuesBatch[artistCount] = new ContentValues();
|
||||||
|
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.HOST_ID, hostId);
|
||||||
|
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ALBUMID, album.albumid);
|
||||||
|
albumArtistsValuesBatch[artistCount].put(MediaContract.AlbumArtists.ARTISTID, artistId);
|
||||||
|
artistCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int genreId : album.genreid) {
|
||||||
|
albumGenresValuesBatch[genreCount] = new ContentValues();
|
||||||
|
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.HOST_ID, hostId);
|
||||||
|
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.ALBUMID, album.albumid);
|
||||||
|
albumGenresValuesBatch[genreCount].put(MediaContract.AlbumGenres.GENREID, genreId);
|
||||||
|
genreCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentResolver.bulkInsert(MediaContract.AlbumArtists.CONTENT_URI, albumArtistsValuesBatch);
|
||||||
|
contentResolver.bulkInsert(MediaContract.AlbumGenres.CONTENT_URI, albumGenresValuesBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insertSongsItems(List<AudioType.DetailsSong> items, ContentResolver contentResolver) {
|
||||||
|
ContentValues songValuesBatch[] = new ContentValues[items.size()];
|
||||||
|
int totalArtistsCount = 0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean moreItemsAvailable(ListType.LimitsReturned limitsReturned) {
|
private boolean moreItemsAvailable(ListType.LimitsReturned limitsReturned) {
|
||||||
boolean moreItemsAvailable = false;
|
boolean moreItemsAvailable = false;
|
||||||
if (limitsReturned != null) {
|
if (limitsReturned != null) {
|
||||||
|
|
|
@ -710,7 +710,7 @@ public class AlbumDetailsFragment extends AbstractDetailsFragment
|
||||||
/**
|
/**
|
||||||
* Album details query parameters.
|
* Album details query parameters.
|
||||||
*/
|
*/
|
||||||
private interface AlbumDetailsQuery {
|
public interface AlbumDetailsQuery {
|
||||||
String[] PROJECTION = {
|
String[] PROJECTION = {
|
||||||
BaseColumns._ID,
|
BaseColumns._ID,
|
||||||
MediaContract.Albums.TITLE,
|
MediaContract.Albums.TITLE,
|
||||||
|
@ -739,7 +739,7 @@ public class AlbumDetailsFragment extends AbstractDetailsFragment
|
||||||
/**
|
/**
|
||||||
* Movie cast list query parameters.
|
* Movie cast list query parameters.
|
||||||
*/
|
*/
|
||||||
private interface AlbumSongsListQuery {
|
public interface AlbumSongsListQuery {
|
||||||
String[] PROJECTION = {
|
String[] PROJECTION = {
|
||||||
BaseColumns._ID,
|
BaseColumns._ID,
|
||||||
MediaContract.Songs.TITLE,
|
MediaContract.Songs.TITLE,
|
||||||
|
|
|
@ -163,7 +163,7 @@ public class AlbumListFragment extends AbstractCursorListFragment {
|
||||||
/**
|
/**
|
||||||
* Album list query parameters.
|
* Album list query parameters.
|
||||||
*/
|
*/
|
||||||
private interface AlbumListQuery {
|
public interface AlbumListQuery {
|
||||||
String[] PROJECTION = {
|
String[] PROJECTION = {
|
||||||
BaseColumns._ID,
|
BaseColumns._ID,
|
||||||
MediaContract.Albums.ALBUMID,
|
MediaContract.Albums.ALBUMID,
|
||||||
|
|
|
@ -108,7 +108,7 @@ public class AudioGenresListFragment extends AbstractCursorListFragment {
|
||||||
/**
|
/**
|
||||||
* Audio genres list query parameters.
|
* Audio genres list query parameters.
|
||||||
*/
|
*/
|
||||||
private interface AudioGenreListQuery {
|
public interface AudioGenreListQuery {
|
||||||
String[] PROJECTION = {
|
String[] PROJECTION = {
|
||||||
BaseColumns._ID,
|
BaseColumns._ID,
|
||||||
MediaContract.AudioGenres.GENREID,
|
MediaContract.AudioGenres.GENREID,
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class SongsListFragment extends AbstractCursorListFragment {
|
||||||
/**
|
/**
|
||||||
* Album songs list query parameters.
|
* Album songs list query parameters.
|
||||||
*/
|
*/
|
||||||
private interface SongsListQuery {
|
public interface SongsListQuery {
|
||||||
String[] PROJECTION = {
|
String[] PROJECTION = {
|
||||||
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
|
MediaDatabase.Tables.SONGS + "." + BaseColumns._ID,
|
||||||
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,
|
MediaDatabase.Tables.SONGS + "." + MediaContract.Songs.TITLE,
|
||||||
|
|
|
@ -76,6 +76,22 @@ public class Utils {
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concats a list of integers...
|
||||||
|
* @param list
|
||||||
|
* @param delimiter
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String listIntegerConcat(List<Integer> list, String delimiter) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
boolean first = true;
|
||||||
|
for (Integer item : list) {
|
||||||
|
if (!first) builder.append(delimiter);
|
||||||
|
builder.append(item);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls {@link Context#startActivity(Intent)} with the given <b>implicit</b> {@link Intent}
|
* Calls {@link Context#startActivity(Intent)} with the given <b>implicit</b> {@link Intent}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# JSON Tools
|
||||||
|
|
||||||
|
Here you will find perl scripts that can be used to retrieve JSON responses from a Kodi instance.
|
||||||
|
The scripts are primarily used to create the JSON source files needed by the instrumentation tests.
|
||||||
|
|
||||||
|
|
||||||
|
## Getting json responses
|
||||||
|
|
||||||
|
Currently there are two scripts available to get media details from a Kodi instance.
|
||||||
|
|
||||||
|
* `getmovies.pl`: retrieves movie details
|
||||||
|
* `getmusic.pl`: retrieves music details
|
||||||
|
|
||||||
|
By default the scripts connect to Kodi running on the same machine (`127.0.0.1`) on port `8080`.
|
||||||
|
If you need to contact a Kodi instance on a different port and/or IP-address change the
|
||||||
|
following line in each script:
|
||||||
|
|
||||||
|
```
|
||||||
|
my $url = "http://127.0.0.1:8080/jsonrpc";
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generating test values
|
||||||
|
|
||||||
|
The instrumentation tests require some values such as "total number of songs", "list of artistids", "genre ids", etc. etc.
|
||||||
|
To generate these values from the JSON files, you can run
|
||||||
|
`gentestnumbers.pl`. This script expects the JSON files to be located in the same directory you execute the script.
|
||||||
|
It also assumes the names of the JSON files are the same as generated by `getmovies.pl` and `getmusic.pl`.
|
|
@ -0,0 +1,283 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
#
|
||||||
|
# Copyright 2016 Martijn Brekhof. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use Cpanel::JSON::XS qw(encode_json decode_json);
|
||||||
|
|
||||||
|
sub printRanges($\@) {
|
||||||
|
my $key = shift;
|
||||||
|
my $arg = shift;
|
||||||
|
my $count = 0;
|
||||||
|
|
||||||
|
my @list = @{$arg};
|
||||||
|
my $current;
|
||||||
|
for (my $i = 1; $i < @list; $i++) {
|
||||||
|
$current = $list[$i]->{$key};
|
||||||
|
my $prev = $list[$i-1]->{$key};
|
||||||
|
if ( $current - $prev == 1 ) {
|
||||||
|
$count++;
|
||||||
|
} else {
|
||||||
|
if ( $count == 0 ) {
|
||||||
|
print $prev;
|
||||||
|
} else {
|
||||||
|
print $prev - $count . "-" . $prev;
|
||||||
|
}
|
||||||
|
print " ";
|
||||||
|
$count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $count == 0 ) {
|
||||||
|
print $current;
|
||||||
|
} else {
|
||||||
|
print $current - $count . "-" . $current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub decodeJson($) {
|
||||||
|
my $filename = shift;
|
||||||
|
local $/ = undef;
|
||||||
|
open (FH, $filename) or die "Error opening file $filename\n";
|
||||||
|
my $json_hash = decode_json(<FH>);
|
||||||
|
close FH;
|
||||||
|
return $json_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub printSong(\%) {
|
||||||
|
my $song = shift;
|
||||||
|
print "title: " . $song->{"title"} . "\n";
|
||||||
|
|
||||||
|
print "artistid: ";
|
||||||
|
for my $artistid ( @{$song->{"artistid"}} ) {
|
||||||
|
print $artistid . " ";
|
||||||
|
}
|
||||||
|
print "\n";
|
||||||
|
|
||||||
|
print "albumid: " . $song->{"albumid"} . "\n";
|
||||||
|
print "songid: " . $song->{"songid"} . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub printAlbum(\%) {
|
||||||
|
my $album = shift;
|
||||||
|
|
||||||
|
print "title: " . $album->{"title"} . "\n";
|
||||||
|
print "albumid: " . $album->{"albumid"} . "\n";
|
||||||
|
print "displayartist: " . $album->{"displayartist"} . "\n";
|
||||||
|
print "year: " . $album->{"year"} . "\n";
|
||||||
|
print "genre: " . @{$album->{"genre"}} . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub getArtists($) {
|
||||||
|
my $json_hash = shift;
|
||||||
|
return $json_hash->{"result"}->{"artists"};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getArtist($$) {
|
||||||
|
my $json_hash = shift;
|
||||||
|
my $artistid = shift;
|
||||||
|
|
||||||
|
my $artists = getArtists($json_hash);
|
||||||
|
for my $artist (@{$artists}) {
|
||||||
|
if ( $artistid == $artist->{"artistid"} ) {
|
||||||
|
return $artist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getAlbums($) {
|
||||||
|
my $json_hash = shift;
|
||||||
|
return $json_hash->{"result"}->{"albums"};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getAlbum($$) {
|
||||||
|
my $json_hash = shift;
|
||||||
|
my $albumid = shift;
|
||||||
|
|
||||||
|
my $albums = getAlbums($json_hash);
|
||||||
|
for my $album (@{$albums}) {
|
||||||
|
if ( $albumid == $album->{"albumid"}) {
|
||||||
|
return $album;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getAlbumsForGenre($$) {
|
||||||
|
my $json_hash = shift;
|
||||||
|
my $genreid = shift;
|
||||||
|
|
||||||
|
my @result;
|
||||||
|
|
||||||
|
my $albums = getAlbums($json_hash);
|
||||||
|
for my $album (@{$albums}) {
|
||||||
|
for my $albumGenreId (@{$album->{"genreid"}}) {
|
||||||
|
if ( $albumGenreId == $genreid ) {
|
||||||
|
push @result, $album;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return @result;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getSongs(%) {
|
||||||
|
my $json_hash = shift;
|
||||||
|
return $json_hash->{"result"}->{"songs"};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getSong(\%$) {
|
||||||
|
my $json_hash = shift;
|
||||||
|
my $songid = shift;
|
||||||
|
|
||||||
|
my $songs = getSongs($json_hash);
|
||||||
|
for my $song (@{$songs}) {
|
||||||
|
if ( $songid == $song->{"songid"}) {
|
||||||
|
return $song;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub printArtistTestNumbers($) {
|
||||||
|
my $artistid = shift;
|
||||||
|
|
||||||
|
my $json_hash = decodeJson( "AudioLibrary.GetArtists.json" );
|
||||||
|
my $result = getArtists($json_hash);
|
||||||
|
print "Amount of artists: ", scalar @{$result}, "\n\n";
|
||||||
|
|
||||||
|
print "Artist ids: ";
|
||||||
|
my @artists = sort {$a->{"artistid"} <=> $b->{"artistid"}} @{$result};
|
||||||
|
printRanges("artistid", @artists);
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Artist with artistId $artistid\n";
|
||||||
|
my $artist = getArtist($json_hash, $artistid);
|
||||||
|
print "artist: " . $artist->{"artist"} . "\n";
|
||||||
|
print "artistid: " . $artist->{"artistid"} . "\n";
|
||||||
|
print "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub printAlbumTestNumbers($$) {
|
||||||
|
my $albumid = shift;
|
||||||
|
my $genreid = shift;
|
||||||
|
my $json_hash = decodeJson( "AudioLibrary.GetAlbums.json" );
|
||||||
|
my $result = getAlbums($json_hash);
|
||||||
|
print "Amount of albums: ", scalar @{$result}, "\n\n";
|
||||||
|
|
||||||
|
print "Album ids: ";
|
||||||
|
my @albums = sort {$a->{"albumid"} <=> $b->{"albumid"}} @{$result};
|
||||||
|
printRanges("albumid", @albums);
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Albums for genre id $genreid: ";
|
||||||
|
my @result = getAlbumsForGenre( $json_hash, $genreid );
|
||||||
|
@albums = sort {$a->{"albumid"} <=> $b->{"albumid"}} @result;
|
||||||
|
printRanges("albumid", @albums);
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Album with albumId $albumid\n";
|
||||||
|
my $album = getAlbum($json_hash, $albumid);
|
||||||
|
printAlbum(%$album);
|
||||||
|
print "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub printSongTestNumbers($$) {
|
||||||
|
my $artistid = shift;
|
||||||
|
my $albumid = shift;
|
||||||
|
|
||||||
|
my $json_hash = decodeJson( "AudioLibrary.GetSongs.json" );
|
||||||
|
my $result = getSongs($json_hash);
|
||||||
|
print "Amount of songs: ", scalar @{$result}, "\n\n";
|
||||||
|
|
||||||
|
my @songsforartist;
|
||||||
|
my @songsforalbum;
|
||||||
|
|
||||||
|
print "Song ids: ";
|
||||||
|
|
||||||
|
my @songids = sort {$a->{"songid"} <=> $b->{"songid"}} @{$result};
|
||||||
|
printRanges("songid", @songids);
|
||||||
|
|
||||||
|
for my $song (@songids) {
|
||||||
|
for my $id (@{$song->{"artistid"}}) {
|
||||||
|
if ( $id == $artistid ) {
|
||||||
|
push @songsforartist, $song;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( $song->{"albumid"} == $albumid ) {
|
||||||
|
push @songsforalbum, $song;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Songs for artistid " . $artistid . ": total=" . scalar @songsforartist . ": ids=";
|
||||||
|
printRanges("songid", @songsforartist);
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Songs for albumid " . $albumid . ": total=" . scalar @songsforalbum . ": ids=";
|
||||||
|
printRanges("songid", @songsforalbum);
|
||||||
|
print "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub printSongCornerCases() {
|
||||||
|
|
||||||
|
my $json_hash = decodeJson( "AudioLibrary.GetSongs.json" );
|
||||||
|
|
||||||
|
print "Song with album and artist\n";
|
||||||
|
my $song = getSong(%$json_hash, 1487);
|
||||||
|
printSong(%$song);
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Songs with album but without artist\n";
|
||||||
|
$song = getSong(%$json_hash, 1219);
|
||||||
|
printSong(%$song);
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Song without album but with artist\n";
|
||||||
|
$song = getSong(%$json_hash, 1128);
|
||||||
|
printSong(%$song);
|
||||||
|
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Song with multiple artists\n";
|
||||||
|
$song = getSong(%$json_hash, 1804);
|
||||||
|
printSong(%$song);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub printAlbumCornerCases() {
|
||||||
|
my $json_hash = decodeJson( "AudioLibrary.GetAlbums.json" );
|
||||||
|
|
||||||
|
print "Album without an artist\n";
|
||||||
|
my $album = getAlbum($json_hash, 82);
|
||||||
|
printAlbum(%$album);
|
||||||
|
print "\n\n";
|
||||||
|
|
||||||
|
print "Album with multiple artists\n";
|
||||||
|
$album = getAlbum($json_hash, 234);
|
||||||
|
printAlbum(%$album);
|
||||||
|
print "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
printArtistTestNumbers(13);
|
||||||
|
|
||||||
|
printAlbumTestNumbers(13, 13);
|
||||||
|
printAlbumCornerCases();
|
||||||
|
|
||||||
|
printSongTestNumbers(13, 13);
|
||||||
|
|
||||||
|
printSongCornerCases();
|
Loading…
Reference in New Issue