mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-03-21 17:49:58 -05:00
Allow frontends to launch a new game without force closing Dolphin
Original message: Hey devs, I'm moth, lead developer of the Cocoon Frontend For our now playing integration, we're trying to maximise compatability for launching & swapping games without the user having to force close out of the activity. Dolphin however does not support this at all. No matter what mix of flags and intents I try it just shows the MainActivity. After a deep dive I found out: EmulationActivity has an ignoreLaunchRequests check that is set to true until the end of NativeLibrary.Run() the launch() method returns if its true and just keeps you in MainActivity, never launching the new ROM This is a problem because Cocoon and other frontends need to use CLEAR_TASK to destroy the existing task and start fresh to load the new ROM. This destroys EmulationActivity & Fragment but the process still survives so NativeLibrary.Run never returns gracefully. This makes it so relaunching a new ROM does not work, even if we clear the activity. Also MainActivity or EmulationActivity doesnt handle onNewIntent() This would be the graceful way to handle it so we can use CLEAR_TOP | SINGLE_TOP without being ignored. The two fixes are: in StartupHandler.HandleInit(), reset the flag before launching so the cleared task's limbo state of ignoreLaunchRequests is reset The more graceful way would be to add override fun onNewIntent(intent: Intent) super.onNewIntent(intent) setIntent(intent) StartupHandler.HandleInit(this) } in your MainActivity This would let frontends redeliver game intents without destroying the entire task After implementation: I added multiple guards to ensure proper synchronicity and ensure emulators and surfaces are finished before starting a new game. Frontends can now take advantage of NEW_TASK | CLEAR_TASK to launch a new Dolphin game.
This commit is contained in:
parent
f074cdb08b
commit
57014eec4d
|
|
@ -119,7 +119,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
}
|
||||
|
||||
override fun onDetach() {
|
||||
NativeLibrary.clearEmulationActivity()
|
||||
// Don't clear the reference if a newer EmulationActivity already took over
|
||||
if (NativeLibrary.getEmulationActivity() === emulationActivity) {
|
||||
NativeLibrary.clearEmulationActivity()
|
||||
}
|
||||
super.onDetach()
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +157,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
|
||||
override fun surfaceDestroyed(holder: SurfaceHolder) {
|
||||
Log.debug("[EmulationFragment] Surface destroyed.")
|
||||
NativeLibrary.SurfaceDestroyed()
|
||||
// Don't tear down the surface if a newer EmulationActivity already took over
|
||||
if (NativeLibrary.getEmulationActivity() === emulationActivity) {
|
||||
NativeLibrary.SurfaceDestroyed()
|
||||
}
|
||||
runWhenSurfaceIsValid = true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package org.dolphinemu.dolphinemu.ui.main
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
|
|
@ -90,6 +91,12 @@ class MainActivity : AppCompatActivity(), MainView, OnRefreshListener, ThemeProv
|
|||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
StartupHandler.HandleInit(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
ThemeHelper.setCorrectTheme(this)
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@ class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
StartupHandler.HandleInit(this)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (DirectoryInitialization.shouldStart(this)) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
|
@ -38,11 +41,44 @@ public final class StartupHandler
|
|||
String[] gamesToLaunch = getGamesFromIntent(parent.getIntent());
|
||||
if (gamesToLaunch != null && gamesToLaunch.length > 0)
|
||||
{
|
||||
// Start the emulation activity, send the ISO passed in and finish the main activity
|
||||
EmulationActivity.launch(parent, gamesToLaunch, false, true);
|
||||
// If a previous session is still running, stop it and wait for it to finish
|
||||
// before launching the new game. StopEmulation is async, so launching immediately
|
||||
// would race with the old emulation thread's cleanup.
|
||||
if (!NativeLibrary.IsUninitialized())
|
||||
{
|
||||
NativeLibrary.StopEmulation();
|
||||
waitForStopThenLaunch(parent, gamesToLaunch);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmulationActivity.stopIgnoringLaunchRequests();
|
||||
EmulationActivity.launch(parent, gamesToLaunch, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void waitForStopThenLaunch(FragmentActivity parent, String[] gamesToLaunch)
|
||||
{
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
final long deadline = System.currentTimeMillis() + 5000;
|
||||
handler.postDelayed(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (NativeLibrary.IsUninitialized() || System.currentTimeMillis() >= deadline)
|
||||
{
|
||||
EmulationActivity.stopIgnoringLaunchRequests();
|
||||
EmulationActivity.launch(parent, gamesToLaunch, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler.postDelayed(this, 100);
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
private static String[] getGamesFromIntent(Intent intent)
|
||||
{
|
||||
// Priority order when looking for game paths in an intent:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user