diff --git a/es-app/src/main.cpp b/es-app/src/main.cpp index fe0c191af..e6010c332 100644 --- a/es-app/src/main.cpp +++ b/es-app/src/main.cpp @@ -719,10 +719,6 @@ int main(int argc, char* argv[]) renderer = Renderer::getInstance(); window = Window::getInstance(); -#if defined(__ANDROID__) - Utils::Platform::Android::setupResources(); -#endif - ViewController::getInstance()->setMenuColors(); CollectionSystemsManager::getInstance(); Screensaver screensaver; @@ -740,6 +736,24 @@ int main(int argc, char* argv[]) LOG(LogDebug) << "Android storage state: " << SDL_AndroidGetExternalStorageState(); LOG(LogDebug) << "Android internal path: " << SDL_AndroidGetInternalStoragePath(); LOG(LogDebug) << "Android external path: " << SDL_AndroidGetExternalStoragePath(); + Utils::Platform::Android::setDataDirectory(); + { + std::string buildIdentifier {PROGRAM_VERSION_STRING}; + buildIdentifier.append(" (r") + .append(std::to_string(PROGRAM_RELEASE_NUMBER)) + .append("), built ") + .append(PROGRAM_BUILT_STRING); + if (Utils::Platform::Android::checkNeedResourceCopy(buildIdentifier)) { + LOG(LogInfo) << "Application has been updated or it's a new installation, copying " + "bundled resources and themes to internal storage..."; + if (Settings::getInstance()->getBool("SplashScreen")) + window->renderSplashScreen(Window::SplashScreenState::RESOURCE_COPY, 0.0f); + if (Utils::Platform::Android::setupResources(buildIdentifier)) { + LOG(LogError) << "Copying of resources and themes failed"; + return -1; + } + } + } #endif #if defined(APPLICATION_UPDATER) diff --git a/es-core/src/Window.cpp b/es-core/src/Window.cpp index 4ef169f3c..904661d63 100644 --- a/es-core/src/Window.cpp +++ b/es-core/src/Window.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT // -// EmulationStation Desktop Edition +// ES-DE Frontend // Window.cpp // // Window management, screensaver management, help prompts and splash screen. @@ -144,6 +144,8 @@ bool Window::init() mDefaultFonts.at(1)->buildTextCache("Loading systems...", 0.0f, 0.0f, 0x777777FF)); mSplashTextReloading = std::unique_ptr( mDefaultFonts.at(1)->buildTextCache("Reloading...", 0.0f, 0.0f, 0x777777FF)); + mSplashTextResourceCopy = std::unique_ptr( + mDefaultFonts.at(1)->buildTextCache("Copying resources...", 0.0f, 0.0f, 0x777777FF)); mSplashTextPositions.x = (mRenderer->getScreenWidth() - mSplashTextScanning->metrics.size.x) / 2.0f; @@ -698,6 +700,9 @@ void Window::renderSplashScreen(SplashScreenState state, float progress) textPosX = mSplashTextPositions.w; textPosY += mDefaultFonts.at(1)->getLetterHeight(); } + else if (state == SplashScreenState::RESOURCE_COPY) { + textPosX = (mRenderer->getScreenWidth() - mSplashTextResourceCopy->metrics.size.x) / 2.0f; + } trans = glm::translate(trans, glm::round(glm::vec3 {textPosX, textPosY, 0.0f})); mRenderer->setMatrix(trans); @@ -708,6 +713,8 @@ void Window::renderSplashScreen(SplashScreenState state, float progress) mDefaultFonts.at(1)->renderTextCache(mSplashTextPopulating.get()); else if (state == SplashScreenState::RELOADING) mDefaultFonts.at(1)->renderTextCache(mSplashTextReloading.get()); + else if (state == SplashScreenState::RESOURCE_COPY) + mDefaultFonts.at(1)->renderTextCache(mSplashTextResourceCopy.get()); mRenderer->swapBuffers(); } diff --git a/es-core/src/Window.h b/es-core/src/Window.h index 198e8c2a7..8ea2f4fbd 100644 --- a/es-core/src/Window.h +++ b/es-core/src/Window.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT // -// EmulationStation Desktop Edition +// ES-DE Frontend // Window.h // // Window management, screensaver management, help prompts and splash screen. @@ -109,7 +109,8 @@ public: enum class SplashScreenState { SCANNING, POPULATING, - RELOADING + RELOADING, + RESOURCE_COPY }; void renderSplashScreen(SplashScreenState state, float progress); @@ -188,6 +189,7 @@ private: std::unique_ptr mSplashTextScanning; std::unique_ptr mSplashTextPopulating; std::unique_ptr mSplashTextReloading; + std::unique_ptr mSplashTextResourceCopy; glm::vec4 mSplashTextPositions; std::vector mProgressBarRectangles; diff --git a/es-core/src/utils/PlatformUtil.cpp b/es-core/src/utils/PlatformUtil.cpp index d9de622e5..e5c3802ca 100644 --- a/es-core/src/utils/PlatformUtil.cpp +++ b/es-core/src/utils/PlatformUtil.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT // -// ES-DE +// ES-DE Frontend // Platform.cpp // // Platform utility functions. @@ -387,7 +387,7 @@ namespace Utils return result; } - bool setupResources() + void setDataDirectory() { JNIEnv* jniEnv {reinterpret_cast(SDL_AndroidGetJNIEnv())}; { @@ -401,12 +401,29 @@ namespace Utils jniEnv->ReleaseStringUTFChars(dataDirectory, dataDirUtf); jniEnv->DeleteLocalRef(jniClass); } + } + + bool checkNeedResourceCopy(const std::string& buildIdentifier) + { + JNIEnv* jniEnv {reinterpret_cast(SDL_AndroidGetJNIEnv())}; + jclass jniClass {jniEnv->FindClass("org/es_de/frontend/MainActivity")}; + jmethodID methodID {jniEnv->GetStaticMethodID(jniClass, "checkNeedResourceCopy", + "(Ljava/lang/String;)Z")}; + const bool returnValue {static_cast(jniEnv->CallStaticBooleanMethod( + jniClass, methodID, jniEnv->NewStringUTF(buildIdentifier.c_str())))}; + jniEnv->DeleteLocalRef(jniClass); + return returnValue; + } + + bool setupResources(const std::string& buildIdentifier) + { + JNIEnv* jniEnv {reinterpret_cast(SDL_AndroidGetJNIEnv())}; { jclass jniClass {jniEnv->FindClass("org/es_de/frontend/MainActivity")}; - jmethodID methodID { - jniEnv->GetStaticMethodID(jniClass, "setupResources", "()Z")}; - const bool returnValue { - static_cast(jniEnv->CallStaticBooleanMethod(jniClass, methodID))}; + jmethodID methodID {jniEnv->GetStaticMethodID(jniClass, "setupResources", + "(Ljava/lang/String;)Z")}; + const bool returnValue {static_cast(jniEnv->CallStaticBooleanMethod( + jniClass, methodID, jniEnv->NewStringUTF(buildIdentifier.c_str())))}; jniEnv->DeleteLocalRef(jniClass); if (returnValue) { LOG(LogError) << "Couldn't setup application resources on internal storage"; @@ -415,9 +432,10 @@ namespace Utils } { jclass jniClass {jniEnv->FindClass("org/es_de/frontend/MainActivity")}; - jmethodID methodID {jniEnv->GetStaticMethodID(jniClass, "setupThemes", "()Z")}; - const bool returnValue { - static_cast(jniEnv->CallStaticBooleanMethod(jniClass, methodID))}; + jmethodID methodID {jniEnv->GetStaticMethodID(jniClass, "setupThemes", + "(Ljava/lang/String;)Z")}; + const bool returnValue {static_cast(jniEnv->CallStaticBooleanMethod( + jniClass, methodID, jniEnv->NewStringUTF(buildIdentifier.c_str())))}; jniEnv->DeleteLocalRef(jniClass); if (returnValue) { LOG(LogError) << "Couldn't setup application themes on internal storage"; @@ -436,7 +454,7 @@ namespace Utils const bool returnValue {static_cast(jniEnv->CallStaticBooleanMethod( jniClass, methodID, jniEnv->NewStringUTF(packageName.c_str()), jniEnv->NewStringUTF(activity.c_str())))}; - // jniEnv->DeleteLocalRef(jniClass); + jniEnv->DeleteLocalRef(jniClass); return returnValue; } diff --git a/es-core/src/utils/PlatformUtil.h b/es-core/src/utils/PlatformUtil.h index 7c041f0bf..88de575ca 100644 --- a/es-core/src/utils/PlatformUtil.h +++ b/es-core/src/utils/PlatformUtil.h @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT // -// ES-DE +// ES-DE Frontend // Platform.h // // Platform utility functions. @@ -60,7 +60,9 @@ namespace Utils namespace Android { bool requestStoragePermission(); - bool setupResources(); + void setDataDirectory(); + bool checkNeedResourceCopy(const std::string& buildIdentifier); + bool setupResources(const std::string& buildIdentifier); bool checkEmulatorInstalled(const std::string& packageName, const std::string& activity); int launchGame(const std::string& packageName,