From e28f4976447c151c6a300a9c42766551c1e0ff2f Mon Sep 17 00:00:00 2001 From: Maven85 Date: Mon, 9 Mar 2020 13:40:17 +0100 Subject: [Android TV] fixed cover display for channels Reviewed-by: Jose Luis Marti --- cmake/scripts/android/Install.cmake | 1 + .../android/packaging/xbmc/src/XBMCJsonRPC.java.in | 63 ++++++++++++++-------- .../packaging/xbmc/src/XBMCTextureCache.java.in | 32 +++++++++++ xbmc/platform/android/activity/CMakeLists.txt | 2 + .../android/activity/JNIXBMCTextureCache.cpp | 42 +++++++++++++++ .../android/activity/JNIXBMCTextureCache.h | 29 ++++++++++ xbmc/platform/android/activity/android_main.cpp | 2 + 7 files changed, 150 insertions(+), 21 deletions(-) create mode 100644 tools/android/packaging/xbmc/src/XBMCTextureCache.java.in create mode 100644 xbmc/platform/android/activity/JNIXBMCTextureCache.cpp create mode 100644 xbmc/platform/android/activity/JNIXBMCTextureCache.h diff --git a/cmake/scripts/android/Install.cmake b/cmake/scripts/android/Install.cmake index f88957cc9f..b912141007 100644 --- a/cmake/scripts/android/Install.cmake +++ b/cmake/scripts/android/Install.cmake @@ -48,6 +48,7 @@ set(package_files strings.xml src/XBMCProperties.java src/XBMCVideoView.java src/XBMCFile.java + src/XBMCTextureCache.java src/XBMCURIUtils.java src/channels/SyncChannelJobService.java src/channels/SyncProgramsJobService.java diff --git a/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in b/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in index 24d9239d89..9ec4a64641 100644 --- a/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in +++ b/tools/android/packaging/xbmc/src/XBMCJsonRPC.java.in @@ -24,15 +24,15 @@ import android.net.Uri; import android.provider.BaseColumns; import android.util.Log; +import @APP_PACKAGE@.content.XBMCFileContentProvider; import @APP_PACKAGE@.model.Album; +import @APP_PACKAGE@.model.File; +import @APP_PACKAGE@.model.Media; 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 { @@ -63,6 +63,7 @@ public class XBMCJsonRPC private String m_xbmc_web_url = "http://localhost:8080"; private HashSet mRecomendationIds = new HashSet(); + private XBMCTextureCache mTextureCache = null; private int MAX_RECOMMENDATIONS = 3; @@ -126,6 +127,7 @@ public class XBMCJsonRPC { String jsonPort = XBMCProperties.getStringProperty("xbmc.jsonPort", "8080"); m_xbmc_web_url = "http://localhost:" + jsonPort; + mTextureCache = new XBMCTextureCache(); } public String request_string(String jsonRequest) @@ -864,7 +866,7 @@ public class XBMCJsonRPC String poster = extractKeyFromArtMap(details, "poster"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("2:3"); } // fallback to thumb @@ -873,7 +875,7 @@ public class XBMCJsonRPC poster = extractKeyFromArtMap(details, "thumb"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("16:9"); } } @@ -881,7 +883,7 @@ public class XBMCJsonRPC String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("videodb://movies/titles/" + details.get("movieid").getAsString() + "?showinfo=true"); @@ -935,7 +937,7 @@ public class XBMCJsonRPC String poster = extractKeyFromArtMap(details, "poster"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("2:3"); } // fallback to thumb @@ -944,7 +946,7 @@ public class XBMCJsonRPC poster = extractKeyFromArtMap(details, "thumb"); if (poster != null && !poster.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(poster).toString()); + med.setCardImageUrl(getImageUrl(poster)); med.setCardImageAspectRatio("16:9"); } } @@ -952,7 +954,7 @@ public class XBMCJsonRPC String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("videodb://tvshows/titles/" + details.get("tvshowid").getAsInt() + "/"); med.setCategory(Media.MEDIA_TYPE_TVSHOW); @@ -982,14 +984,14 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("16:9"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("videodb://tvshows/titles/" + details.get("tvshowid").getAsInt() + "/" + details.get("episodeid").getAsInt() + "?showinfo=true"); @@ -1029,14 +1031,14 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } med.setXbmcUrl("musicdb://albums/" + details.get("albumid").getAsString() + "/"); @@ -1064,7 +1066,7 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "album.thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } // fallback to albumartist.thumb @@ -1073,7 +1075,7 @@ public class XBMCJsonRPC thumb = extractKeyFromArtMap(details, "albumartist.thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } else @@ -1082,7 +1084,7 @@ public class XBMCJsonRPC thumb = extractKeyFromArtMap(details, "artist.thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } } @@ -1091,14 +1093,14 @@ public class XBMCJsonRPC String fanart = extractKeyFromArtMap(details, "albumartist.fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } else { fanart = extractKeyFromArtMap(details, "artist.fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } } @@ -1145,21 +1147,21 @@ public class XBMCJsonRPC String thumb = extractKeyFromArtMap(details, "thumb"); if (thumb != null && !thumb.isEmpty()) { - med.setCardImageUrl(XBMCFileContentProvider.buildUri(thumb).toString()); + med.setCardImageUrl(getImageUrl(thumb)); med.setCardImageAspectRatio("1:1"); } // fanart String fanart = extractKeyFromArtMap(details, "fanart"); if (fanart != null && !fanart.isEmpty()) { - med.setBackgroundImageUrl(XBMCFileContentProvider.buildUri(fanart).toString()); + med.setBackgroundImageUrl(getImageUrl(fanart)); } 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.setVideoUrl(getImageUrl(url)); med.setCategory(Media.MEDIA_TYPE_MUSICVIDEO); } @@ -1438,4 +1440,23 @@ public class XBMCJsonRPC return String.valueOf(rating / 2.0); } + private String getImageUrl(String sUrl) + { + Log.d(TAG, "getImageUrl: sUrl = " + sUrl); + if (sUrl.startsWith("image://video@") || sUrl.startsWith("image://music@")) + { + Log.d(TAG, "getImageUrl: " + sUrl + " is not unwrapped"); + return XBMCFileContentProvider.buildUri(sUrl).toString(); + } + + String sUnwrapImageUrl = this.mTextureCache.unwrapImageURL(sUrl); + Log.d(TAG, "getImageUrl: sUnwrapImageUrl = " + sUnwrapImageUrl); + if (!sUnwrapImageUrl.startsWith("http")) + { + return XBMCFileContentProvider.buildUri(sUrl).toString(); + } + + return sUnwrapImageUrl; + } + } diff --git a/tools/android/packaging/xbmc/src/XBMCTextureCache.java.in b/tools/android/packaging/xbmc/src/XBMCTextureCache.java.in new file mode 100644 index 0000000000..09dd7265f5 --- /dev/null +++ b/tools/android/packaging/xbmc/src/XBMCTextureCache.java.in @@ -0,0 +1,32 @@ +package @APP_PACKAGE@; + +import android.util.Log; + +/** + * Created by Maven85 on 16/03/2020. + */ + +public class XBMCTextureCache +{ + native String _unwrapImageURL(String image); + + private static final String TAG = "@APP_NAME@"; + + public XBMCTextureCache() + { + } + + public String unwrapImageURL(String image) + { + try + { + return _unwrapImageURL(image); + } + catch (Exception e) + { + Log.e(TAG, "unwrapImageURL: Exception: " + e.getMessage()); + return null; + } + } + +} diff --git a/xbmc/platform/android/activity/CMakeLists.txt b/xbmc/platform/android/activity/CMakeLists.txt index fddcec8525..55714df929 100644 --- a/xbmc/platform/android/activity/CMakeLists.txt +++ b/xbmc/platform/android/activity/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES android_main.cpp JNIXBMCNsdManagerResolveListener.cpp JNIXBMCJsonHandler.cpp JNIXBMCFile.cpp + JNIXBMCTextureCache.cpp JNIXBMCURIUtils.cpp JNIXBMCDisplayManagerDisplayListener.cpp JNIXBMCSpeechRecognitionListener.cpp @@ -42,6 +43,7 @@ set(HEADERS AndroidFeatures.h JNIXBMCNsdManagerResolveListener.h JNIXBMCJsonHandler.h JNIXBMCFile.h + JNIXBMCTextureCache.h JNIXBMCURIUtils.h JNIXBMCDisplayManagerDisplayListener.h JNIXBMCSpeechRecognitionListener.h diff --git a/xbmc/platform/android/activity/JNIXBMCTextureCache.cpp b/xbmc/platform/android/activity/JNIXBMCTextureCache.cpp new file mode 100644 index 0000000000..bacb4a826d --- /dev/null +++ b/xbmc/platform/android/activity/JNIXBMCTextureCache.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "JNIXBMCTextureCache.h" + +#include "CompileInfo.h" +#include "TextureCache.h" + +#include +#include + +using namespace jni; + +static std::string s_className = std::string(CCompileInfo::GetClass()) + "/XBMCTextureCache"; + +void CJNIXBMCTextureCache::RegisterNatives(JNIEnv* env) +{ + jclass cClass = env->FindClass(s_className.c_str()); + if (cClass) + { + JNINativeMethod methods[] = { + {"_unwrapImageURL", "(Ljava/lang/String;)Ljava/lang/String;", + (void*)&CJNIXBMCTextureCache::_unwrapImageURL}, + }; + + env->RegisterNatives(cClass, methods, sizeof(methods) / sizeof(methods[0])); + } +} + +jstring CJNIXBMCTextureCache::_unwrapImageURL(JNIEnv* env, jobject thiz, jstring image) +{ + std::string strImage = jcast(jhstring::fromJNI(image)); + std::string responseData = CTextureUtils::UnwrapImageURL(strImage); + + jstring jres = env->NewStringUTF(responseData.c_str()); + return jres; +} diff --git a/xbmc/platform/android/activity/JNIXBMCTextureCache.h b/xbmc/platform/android/activity/JNIXBMCTextureCache.h new file mode 100644 index 0000000000..92da6e91d5 --- /dev/null +++ b/xbmc/platform/android/activity/JNIXBMCTextureCache.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include + +namespace jni +{ + +class CJNIXBMCTextureCache : public CJNIBase +{ +public: + CJNIXBMCTextureCache(const jni::jhobject& object) : CJNIBase(object) {} + + static void RegisterNatives(JNIEnv* env); + +protected: + ~CJNIXBMCTextureCache() override = default; + + static jstring _unwrapImageURL(JNIEnv* env, jobject thiz, jstring image); +}; + +} // namespace jni diff --git a/xbmc/platform/android/activity/android_main.cpp b/xbmc/platform/android/activity/android_main.cpp index 3970e78f49..a934b6ee1c 100644 --- a/xbmc/platform/android/activity/android_main.cpp +++ b/xbmc/platform/android/activity/android_main.cpp @@ -23,6 +23,7 @@ #include "platform/android/activity/JNIXBMCNsdManagerResolveListener.h" #include "platform/android/activity/JNIXBMCSpeechRecognitionListener.h" #include "platform/android/activity/JNIXBMCSurfaceTextureOnFrameAvailableListener.h" +#include "platform/android/activity/JNIXBMCTextureCache.h" #include "platform/android/activity/JNIXBMCURIUtils.h" #include "platform/android/activity/JNIXBMCVideoView.h" @@ -127,6 +128,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) CJNIXBMCNsdManagerResolveListener::RegisterNatives(env); CJNIXBMCSpeechRecognitionListener::RegisterNatives(env); CJNIXBMCSurfaceTextureOnFrameAvailableListener::RegisterNatives(env); + CJNIXBMCTextureCache::RegisterNatives(env); CJNIXBMCURIUtils::RegisterNatives(env); CJNIXBMCVideoView::RegisterNatives(env); -- cgit v1.2.3