package @APP_PACKAGE@; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.HashSet; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.SearchManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.MatrixCursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.provider.BaseColumns; import android.util.Log; import @APP_PACKAGE@.model.Album; import @APP_PACKAGE@.model.Movie; import @APP_PACKAGE@.model.MusicVideo; import @APP_PACKAGE@.model.Song; import @APP_PACKAGE@.model.TVEpisode; import @APP_PACKAGE@.model.TVShow; import @APP_PACKAGE@.content.XBMCFileContentProvider; import @APP_PACKAGE@.model.File; import @APP_PACKAGE@.model.Media; public class XBMCJsonRPC { native String _requestJSON(String request); public final static String APP_NAME = "@APP_NAME@ Search"; public final static String COLUMN_FULL_PATH = "COLUMN_FULL_PATH"; public final static String COLUMN_BASE_PATH = "COLUMN_BASE_PATH"; public final static String COLUMN_FILENAME = "COLUMN_FILENAME"; public final static String COLUMN_TITLE = "COLUMN_TITLE"; public final static String COLUMN_TAGLINE = "COLUMN_TAGLINE"; public final static String COLUMN_THUMB = "COLUMN_THUMB"; public final static String COLUMN_FANART = "COLUMN_FANART"; public final static String COLUMN_ID = "COLUMN_ID"; public final static String COLUMN_VIEW_PROGRESS = "COLUMN_VIEW_PROGRESS"; public final static String COLUMN_RECOMMENDATION_REASON = "COLUMN_RECOMMENDATION_REASON"; public final static String REQ_ID_MOVIES = "1"; public final static String REQ_ID_SHOWS = "2"; public final static String REQ_ID_ALBUMS = "3"; public final static String REQ_ID_ARTISTS = "4"; public final static String REQ_ID_MOVIES_ACTOR = "5"; public final static String REQ_ID_SHOWS_ACTOR = "6"; private final static int MAX_ITEMS = 20; private static String TAG = "@APP_NAME@"; private String m_xbmc_web_url = "http://localhost:8080"; private HashSet mRecomendationIds = new HashSet(); private int MAX_RECOMMENDATIONS = 3; private String GET_VERSION = "{ \"jsonrpc\": \"2.0\", \"method\": \"JSONRPC.Version\", \"id\": 1 }"; private String RECOMMENDATION_MOVIES_JSON = "{\"jsonrpc\": \"2.0\", \"method\": \"VideoLibrary.GetMovies\", " + "\"params\": { \"filter\": {\"field\": \"playcount\", \"operator\": \"is\", \"value\": \"0\"}, " + "\"limits\": { \"start\" : 0, \"end\": 10}, " + "\"properties\" : [\"imdbnumber\", \"title\", \"tagline\", \"art\", \"year\", \"runtime\", \"file\", \"plot\", \"rating\"], " + "\"sort\": { \"order\": \"descending\", \"method\": \"random\", \"ignorearticle\": true } }, " + "\"id\": \"1\"}"; private String RECOMMENDATIONS_SHOWS_JSON = "{\"jsonrpc\":\"2.0\",\"method\":\"VideoLibrary.GetTVShows\",\"params\":{\"filter\":{\"and\":[{\"field\":\"playcount\",\"operator\":\"is\",\"value\":\"0\"},{\"field\":\"plot\",\"operator\":\"isnot\",\"value\":\"\"}]},\"limits\":{\"start\":0,\"end\":10},\"properties\":[\"imdbnumber\",\"title\",\"plot\",\"art\",\"studio\", \"year\", \"rating\"],\"sort\":{\"order\":\"descending\",\"method\":\"lastplayed\",\"ignorearticle\":true}},\"id\":\"1\"}"; private String RECOMMENDATIONS_ALBUMS_JSON = "{\"jsonrpc\": \"2.0\", \"method\": \"AudioLibrary.GetAlbums\", \"params\": { \"limits\": { \"start\" : 0, \"end\": 3}, \"properties\" : [\"title\", \"displayartist\", \"art\"], \"sort\": { \"order\": \"descending\", \"method\": \"random\", \"ignorearticle\": true } }, \"id\": \"1\"}"; private String SEARCH_MOVIES_JSON = "{\"jsonrpc\": \"2.0\", \"method\": \"VideoLibrary.GetMovies\", " + "\"params\": { \"filter\": {%s}, " + "\"limits\": { \"start\" : 0, \"end\": 10}, " + "\"properties\" : [\"imdbnumber\", \"title\", \"tagline\", \"art\", \"year\", \"runtime\"], " + "\"sort\": { \"order\": \"ascending\", \"method\": \"title\", \"ignorearticle\": true } }, " + "\"id\": \"%s\"}"; private String SEARCH_SHOWS_JSON = "{\"jsonrpc\":\"2.0\",\"method\":\"VideoLibrary.GetTVShows\",\"params\":{\"filter\":{%s},\"limits\":{\"start\":0,\"end\":10},\"properties\":[\"imdbnumber\",\"title\",\"plot\",\"art\",\"year\"],\"sort\":{\"order\":\"descending\",\"method\":\"lastplayed\",\"ignorearticle\":true}},\"id\":\"%s\"}"; private String SEARCH_ALBUMS_JSON = "{\"jsonrpc\": \"2.0\", \"method\": \"AudioLibrary.GetAlbums\", \"params\": {\"filter\":{%s},\"limits\": { \"start\" : 0, \"end\": 10}, \"properties\" : [\"title\", \"displayartist\", \"art\"], \"sort\": { \"order\": \"descending\", \"method\": \"dateadded\", \"ignorearticle\": true } }, \"id\": \"%s\"}"; private String SEARCH_ARTISTS_JSON = "{\"jsonrpc\": \"2.0\", \"method\": \"AudioLibrary.GetArtists\", \"params\": {\"filter\":{%s},\"limits\": { \"start\" : 0, \"end\": 10}, \"properties\" : [\"description\", \"art\"], \"sort\": { \"order\": \"descending\", \"method\": \"dateadded\", \"ignorearticle\": true } }, \"id\": \"%s\"}"; private String RETRIEVE_MOVIE_DETAILS = "{ \"jsonrpc\": \"2.0\", \"method\": \"VideoLibrary.GetMovieDetails\", \"params\": { \"movieid\" : %s, \"properties\" : [\"imdbnumber\", \"title\", \"tagline\", \"art\", \"year\", \"runtime\", \"file\", \"plot\", \"trailer\", \"rating\"] }, \"id\": \"%s\" }"; private String RETRIEVE_EPISODE_DETAILS = "{ \"jsonrpc\": \"2.0\", \"method\": \"VideoLibrary.GetEpisodeDetails\", \"params\": { \"episodeid\" : %s, \"properties\" : [\"title\", \"tvshowid\", \"showtitle\", \"season\", \"episode\", \"art\", \"file\", \"plot\", \"rating\", \"runtime\", \"firstaired\"] }, \"id\": \"%s\" }"; private String RETRIEVE_TVSHOW_DETAILS = "{ \"jsonrpc\": \"2.0\", \"method\": \"VideoLibrary.GetTVShowDetails\", \"params\": { \"tvshowid\" : %s, \"properties\" : [\"title\", \"studio\", \"art\", \"plot\", \"year\", \"rating\"] }, \"id\": \"%s\" }"; private String RETRIEVE_ALBUM_DETAILS = "{ \"jsonrpc\": \"2.0\", \"method\": \"AudioLibrary.GetAlbumDetails\", \"params\": { \"albumid\" : %s, \"properties\" : [\"title\", \"displayartist\", \"art\", \"artistid\"] }, \"id\": \"%s\" }"; private String RETRIEVE_SONG_DETAILS = "{ \"jsonrpc\": \"2.0\", \"method\": \"AudioLibrary.GetSongDetails\", \"params\": { \"songid\" : %s, \"properties\" : [\"title\", \"displayartist\", \"art\", \"albumid\", \"artistid\", \"file\"] }, \"id\": \"%s\" }"; private String RETRIEVE_MUSICVIDEO_DETAILS = "{ \"jsonrpc\": \"2.0\", \"method\": \"VideoLibrary.GetMusicVideoDetails\", \"params\": { \"musicvideoid\" : %s, \"properties\" : [\"title\", \"artist\", \"art\", \"file\"] }, \"id\": \"%s\" }"; private String RETRIEVE_FILE_ITEMS = "{ \"jsonrpc\": \"2.0\", \"method\": \"Files.GetDirectory\", \"params\": { \"directory\" : \"%s\" }, \"id\": \"%s\" }"; private NotificationManager mNotificationManager; public XBMCJsonRPC() { String jsonPort = XBMCProperties.getStringProperty("xbmc.jsonPort", "8080"); m_xbmc_web_url = "http://localhost:" + jsonPort; } public String request_string(String jsonRequest) { try { return _requestJSON(jsonRequest); } catch (Exception e) { Log.e(TAG, "XBMCJsonRPC: Failed to read JSON"); e.printStackTrace(); return null; } catch (UnsatisfiedLinkError e) { Log.e(TAG, "XBMCJsonRPC: _requestJSON: Not available"); return null; } } public JsonObject request_object(String jsonRequest) { try { String stringResp = request_string(jsonRequest); if (stringResp == null) return null; return JsonParser.parseString(stringResp).getAsJsonObject(); } catch (Exception e) { Log.e(TAG, "XBMCJsonRPC: Failed to parse JSON"); e.printStackTrace(); return null; } } public JsonArray request_array(String jsonRequest) { try { String stringResp = request_string(jsonRequest); if (stringResp == null) return null; return JsonParser.parseString(stringResp).getAsJsonArray(); } catch (Exception e) { Log.e(TAG, "XBMCJsonRPC: Failed to parse JSON"); e.printStackTrace(); return null; } } public Bitmap getBitmap(Context ctx, String src) { try { ContentResolver resolver = ctx.getContentResolver(); InputStream input = resolver.openInputStream(XBMCFileContentProvider.buildUri(src)); Bitmap bitmap = BitmapFactory.decodeStream(input); input.close(); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } public String getDownloadUrl(String src) { return src; } public boolean Ping() { try { JsonObject req = request_object(GET_VERSION); if (req == null || !req.has("result")) return false; } catch (Exception e) { return false; } return true; } public Cursor search(String query) { String[] menuCols = new String[] { BaseColumns._ID, COLUMN_TITLE, COLUMN_TAGLINE, COLUMN_THUMB, COLUMN_FANART, }; MatrixCursor mc = new MatrixCursor(menuCols); try { JsonObject req = request_object(String.format(SEARCH_MOVIES_JSON, /*"\"operator\": \"contains\", \"field\": \"title\", \"value\": \"" + query + "\"", limit));*/ "\"or\": [" + "{\"operator\": \"contains\", \"field\": \"title\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"originaltitle\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"set\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"actor\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"director\", \"value\": \"" + query + "\"}]")); if (req == null || !req.has("result")) return null; JsonObject results = req.getAsJsonObject("result"); JsonArray movies = results.getAsJsonArray("movies"); for (int i = 0; i < movies.size(); ++i) { JsonObject movie = movies.get(i).getAsJsonObject(); String poster = extractKeyFromArtMap(movie, "poster"); String thumb = extractKeyFromArtMap(movie, "thumb"); String fanart = extractKeyFromArtMap(movie, "fanart"); mc.addRow(new Object[]{ movie.get("movieid"), movie.get("title"), movie.get("tagline"), poster != null && !poster.isEmpty() ? poster : thumb != null && !thumb.isEmpty() ? thumb : "", fanart != null && !fanart.isEmpty() ? fanart : "" }); } } catch (Exception e) { e.printStackTrace(); return null; } try { JsonObject req = request_object(String.format(SEARCH_SHOWS_JSON, /*"\"operator\": \"contains\", \"field\": \"title\", \"value\": \"" + query + "\"", limit));*/ "\"or\": [" + "{\"operator\": \"contains\", \"field\": \"title\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"actor\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"director\", \"value\": \"" + query + "\"}]")); if (req == null || !req.has("result")) return null; JsonObject results = req.getAsJsonObject("result"); JsonArray tvshows = results.getAsJsonArray("tvshows"); for (int i = 0; i < tvshows.size(); ++i) { JsonObject tvshow = tvshows.get(i).getAsJsonObject(); String poster = extractKeyFromArtMap(tvshow, "poster"); String thumb = extractKeyFromArtMap(tvshow, "thumb"); String fanart = extractKeyFromArtMap(tvshow, "fanart"); mc.addRow(new Object[]{ tvshow.get("movieid"), tvshow.get("title"), tvshow.get("plot"), poster != null && !poster.isEmpty() ? poster : thumb != null && !thumb.isEmpty() ? thumb : "", fanart != null && !fanart.isEmpty() ? fanart : "" }); } } catch (Exception e) { e.printStackTrace(); return null; } return mc; } public Cursor getSuggestions(String query, int limit) { //Log.d(TAG, "query: " + query); int totCount = 0; String[] menuCols = new String[] { BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_TEXT_2, SearchManager.SUGGEST_COLUMN_ICON_1, SearchManager.SUGGEST_COLUMN_RESULT_CARD_IMAGE, SearchManager.SUGGEST_COLUMN_INTENT_ACTION, SearchManager.SUGGEST_COLUMN_INTENT_DATA, SearchManager.SUGGEST_COLUMN_VIDEO_WIDTH, SearchManager.SUGGEST_COLUMN_VIDEO_HEIGHT, SearchManager.SUGGEST_COLUMN_PRODUCTION_YEAR, SearchManager.SUGGEST_COLUMN_DURATION, SearchManager.SUGGEST_COLUMN_SHORTCUT_ID }; MatrixCursor mc = new MatrixCursor(menuCols); String str_req = "[" + String.format(SEARCH_MOVIES_JSON, "\"or\": [" + "{\"operator\": \"contains\", \"field\": \"title\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"originaltitle\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"set\", \"value\": \"" + query + "\"}]", REQ_ID_MOVIES) + "," + String.format(SEARCH_SHOWS_JSON, "\"or\": [" + "{\"operator\": \"contains\", \"field\": \"title\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"originaltitle\", \"value\": \"" + query + "\"}]", REQ_ID_SHOWS) + "," + String.format(SEARCH_ALBUMS_JSON, "\"or\": [" + "{\"operator\": \"contains\", \"field\": \"album\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"label\", \"value\": \"" + query + "\"}]", REQ_ID_ALBUMS) + "," + String.format(SEARCH_ARTISTS_JSON, "\"operator\": \"contains\", \"field\": \"artist\", \"value\": \"" + query + "\"", REQ_ID_ARTISTS) + "," + String.format(SEARCH_MOVIES_JSON, "\"or\": [" + "{\"operator\": \"contains\", \"field\": \"actor\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"director\", \"value\": \"" + query + "\"}]", REQ_ID_MOVIES_ACTOR) + "," + String.format(SEARCH_SHOWS_JSON, "\"or\": [" + "{\"operator\": \"contains\", \"field\": \"actor\", \"value\": \"" + query + "\"}," + "{\"operator\": \"contains\", \"field\": \"director\", \"value\": \"" + query + "\"}]", REQ_ID_SHOWS_ACTOR) + "]"; JsonArray res_array = request_array(str_req); if (res_array == null) return null; int nb_movies = 0; int nb_shows = 0; for (int j = 0; j < res_array.size(); ++j) { String id; JsonObject resp; try { resp = res_array.get(j).getAsJsonObject(); if (resp == null) continue; id = resp.get("id").getAsString(); } catch (Exception e) { e.printStackTrace(); continue; } if (id.equals(REQ_ID_MOVIES) || ((nb_movies + nb_shows) < 3 && id.equals(REQ_ID_MOVIES_ACTOR))) { searchmovies: try { if (resp == null || !resp.has("result")) break searchmovies; JsonObject results = resp.getAsJsonObject("result"); if (results == null || !results.has("movies")) break searchmovies; JsonArray movies = results.get("movies").getAsJsonArray(); for (int i = 0; i < movies.size() && totCount < limit; ++i) { JsonObject movie = movies.get(i).getAsJsonObject(); String poster = extractKeyFromArtMap(movie, "poster"); String thumb = extractKeyFromArtMap(movie, "thumb"); int rYear = 0; long rDur = 0; try { rYear = movie.get("year").getAsInt(); rDur = movie.get("runtime").getAsLong() * 1000; } catch (Exception e) { e.printStackTrace(); } mc.addRow(new Object[] { movie.get("movieid").getAsString(), movie.get("title").getAsString(), movie.get("tagline").getAsString(), XBMCFileContentProvider.buildUri(getDownloadUrl( poster != null && !poster.isEmpty() ? poster : thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), XBMCFileContentProvider.buildUri(getDownloadUrl( poster != null && !poster.isEmpty() ? poster : thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), Intent.ACTION_GET_CONTENT, Uri.parse("videodb://movies/titles/" + movie.get("movieid").getAsString() + "?showinfo=true"), 0, 0, rYear, rDur, -1 }); nb_movies++; totCount++; } } catch (Exception e) { e.printStackTrace(); } } else if (id.equals(REQ_ID_SHOWS) || ((nb_movies + nb_shows) < 3 && id.equals(REQ_ID_SHOWS_ACTOR))) { searchtv: try { if(!resp.has("result")) break searchtv; JsonObject results = resp.getAsJsonObject("result"); if (results == null || !results.has("tvshows")) break searchtv; JsonArray tvshows = results.get("tvshows").getAsJsonArray(); for (int i = 0; i < tvshows.size() && totCount < limit; ++i) { JsonObject tvshow = tvshows.get(i).getAsJsonObject(); String poster = extractKeyFromArtMap(tvshow, "poster"); String thumb = extractKeyFromArtMap(tvshow, "thumb"); int rYear = 0; long rDur = 0; try { rYear = tvshow.get("year").getAsInt(); } catch (Exception e) { e.printStackTrace(); } mc.addRow(new Object[] { tvshow.get("tvshowid").getAsString(), tvshow.get("title").getAsString(), tvshow.get("plot").getAsString(), XBMCFileContentProvider.buildUri(getDownloadUrl( poster != null && !poster.isEmpty() ? poster : thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), XBMCFileContentProvider.buildUri(getDownloadUrl( poster != null && !poster.isEmpty() ? poster : thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), Intent.ACTION_GET_CONTENT, Uri.parse("videodb://tvshows/titles/" + tvshow.get("tvshowid").getAsString() + "?showinfo=true"), 0, 0, rYear, 45*60*1000, -1 }); Log.d(TAG, "XBMCJsonRPC: tvshow: " + tvshow.get("title").getAsString() + ", " + tvshow.get("year").getAsInt()); nb_shows++; totCount++; } } catch (Exception e) { e.printStackTrace(); } } else if (id.equals(REQ_ID_ALBUMS)) { searchalbums: try { if (!resp.has("result")) break searchalbums; JsonObject results = resp.getAsJsonObject("result"); if (results == null || !results.has("albums")) break searchalbums; JsonArray albums = results.get("albums").getAsJsonArray(); for (int i = 0; i < albums.size() && totCount < limit; ++i) { JsonObject album = albums.get(i).getAsJsonObject(); String thumb = extractKeyFromArtMap(album, "thumb"); mc.addRow(new Object[] { album.get("albumid").getAsString(), album.get("title").getAsString(), album.get("displayartist").getAsString(), XBMCFileContentProvider.buildUri(getDownloadUrl(thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), XBMCFileContentProvider.buildUri(getDownloadUrl(thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), Intent.ACTION_GET_CONTENT, Uri.parse("musicdb://albums/" + album.get("albumid").getAsString() + "/"), 0, 0, 0, 0, -1 }); totCount++; } } catch (Exception e) { e.printStackTrace(); } } else if (id.equals(REQ_ID_ARTISTS)) { searchartists: try { if (!resp.has("result")) break searchartists; JsonObject results = resp.getAsJsonObject("result"); if (results == null || !results.has("artists")) break searchartists; JsonArray artists = results.get("artists").getAsJsonArray(); for (int i = 0; i < artists.size() && totCount < limit; ++i) { JsonObject artist = artists.get(i).getAsJsonObject(); String thumb = extractKeyFromArtMap(artist, "thumb"); mc.addRow(new Object[] { artist.get("artistid").getAsString(), artist.get("artist").getAsString(), artist.get("description").getAsString(), XBMCFileContentProvider.buildUri(getDownloadUrl(thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), XBMCFileContentProvider.buildUri(getDownloadUrl(thumb != null && !thumb.isEmpty() ? thumb : "" )).toString(), Intent.ACTION_GET_CONTENT, Uri.parse("musicdb://artists/" + artist.get("artistid").getAsString() + "/"), 0, 0, 0, 0, -1 }); totCount++; } } catch (Exception e) { e.printStackTrace(); } } } return mc; } public void updateLeanback(Context ctx) { if (mNotificationManager == null) { mNotificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE); } for(Integer id : mRecomendationIds) mNotificationManager.cancel(id); mRecomendationIds.clear(); JsonObject rep = request_object(RECOMMENDATION_MOVIES_JSON); if (rep != null && rep.has("result")) { try { JsonObject results = rep.getAsJsonObject("result"); JsonArray movies = results.get("movies").getAsJsonArray(); int count = 0; for (int i = 0; i < movies.size() && count < MAX_RECOMMENDATIONS; ++i) { try { JsonObject movie = movies.get(i).getAsJsonObject(); int id = movie.get("movieid").getAsInt() + 1000000; String poster = extractKeyFromArtMap(movie, "poster"); String thumb = extractKeyFromArtMap(movie, "thumb"); String fanart = extractKeyFromArtMap(movie, "fanart"); final XBMCRecommendationBuilder notificationBuilder = new XBMCRecommendationBuilder() .setContext(ctx) .setSmallIcon(R.drawable.notif_icon) .setId(id).setPriority(MAX_RECOMMENDATIONS - count) .setTitle(movie.get("title").getAsString()) .setDescription(movie.get("tagline").getAsString()) .setIntent(buildPendingMovieIntent(ctx, movie)); if (fanart != null && !fanart.isEmpty()) { notificationBuilder.setBackground(XBMCFileContentProvider.buildUri( getDownloadUrl(fanart)).toString()); } if (poster != null && !poster.isEmpty()) { Bitmap bitmap = getBitmap(ctx, poster); notificationBuilder.setBitmap(bitmap); } else if (thumb != null && !thumb.isEmpty()) { Bitmap bitmap = getBitmap(ctx, thumb); notificationBuilder.setBitmap(bitmap); } Notification notification = notificationBuilder.build(); mNotificationManager.notify(id, notification); mRecomendationIds.add(id); ++count; } catch (Exception e) { continue; } } } catch (Exception e) { e.printStackTrace(); } } rep = request_object(RECOMMENDATIONS_SHOWS_JSON); if (rep != null && rep.has("result")) { try { JsonObject results = rep.getAsJsonObject("result"); JsonArray tvshows = results.get("tvshows").getAsJsonArray(); int count = 0; for (int i = 0; i < tvshows.size() && count < MAX_RECOMMENDATIONS; ++i) { try { JsonObject tvshow = tvshows.get(i).getAsJsonObject(); int id = tvshow.get("tvshowid").getAsInt() + 2000000; String poster = extractKeyFromArtMap(tvshow, "poster"); String thumb = extractKeyFromArtMap(tvshow, "thumb"); String fanart = extractKeyFromArtMap(tvshow, "fanart"); final XBMCRecommendationBuilder notificationBuilder = new XBMCRecommendationBuilder() .setContext(ctx) .setSmallIcon(R.drawable.notif_icon) .setId(id).setPriority(MAX_RECOMMENDATIONS - count) .setTitle(tvshow.get("title").getAsString()) .setDescription(tvshow.get("plot").getAsString()) .setIntent(buildPendingShowIntent(ctx, tvshow)); if (fanart != null && !fanart.isEmpty()) { notificationBuilder.setBackground(XBMCFileContentProvider.buildUri( getDownloadUrl(fanart)).toString()); } if (poster != null && !poster.isEmpty()) { Bitmap bitmap = getBitmap(ctx, poster); notificationBuilder.setBitmap(bitmap); } else if (thumb != null && !thumb.isEmpty()) { Bitmap bitmap = getBitmap(ctx, thumb); notificationBuilder.setBitmap(bitmap); } Notification notification = notificationBuilder.build(); mNotificationManager.notify(id, notification); mRecomendationIds.add(id); ++count; } catch (Exception e) { continue; } } } catch (Exception e) { e.printStackTrace(); } } rep = request_object(RECOMMENDATIONS_ALBUMS_JSON); if (rep != null && rep.has("result")) { try { JsonObject results = rep.getAsJsonObject("result"); JsonArray albums = results.get("albums").getAsJsonArray(); int count = 0; for (int i = 0; i < albums.size() && count < MAX_RECOMMENDATIONS; ++i) { try { JsonObject album = albums.get(i).getAsJsonObject(); int id = album.get("albumid").getAsInt() + 3000000; String thumb = extractKeyFromArtMap(album, "thumb"); String fanart = extractKeyFromArtMap(album, "fanart"); final XBMCRecommendationBuilder notificationBuilder = new XBMCRecommendationBuilder() .setContext(ctx) .setSmallIcon(R.drawable.notif_icon) .setId(id).setPriority(MAX_RECOMMENDATIONS - count) .setTitle(album.get("title").getAsString()) .setDescription(album.get("displayartist").getAsString()) .setIntent(buildPendingAlbumIntent(ctx, album)); if (fanart != null && !fanart.isEmpty()) { notificationBuilder.setBackground(XBMCFileContentProvider.buildUri( getDownloadUrl(fanart)).toString()); } if (thumb != null && !thumb.isEmpty()) { Bitmap bitmap = getBitmap(ctx, thumb); notificationBuilder.setBitmap(bitmap); } Notification notification = notificationBuilder.build(); mNotificationManager.notify(id, notification); mRecomendationIds.add(id); ++count; } catch (Exception e) { continue; } } } catch (Exception e) { e.printStackTrace(); } } } private PendingIntent buildPendingMovieIntent(Context ctx, JsonObject movie) { try { Intent detailsIntent = new Intent(ctx, Splash.class); detailsIntent.setAction(Intent.ACTION_VIEW); detailsIntent.setData(Uri.parse("videodb://movies/titles/" + movie.get("movieid").getAsString() + "?showinfo=true")); //detailsIntent.putExtra(MovieDetailsActivity.MOVIE, movie); //detailsIntent.putExtra(MovieDetailsActivity.NOTIFICATION_ID, id); return PendingIntent.getActivity(ctx, 0, detailsIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); } catch (Exception e) { e.printStackTrace(); return null; } } private PendingIntent buildPendingShowIntent(Context ctx, JsonObject tvshow) { try { Intent detailsIntent = new Intent(ctx, Splash.class); detailsIntent.setAction(Intent.ACTION_GET_CONTENT); detailsIntent.setData(Uri.parse("videodb://tvshows/titles/" + tvshow.get("tvshowid").getAsString() + "/")); return PendingIntent.getActivity(ctx, 0, detailsIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); } catch (Exception e) { e.printStackTrace(); return null; } } private PendingIntent buildPendingAlbumIntent(Context ctx, JsonObject album) { try { Intent detailsIntent = new Intent(ctx, Splash.class); detailsIntent.setAction(Intent.ACTION_GET_CONTENT); detailsIntent.setData(Uri.parse("musicdb://albums/" + album.get("albumid").getAsString() + "/")); return PendingIntent.getActivity(ctx, 0, detailsIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); } catch (Exception e) { e.printStackTrace(); return null; } } public List getFiles(String url) { List files = new ArrayList(); try { JsonObject req = request_object(String.format(RETRIEVE_FILE_ITEMS, url, "1")); if (req == null || !req.has("result")) return files; JsonObject results = req.getAsJsonObject("result"); if (!results.has("files")) return files; JsonArray filesA = results.get("files").getAsJsonArray(); for (int i = 0; i < filesA.size(); ++i) { JsonObject fileO = filesA.get(i).getAsJsonObject(); Uri uri = Uri.parse(fileO.get("file").getAsString()); File file = File.createFile(fileO.get("label").getAsString(), fileO.get("filetype").getAsString(), XBMCFileContentProvider.buildUri(uri.toString()).toString()); if (fileO.has("id")) file.setId(fileO.get("id").getAsInt()); if (fileO.has("type") && !fileO.get("type").getAsString().equals("unknown")) file.setMediatype(fileO.get("type").getAsString()); files.add(file); } } catch (Exception e) { e.printStackTrace(); } return files; } private Movie createMovieFromJson(JsonObject details) { Movie med = new Movie(); try { med.setId(details.get("movieid").getAsInt()); med.setTitle(details.get("title").getAsString()); med.setDescription(details.get("plot").getAsString()); // poster String poster = extractKeyFromArtMap(details, "poster"); if (poster != null && !poster.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); med.setCardImageAspectRatio("2:3"); } // fallback to thumb else { poster = extractKeyFromArtMap(details, "thumb"); if (poster != null && !poster.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); med.setCardImageAspectRatio("16:9"); } } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); } med.setXbmcUrl("videodb://movies/titles/" + details.get("movieid").getAsString() + "?showinfo=true"); /* if (details.has("trailer") && !details.get("trailer").getAsString().isEmpty()) { String trailer_url = details.get("trailer").getAsString(); if (trailer_url.startsWith("plugin://plugin.video.youtube")) { Uri u = Uri.parse(trailer_url); String videoid = u.getQueryParameter("videoid"); String yturl = Uri.parse(m_xbmc_web_url) .buildUpon() .appendPath("addons").appendPath("webinterface.youtube-dl") .appendQueryParameter("url", "http://www.youtube.com/watch?v=" + videoid) .build() .toString(); med.setVideoUrl(XBMCYTDLContentProvider.GetYTDLUri(yturl).toString()); Log.d(TAG, "createMovieFromJson: " + med.getVideoUrl()); } else med.setVideoUrl(trailer_url); } */ med.setCategory(Media.MEDIA_TYPE_MOVIE); med.setYear(details.get("year").getAsString()); med.setRating(convertRating(details.get("rating").getAsDouble())); med.setDuration(details.get("runtime").getAsInt() * 1000); } catch (Exception e) { return null; } return med; } private TVShow createTVShowFromJson(JsonObject details) { TVShow med = new TVShow(); try { med.setId(details.get("tvshowid").getAsInt()); med.setTitle(details.get("title").getAsString()); med.setDescription(details.get("plot").getAsString()); // poster String poster = extractKeyFromArtMap(details, "poster"); if (poster != null && !poster.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); med.setCardImageAspectRatio("2:3"); } // fallback to thumb else { poster = extractKeyFromArtMap(details, "thumb"); if (poster != null && !poster.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); med.setCardImageAspectRatio("16:9"); } } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); } med.setXbmcUrl("videodb://tvshows/titles/" + details.get("tvshowid").getAsInt() + "/"); med.setCategory(Media.MEDIA_TYPE_TVSHOW); med.setYear(details.get("year").getAsString()); med.setRating(convertRating(details.get("rating").getAsDouble())); } catch (Exception e) { return null; } return med; } private TVEpisode createTVEpisodeFromJson(JsonObject details) { TVEpisode med = new TVEpisode(); try { med.setId(details.get("episodeid").getAsInt()); med.setTitle(details.get("title").getAsString()); med.setDescription(details.get("plot").getAsString()); // thumb String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); med.setCardImageAspectRatio("16:9"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); } med.setXbmcUrl("videodb://tvshows/titles/" + details.get("tvshowid").getAsInt() + "/" + details.get("episodeid").getAsInt() + "?showinfo=true"); /* String url = getDownloadUrl(details.get("file").getAsString()); if (!url.isEmpty()) med.setVideoUrl(url); */ med.setCategory(Media.MEDIA_TYPE_TVEPISODE); med.setShowTitle(details.get("showtitle").getAsString()); med.setSeason(details.get("season").getAsInt()); med.setEpisode(details.get("episode").getAsInt()); med.setRating(convertRating(details.get("rating").getAsDouble())); med.setDuration(details.get("runtime").getAsInt() * 1000); med.setFirstaired(details.get("firstaired").getAsString()); } catch (Exception e) { return null; } return med; } private Album createAlbumFromJson(JsonObject details) { Album med = new Album(); try { med.setId(details.get("albumid").getAsInt()); med.setTitle(details.get("title").getAsString()); med.setDescription(details.get("displayartist").getAsString()); // thumb String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); med.setCardImageAspectRatio("1:1"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); } med.setXbmcUrl("musicdb://albums/" + details.get("albumid").getAsString() + "/"); med.setCategory(Media.MEDIA_TYPE_ALBUM); } catch (Exception e) { return null; } return med; } private Song createSongFromJson(JsonObject details) { Song med = new Song(); try { med.setId(details.get("songid").getAsInt()); med.setTitle(details.get("title").getAsString()); med.setDescription(details.get("displayartist").getAsString()); // album thumb String thumb = extractKeyFromArtMap(details, "album.thumb"); if (thumb != null && !thumb.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); med.setCardImageAspectRatio("1:1"); } // fallback to albumartist.thumb else { thumb = extractKeyFromArtMap(details, "albumartist.thumb"); if (thumb != null && !thumb.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); med.setCardImageAspectRatio("1:1"); } else { // fallback to artist.thumb thumb = extractKeyFromArtMap(details, "artist.thumb"); if (thumb != null && !thumb.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); med.setCardImageAspectRatio("1:1"); } } } // fanart String fanart = extractKeyFromArtMap(details, "albumartist.fanart"); if (fanart != null && !fanart.isEmpty()) { med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); } else { fanart = extractKeyFromArtMap(details, "artist.fanart"); if (fanart != null && !fanart.isEmpty()) { med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); } } String extension = ""; if (details.has("file") && !details.get("file").getAsString().isEmpty()) { String file = details.get("file").getAsString(); extension = file.substring(file.lastIndexOf(".")); } if (details.has("albumid") && !details.get("albumid").getAsString().isEmpty()) med.setXbmcUrl("musicdb://albums/" + details.get("albumid").getAsString() + "/" + details.get("songid").getAsInt() + extension); else med.setXbmcUrl("musicdb://songs/" + details.get("songid").getAsInt() + extension); /* String url = getDownloadUrl(details.get("file").getAsString()); if (!url.isEmpty()) med.setVideoUrl(url); */ med.setCategory(Media.MEDIA_TYPE_SONG); } catch (Exception e) { return null; } return med; } private MusicVideo createMusicvideoFromJson(JsonObject details) { MusicVideo med = new MusicVideo(); try { med.setId(details.get("musicvideoid").getAsInt()); med.setTitle(details.get("title").getAsString()); JsonArray ja = details.get("artist").getAsJsonArray(); if (ja.size() > 0) med.setDescription(ja.get(0).getAsString()); // thumb String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); med.setCardImageAspectRatio("1:1"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); } med.setXbmcUrl("videodb://musicvideos/titles/" + details.get("musicvideoid").getAsInt()); String url = getDownloadUrl(details.get("file").getAsString()); if (url != null && !url.isEmpty()) med.setVideoUrl(XBMCFileContentProvider.buildUri(url).toString()); med.setCategory(Media.MEDIA_TYPE_MUSICVIDEO); } catch (Exception e) { return null; } return med; } public List getSuggestions() { List medias = new ArrayList(); // count the number of categories with data int categories = 0; JsonObject rep = request_object(RECOMMENDATION_MOVIES_JSON); JsonArray movies = new JsonArray(); if (rep != null && rep.has("result")) { try { JsonObject results = rep.getAsJsonObject("result"); if (results.has("movies")) { movies = results.get("movies").getAsJsonArray(); if (movies.size() > 0) { ++categories; } } } catch (Exception e) { } } rep = request_object(RECOMMENDATIONS_SHOWS_JSON); JsonArray tvshows = new JsonArray(); if (rep != null && rep.has("result")) { try { JsonObject results = rep.getAsJsonObject("result"); if (results.has("tvshows")) { tvshows = results.get("tvshows").getAsJsonArray(); if (tvshows.size() > 0) { ++categories; } } } catch (Exception e) { } } rep = request_object(RECOMMENDATIONS_ALBUMS_JSON); JsonArray albums = new JsonArray(); if (rep != null && rep.has("result")) { try { JsonObject results = rep.getAsJsonObject("result"); if (results.has("albums")) { albums = results.get("albums").getAsJsonArray(); if (albums.size() > 0) { ++categories; } } } catch (Exception e) { } } // distribution by the number of categories with data if (categories == 1) { MAX_RECOMMENDATIONS = 10; // 1x10 items } else if (categories == 2) { MAX_RECOMMENDATIONS = 5; // 2x5 items } else { MAX_RECOMMENDATIONS = 3; // 3x3 items } if (movies.size() > 0) { int count = 0; for (int i = 0; i < movies.size() && count < MAX_RECOMMENDATIONS; ++i) { try { JsonObject details = movies.get(i).getAsJsonObject(); Movie med = createMovieFromJson(details); if (med != null) { medias.add(med); ++count; } } catch (Exception e) { continue; } } } if (tvshows.size() > 0) { int count = 0; for (int i = 0; i < tvshows.size() && count < MAX_RECOMMENDATIONS; ++i) { try { JsonObject tvshow = tvshows.get(i).getAsJsonObject(); TVShow med = createTVShowFromJson(tvshow); if (med != null) { medias.add(med); ++count; } } catch (Exception e) { continue; } } } if (albums.size() > 0) { int count = 0; for (int i = 0; i < albums.size() && count < MAX_RECOMMENDATIONS; ++i) { try { JsonObject album = albums.get(i).getAsJsonObject(); Album med = createAlbumFromJson(album); if (med != null) { medias.add(med); ++count; } } catch (Exception e) { continue; } } } return medias; } public List getMedias(List files) { List medias = new ArrayList(); try { int nbItems = 0; String strReq = "["; for (int i = 0; i < files.size() && nbItems < MAX_ITEMS; ++i) { File file = files.get(i); String mediaType = file.getMediatype(); long mediaId = file.getId(); if (mediaType.equals("movie")) strReq += String.format(RETRIEVE_MOVIE_DETAILS, mediaId, String.valueOf(++nbItems)); else if (mediaType.equals("episode")) strReq += String.format(RETRIEVE_EPISODE_DETAILS, mediaId, String.valueOf(++nbItems)); else if (mediaType.equals("tvshow")) strReq += String.format(RETRIEVE_TVSHOW_DETAILS, mediaId, String.valueOf(++nbItems)); else if (mediaType.equals("album")) strReq += String.format(RETRIEVE_ALBUM_DETAILS, mediaId, String.valueOf(++nbItems)); else if (mediaType.equals("song")) strReq += String.format(RETRIEVE_SONG_DETAILS, mediaId, String.valueOf(++nbItems)); else if (mediaType.equals("musicvideo")) strReq += String.format(RETRIEVE_MUSICVIDEO_DETAILS, mediaId, String.valueOf(++nbItems)); if (i+1 < files.size() && nbItems < MAX_ITEMS) strReq += ","; } strReq += "]"; JsonArray reqBatch = request_array(strReq); if (reqBatch == null) return medias; nbItems = 0; for (int i = 0; i < reqBatch.size(); ++i) { JsonObject req = reqBatch.get(i).getAsJsonObject(); if (req == null || !req.has("result")) continue; File file = files.get(i); String mediaType = file.getMediatype(); if (mediaType.equals("movie")) { JsonObject details = req.getAsJsonObject("result").getAsJsonObject("moviedetails"); Movie med = createMovieFromJson(details); if (med != null) { medias.add(med); nbItems++; } } else if (mediaType.equals("episode")) { JsonObject details = req.getAsJsonObject("result").getAsJsonObject("episodedetails"); TVEpisode med = createTVEpisodeFromJson(details); if (med != null) { medias.add(med); nbItems++; } } else if (mediaType.equals("tvshow")) { JsonObject details = req.getAsJsonObject("result").getAsJsonObject("tvshowdetails"); TVShow med = createTVShowFromJson(details); medias.add(med); nbItems++; } else if (mediaType.equals("album")) { JsonObject details = req.getAsJsonObject("result").getAsJsonObject("albumdetails"); Album med = createAlbumFromJson(details); medias.add(med); nbItems++; } else if (mediaType.equals("song")) { JsonObject details = req.getAsJsonObject("result").getAsJsonObject("songdetails"); Song med = createSongFromJson(details); medias.add(med); nbItems++; } else if (mediaType.equals("musicvideo")) { JsonObject details = req.getAsJsonObject("result").getAsJsonObject("musicvideodetails"); MusicVideo med = createMusicvideoFromJson(details); medias.add(med); nbItems++; } } } catch (Exception e) { e.printStackTrace(); } return medias; } private String extractKeyFromArtMap(JsonObject details, String key) { if (details.has("art") && !details.get("art").getAsJsonObject().isJsonNull() && details.get("art").getAsJsonObject().has(key) && !details.get("art").getAsJsonObject().get(key).getAsString().isEmpty()) { return getDownloadUrl(details.get("art").getAsJsonObject().get(key).getAsString()); } return null; } private String convertRating(Double rating) { if(rating == null || rating.doubleValue() <= 0.0) return null; return String.valueOf(rating / 2.0); } }