mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-03-27 13:50:22 -06:00
android: Fix launching applications through intent data in vanilla build (#1896)
* android: Fix launching applications through intent data in vanilla build * GameHelper.kt: Use Uri.scheme where applicable --------- Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
This commit is contained in:
parent
ae9972b6be
commit
3d5ba09eb1
@ -18,6 +18,7 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.os.SystemClock
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
@ -73,6 +74,7 @@ import org.citra.citra_emu.features.settings.model.SettingsViewModel
|
||||
import org.citra.citra_emu.features.settings.ui.SettingsActivity
|
||||
import org.citra.citra_emu.features.settings.utils.SettingsFile
|
||||
import org.citra.citra_emu.model.Game
|
||||
import org.citra.citra_emu.utils.BuildUtil
|
||||
import org.citra.citra_emu.utils.DirectoryInitialization
|
||||
import org.citra.citra_emu.utils.DirectoryInitialization.DirectoryInitializationState
|
||||
import org.citra.citra_emu.utils.EmulationMenuSettings
|
||||
@ -108,6 +110,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||
private val onPause = Runnable{ togglePause() }
|
||||
private val onShutdown = Runnable{ emulationState.stop() }
|
||||
|
||||
// Only used if a game is passed through intent on google play variant
|
||||
private var gameFd: Int? = null
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
if (context is EmulationActivity) {
|
||||
@ -125,27 +130,34 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = requireActivity().intent
|
||||
val intentUri: Uri? = intent.data
|
||||
var intentUri: Uri? = intent.data
|
||||
val oldIntentInfo = Pair(
|
||||
intent.getStringExtra("SelectedGame"),
|
||||
intent.getStringExtra("SelectedTitle")
|
||||
)
|
||||
var intentGame: Game? = null
|
||||
intentUri = if (intentUri == null && oldIntentInfo.first != null) {
|
||||
Uri.parse(oldIntentInfo.first)
|
||||
} else {
|
||||
intentUri
|
||||
}
|
||||
if (intentUri != null) {
|
||||
intentGame = if (Game.extensions.contains(FileUtil.getExtension(intentUri))) {
|
||||
// isInstalled, addedToLibrary and mediaType do not matter here
|
||||
GameHelper.getGame(intentUri, isInstalled = false, addedToLibrary = false, mediaType = Game.MediaType.GAME_CARD)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else if (oldIntentInfo.first != null) {
|
||||
val gameUri = Uri.parse(oldIntentInfo.first)
|
||||
intentGame = if (Game.extensions.contains(FileUtil.getExtension(gameUri))) {
|
||||
// isInstalled, addedToLibrary and mediaType do not matter here
|
||||
GameHelper.getGame(gameUri, isInstalled = false, addedToLibrary = false, mediaType = Game.MediaType.GAME_CARD)
|
||||
} else {
|
||||
null
|
||||
if (!BuildUtil.isGooglePlayBuild) {
|
||||
// We need to build a special path as the incoming URI may be SAF exclusive
|
||||
Log.warning("[EmulationFragment] Cannot determine native path of URI \"" +
|
||||
intentUri.toString() + "\", using file descriptor instead.")
|
||||
gameFd = requireContext().contentResolver.openFileDescriptor(intentUri, "r")?.detachFd()
|
||||
intentUri = if (gameFd != null) {
|
||||
Uri.parse("fd://" + gameFd.toString())
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
intentGame =
|
||||
intentUri?.let {
|
||||
// isInstalled, addedToLibrary and mediaType do not matter here
|
||||
GameHelper.getGame(it, isInstalled = false, addedToLibrary = false, mediaType = Game.MediaType.GAME_CARD)
|
||||
}
|
||||
}
|
||||
|
||||
val insertedCartridge = preferences.getString("insertedCartridge", "")
|
||||
@ -163,6 +175,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||
return
|
||||
}
|
||||
|
||||
Log.info("[EmulationFragment] Starting application " + game.path)
|
||||
|
||||
// So this fragment doesn't restart on configuration changes; i.e. rotation.
|
||||
retainInstance = true
|
||||
emulationState = EmulationState(game.path)
|
||||
@ -528,6 +542,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
|
||||
override fun onDestroy() {
|
||||
EmulationLifecycleUtil.removeHook(onPause)
|
||||
EmulationLifecycleUtil.removeHook(onShutdown)
|
||||
if (gameFd != null) {
|
||||
ParcelFileDescriptor.adoptFd(gameFd!!).close()
|
||||
gameFd = null
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
||||
@ -222,6 +222,10 @@ object FileUtil {
|
||||
var filename = ""
|
||||
var c: Cursor? = null
|
||||
try {
|
||||
if (uri.scheme == "fd") {
|
||||
return ""
|
||||
}
|
||||
|
||||
if (uri.scheme == "file") {
|
||||
BuildUtil.assertNotGooglePlay()
|
||||
val file = File(uri.path!!);
|
||||
|
||||
@ -75,7 +75,11 @@ object GameHelper {
|
||||
if (BuildUtil.isGooglePlayBuild || FileUtil.isNativePath(filePath)) {
|
||||
gameInfo = GameInfo(filePath)
|
||||
} else {
|
||||
nativePath = "!" + NativeLibrary.getNativePath(uri);
|
||||
nativePath = if (uri.scheme == "fd") {
|
||||
uri.toString()
|
||||
} else {
|
||||
"!" + NativeLibrary.getNativePath(uri)
|
||||
};
|
||||
gameInfo = GameInfo(nativePath)
|
||||
}
|
||||
|
||||
|
||||
@ -122,6 +122,16 @@ typedef struct stat file_stat_t;
|
||||
#define FERROR ferror
|
||||
#define FFLUSH std::fflush
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define DUP_FD _dup
|
||||
#define FDOPEN _fdopen
|
||||
#define CLOSE_FD _close
|
||||
#else
|
||||
#define DUP_FD dup
|
||||
#define FDOPEN fdopen
|
||||
#define CLOSE_FD close
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// This namespace has various generic functions related to files and paths.
|
||||
@ -1262,6 +1272,44 @@ void IOFile::Swap(IOFile& other) noexcept {
|
||||
bool IOFile::Open() {
|
||||
Close();
|
||||
|
||||
// Any filename with the format fd://<file_descriptor> represents a file that
|
||||
// must be opened by duplicating the provided file_descriptor. This is used
|
||||
// on Android vanilla builds when the ROM absolute path is not known.
|
||||
if (filename.starts_with("fd://")) {
|
||||
|
||||
#if !defined(HAVE_LIBRETRO_VFS)
|
||||
const std::string fd_str = filename.substr(5);
|
||||
|
||||
// Check that fd_str is not empty and contains only digits
|
||||
if (fd_str.empty() || !std::all_of(fd_str.begin(), fd_str.end(), ::isdigit)) {
|
||||
m_good = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = std::stoi(fd_str);
|
||||
|
||||
int dup_fd = DUP_FD(fd);
|
||||
if (dup_fd == -1) {
|
||||
m_good = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_file = FDOPEN(dup_fd, openmode.c_str());
|
||||
if (!m_file) {
|
||||
CLOSE_FD(dup_fd);
|
||||
m_good = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_good = true;
|
||||
return true;
|
||||
#else
|
||||
// TODO: Add support for libretro vfs when needed.
|
||||
m_good = false;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Open with FILE_SHARE_READ, FILE_SHARE_WRITE and FILE_SHARE_DELETE
|
||||
// flags. This mimics linux behaviour as much as possible, which
|
||||
|
||||
Loading…
Reference in New Issue
Block a user