diff --git a/app/src/main/cpp/CelestiaRenderer.cpp b/app/src/main/cpp/CelestiaRenderer.cpp index 92009f64..31d8c7e8 100644 --- a/app/src/main/cpp/CelestiaRenderer.cpp +++ b/app/src/main/cpp/CelestiaRenderer.cpp @@ -318,9 +318,15 @@ void *CelestiaRenderer::threadCallback(void *self) bool renderingEnabled = true; - while (renderingEnabled) { + while (renderingEnabled) + { if (renderer->surface != EGL_NO_SURFACE && !renderer->engineStartedCalled) - renderer->engineStartedCalled = newEnv->CallBooleanMethod(renderer->javaObject, CelestiaRenderer::engineStartedMethod) == JNI_TRUE; + { + bool started = newEnv->CallBooleanMethod(renderer->javaObject, CelestiaRenderer::engineStartedMethod) == JNI_TRUE; + if (!started) + break; + renderer->engineStartedCalled = true; + } if (renderer->engineStartedCalled) newEnv->CallVoidMethod(renderer->javaObject, CelestiaRenderer::flushTasksMethod); @@ -334,7 +340,6 @@ void *CelestiaRenderer::threadCallback(void *self) break; case CelestiaRenderer::MSG_RENDER_LOOP_EXIT: renderingEnabled = false; - renderer->destroy(); break; default: break; @@ -356,6 +361,7 @@ void *CelestiaRenderer::threadCallback(void *self) LOG_ERROR("eglSwapBuffers() returned error %d", eglGetError()); } } + renderer->destroy(); // Detach CelestiaRenderer::jvm->DetachCurrentThread(); diff --git a/app/src/main/java/space/celestia/mobilecelestia/MainActivity.kt b/app/src/main/java/space/celestia/mobilecelestia/MainActivity.kt index 4dd3ce79..0e5de8f1 100644 --- a/app/src/main/java/space/celestia/mobilecelestia/MainActivity.kt +++ b/app/src/main/java/space/celestia/mobilecelestia/MainActivity.kt @@ -124,12 +124,15 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), private var readyForInteraction = false private var scriptOrURLPath: String? = null + private val defaultConfigFilePath by lazy { "$defaultDataDirectoryPath/$CELESTIA_CFG_NAME" } + private val defaultDataDirectoryPath by lazy { "$celestiaParentPath/$CELESTIA_DATA_FOLDER_NAME" } + private val celestiaConfigFilePath: String get() { val custom = customConfigFilePath if (custom != null) return custom - return "$celestiaParentPath/$CELESTIA_DATA_FOLDER_NAME/$CELESTIA_CFG_NAME" + return defaultConfigFilePath } private val celestiaDataDirPath: String @@ -137,7 +140,7 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), val custom = customDataDirPath if (custom != null) return custom - return "$celestiaParentPath/$CELESTIA_DATA_FOLDER_NAME" + return defaultDataDirectoryPath } private val fontDirPath: String @@ -207,7 +210,7 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), val currentState = AppStatusReporter.shared().state if (currentState == AppStatusReporter.State.LOADING_FAILURE || currentState == AppStatusReporter.State.EXTERNAL_LOADING_FAILURE) { - celestiaUnrecoveableLoadingFailed() + celestiaLoadingFailed() return } @@ -340,9 +343,7 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), override fun celestiaLoadingStateChanged(newState: AppStatusReporter.State) { if (newState == AppStatusReporter.State.SUCCESS) { celestiaLoadingSucceeded() - } else if (newState == AppStatusReporter.State.EXTERNAL_LOADING_FAILURE) { - celestiaUnrecoveableLoadingFailed() - } else if (newState == AppStatusReporter.State.LOADING_FAILURE) { + } else if (newState == AppStatusReporter.State.EXTERNAL_LOADING_FAILURE || newState == AppStatusReporter.State.LOADING_FAILURE) { celestiaLoadingFailed() } } @@ -367,26 +368,10 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), } } - fun celestiaUnrecoveableLoadingFailed() { - AppStatusReporter.shared().updateStatus(CelestiaString("Please restart Celestia", "")) - } - fun celestiaLoadingFailed() { AppStatusReporter.shared().updateStatus(CelestiaString("Loading Celestia failed…", "")) - val recoverable = customDataDirPath != null || customConfigFilePath != null - if (!recoverable) { - celestiaUnrecoveableLoadingFailed() - return - } lifecycleScope.launch { removeCelestiaFragment() - showAlert(CelestiaString("Error loading data, fallback to original configuration.", "")) { - // Fallback to default - setConfigFilePath(null) - setDataDirectoryPath(null) - AppStatusReporter.shared().updateState(AppStatusReporter.State.EXTERNAL_LOADING_FINISHED) - loadConfigSuccess(null) - } } } @@ -1297,6 +1282,20 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), showInfo(selection) } + override fun provideFallbackConfigFilePath(): String { + return defaultConfigFilePath + } + + override fun provideFallbackDataDirectoryPath(): String { + return defaultDataDirectoryPath + } + + override fun celestiaFragmentLoadingFromFallback() { + lifecycleScope.launch { + showAlert(CelestiaString("Error loading data, fallback to original configuration.", "")) + } + } + private fun openURL(url: String) { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) if (intent.resolveActivity(packageManager) != null) diff --git a/app/src/main/java/space/celestia/mobilecelestia/celestia/CelestiaFragment.kt b/app/src/main/java/space/celestia/mobilecelestia/celestia/CelestiaFragment.kt index 5edb4200..5724ccef 100644 --- a/app/src/main/java/space/celestia/mobilecelestia/celestia/CelestiaFragment.kt +++ b/app/src/main/java/space/celestia/mobilecelestia/celestia/CelestiaFragment.kt @@ -77,6 +77,9 @@ class CelestiaFragment: Fragment(), SurfaceHolder.Callback, CelestiaControlView. interface Listener { fun celestiaFragmentDidRequestActionMenu() fun celestiaFragmentDidRequestObjectInfo() + fun provideFallbackConfigFilePath(): String + fun provideFallbackDataDirectoryPath(): String + fun celestiaFragmentLoadingFromFallback() } var listener: Listener? = null @@ -94,9 +97,11 @@ class CelestiaFragment: Fragment(), SurfaceHolder.Callback, CelestiaControlView. languageOverride = it.getString(ARG_LANG_OVERRIDE) } - core.setRenderer(renderer) - renderer.setEngineStartedListener { - load() + if (savedInstanceState == null) { + core.setRenderer(renderer) + renderer.setEngineStartedListener { + loadCelestia() + } } } @@ -242,21 +247,50 @@ class CelestiaFragment: Fragment(), SurfaceHolder.Callback, CelestiaControlView. } @SuppressLint("ClickableViewAccessibility") - private fun loadCelestia(path: String, cfg: String, addon: String?): Boolean { + private fun loadCelestia(): Boolean { + val data = pathToLoad + val cfg = cfgToLoad + val addon = addonToLoad + + if (data == null || cfg == null) { + AppStatusReporter.shared().updateState(AppStatusReporter.State.LOADING_FAILURE) + return false + } + AppStatusReporter.shared().updateState(AppStatusReporter.State.LOADING) CelestiaAppCore.initGL() - CelestiaAppCore.chdir(path) + CelestiaAppCore.chdir(data) // Set up locale - CelestiaAppCore.setLocaleDirectoryPath("$path/locale", languageOverride ?: Locale.getDefault().toString()) + val language = languageOverride ?: Locale.getDefault().toString() + CelestiaAppCore.setLocaleDirectoryPath("$data/locale", language) val extraDirs = if (addon != null) arrayOf(addon) else null // Reading config, data if (!core.startSimulation(cfg, extraDirs, AppStatusReporter.shared())) { - AppStatusReporter.shared().updateState(AppStatusReporter.State.LOADING_FAILURE) - return false + var lis = listener; + if (lis != null) { + // Read from fallback + var fallbackConfigPath = lis.provideFallbackConfigFilePath(); + var fallbackDataPath = lis.provideFallbackDataDirectoryPath(); + if (fallbackConfigPath != cfg || fallbackDataPath != data) { + lis.celestiaFragmentLoadingFromFallback() + CelestiaAppCore.chdir(fallbackDataPath) + CelestiaAppCore.setLocaleDirectoryPath("$fallbackDataPath/locale", language) + if (!core.startSimulation(cfg, extraDirs, AppStatusReporter.shared())) { + AppStatusReporter.shared().updateState(AppStatusReporter.State.LOADING_FAILURE) + return false + } + } else { + AppStatusReporter.shared().updateState(AppStatusReporter.State.LOADING_FAILURE) + return false + } + } else { + AppStatusReporter.shared().updateState(AppStatusReporter.State.LOADING_FAILURE) + return false + } } // Prepare renderer @@ -429,22 +463,6 @@ class CelestiaFragment: Fragment(), SurfaceHolder.Callback, CelestiaControlView. renderer.setSurface(holder.surface) } - private fun load(): Boolean { - val data = pathToLoad - val cfg = cfgToLoad - val addon = addonToLoad - - pathToLoad = null - cfgToLoad = null - addonToLoad = null - - if (data == null || cfg == null) { - AppStatusReporter.shared().updateState(AppStatusReporter.State.LOADING_FAILURE) - return false - } - return loadCelestia(data, cfg, addon) - } - override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { Log.d(TAG, "Resize to $width x $height") renderer.setSurfaceSize(width, height)