(Android) Added find rules logic and launch command configuration logic

Also did some general refactoring of the emulator launch code
This commit is contained in:
Leon Styhre 2023-11-26 13:32:11 +01:00
parent d48872af6c
commit 310fb6e809
6 changed files with 268 additions and 73 deletions

View file

@ -947,6 +947,12 @@ void FileData::launchGame()
bool foundCoreFile {false};
std::vector<std::string> emulatorCorePaths;
#if defined(__ANDROID__)
std::string androidPackage;
std::string androidComponent;
std::vector<std::pair<std::string, std::string>> androidExtras;
#endif
#if defined(_WIN64)
bool hideWindow {false};
@ -997,30 +1003,27 @@ void FileData::launchGame()
// Expand home path if ~ is used.
command = Utils::FileSystem::expandHomePath(command);
std::string preCommandPath;
// Check for any pre-command entry, and if it exists then expand it using the find rules.
if (command.find("%PRECOMMAND_") != std::string::npos) {
preCommandPath = findEmulatorPath(command, true);
const std::pair<std::string, FileData::findEmulatorResult> preCommand {
findEmulator(command, true)};
// Show an error message if there was no matching emulator entry in es_find_rules.xml.
if (preCommandPath.substr(0, 18) == "NO EMULATOR RULE: ") {
const std::string& preCommandEntry {
preCommandPath.substr(18, preCommandPath.size() - 18)};
if (preCommand.second == FileData::findEmulatorResult::NO_RULES) {
LOG(LogError)
<< "Couldn't launch game, either there is no emulator entry for pre-command \""
<< preCommandEntry << "\" in es_find_rules.xml or there are no rules defined";
<< preCommand.first << "\" in es_find_rules.xml or there are no rules defined";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
window->queueInfoPopup("ERROR: MISSING PRE-COMMAND FIND RULES CONFIGURATION FOR '" +
preCommandEntry + "'",
preCommand.first + "'",
6000);
window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true);
return;
}
else if (preCommandPath.empty()) {
LOG(LogError) << "Couldn't launch game, pre-command binary not found";
else if (preCommand.first.empty()) {
LOG(LogError) << "Couldn't launch game, pre-command not found";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
@ -1047,30 +1050,30 @@ void FileData::launchGame()
return;
}
else {
LOG(LogDebug) << "FileData::launchGame(): Pre-command binary set to \""
<< preCommandPath << "\"";
LOG(LogDebug) << "FileData::launchGame(): Pre-command set to \"" << preCommand.first
<< "\"";
}
}
// Check that the emulator binary actually exists, and if so, get its path.
const std::string& binaryPath {findEmulatorPath(command, false)};
// Check that the emulator actually exists, and if so, get its path.
const std::pair<std::string, FileData::findEmulatorResult> emulator {
findEmulator(command, false)};
// Show an error message if there was no matching emulator entry in es_find_rules.xml.
if (binaryPath.substr(0, 18) == "NO EMULATOR RULE: ") {
const std::string& emulatorEntry {binaryPath.substr(18, binaryPath.size() - 18)};
if (emulator.second == FileData::findEmulatorResult::NO_RULES) {
LOG(LogError) << "Couldn't launch game, either there is no emulator entry for \""
<< emulatorEntry << "\" in es_find_rules.xml or there are no rules defined";
<< emulator.first << "\" in es_find_rules.xml or there are no rules defined";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
window->queueInfoPopup(
"ERROR: MISSING EMULATOR FIND RULES CONFIGURATION FOR '" + emulatorEntry + "'", 6000);
"ERROR: MISSING EMULATOR FIND RULES CONFIGURATION FOR '" + emulator.first + "'", 6000);
window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true);
return;
}
else if (binaryPath.empty()) {
LOG(LogError) << "Couldn't launch game, emulator binary not found";
else if (emulator.second == FileData::findEmulatorResult::NOT_FOUND) {
LOG(LogError) << "Couldn't launch game, emulator not found";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
@ -1098,15 +1101,27 @@ void FileData::launchGame()
}
#if defined(_WIN64)
else {
std::string binaryLogPath {Utils::String::replace(
Utils::String::replace(binaryPath, "%ESPATH%", esPath), "/", "\\")};
if (binaryLogPath.front() != '\"' && binaryLogPath.back() != '\"')
binaryLogPath = "\"" + binaryLogPath + "\"";
LOG(LogDebug) << "FileData::launchGame(): Emulator binary set to " << binaryLogPath;
std::string emulatorLogPath {Utils::String::replace(
Utils::String::replace(emulator.first, "%ESPATH%", esPath), "/", "\\")};
if (emulatorLogPath.front() != '\"' && emulatorLogPath.back() != '\"')
emulatorLogPath = "\"" + emulatorLogPath + "\"";
LOG(LogDebug) << "FileData::launchGame(): Emulator set to " << emulatorLogPath;
#else
#if defined(__ANDROID__)
else if (emulator.second == FileData::findEmulatorResult::FOUND_ANDROID_PACKAGE) {
androidPackage = emulator.first;
const size_t pipePos {androidPackage.find('|')};
if (pipePos != std::string::npos) {
androidComponent = androidPackage.substr(pipePos + 1);
androidPackage = androidPackage.substr(0, pipePos);
}
LOG(LogDebug) << "FileData::launchGame(): Found Android emulator package \""
<< androidPackage << "\"";
}
#endif
else if (!isShortcut) {
LOG(LogDebug) << "FileData::launchGame(): Emulator binary set to \""
<< Utils::String::replace(binaryPath, "%ESPATH%", esPath) << "\"";
LOG(LogDebug) << "FileData::launchGame(): Emulator set to \""
<< Utils::String::replace(emulator.first, "%ESPATH%", esPath) << "\"";
#endif
}
@ -1127,11 +1142,12 @@ void FileData::launchGame()
if (spacePos != std::string::npos) {
coreRaw = command.substr(emuPathPos, spacePos - emuPathPos);
#if defined(_WIN64)
coreFile = Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")) +
coreFile =
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")) +
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9);
coreFile = Utils::String::replace(coreFile, "/", "\\");
#else
coreFile = Utils::FileSystem::getParent(binaryPath) +
coreFile = Utils::FileSystem::getParent(emulator.first) +
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9);
#endif
if (hasQuotationMark) {
@ -1192,7 +1208,7 @@ void FileData::launchGame()
// the emulator core using the rules defined in es_find_rules.xml.
for (std::string& path : emulatorCorePaths) {
// The position of the %CORE_ variable could have changed as there may have been an
// %EMULATOR_ variable that was substituted for the actual emulator binary.
// %EMULATOR_ variable that was substituted for the actual emulator.
coreEntryPos = command.find("%CORE_");
coreFilePos = command.find("%", coreEntryPos + 6);
@ -1218,10 +1234,11 @@ void FileData::launchGame()
#if defined(_WIN64)
coreFile = coreFile.replace(
stringPos, 9,
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")));
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")));
coreFile = Utils::String::replace(coreFile, "/", "\\");
#else
coreFile = coreFile.replace(stringPos, 9, Utils::FileSystem::getParent(binaryPath));
coreFile =
coreFile.replace(stringPos, 9, Utils::FileSystem::getParent(emulator.first));
#endif
}
@ -1325,7 +1342,7 @@ void FileData::launchGame()
#if defined(_WIN64)
startDirectory = Utils::String::replace(
startDirectory, "%EMUDIR%",
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")));
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")));
startDirectory = Utils::String::replace(
startDirectory, "%GAMEDIR%",
@ -1336,7 +1353,7 @@ void FileData::launchGame()
#else
startDirectory = Utils::String::replace(
startDirectory, "%EMUDIR%",
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\\", "")));
Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\\", "")));
startDirectory = Utils::String::replace(
startDirectory, "%GAMEDIR%",
@ -1500,7 +1517,7 @@ void FileData::launchGame()
if (Utils::FileSystem::exists(Utils::String::replace(romPath, "\\", ""))) {
LOG(LogInfo) << "Opening app or alias file \""
<< Utils::String::replace(romPath, "\\", "") << "\"";
command = Utils::String::replace(command, binaryPath, "open -W -a");
command = Utils::String::replace(command, emulator.first, "open -W -a");
}
else {
LOG(LogError) << "App or alias file \"" << romPath
@ -1551,7 +1568,7 @@ void FileData::launchGame()
}
romPath = Utils::String::replace(romPath, "%%", "%");
romPath = Utils::String::trim(romPath);
command = Utils::String::replace(command, binaryPath, "");
command = Utils::String::replace(command, emulator.first, "");
execEntry = true;
break;
}
@ -1583,12 +1600,71 @@ void FileData::launchGame()
command = Utils::String::replace(command, "%ROMRAW%", romRaw);
command = Utils::String::replace(command, "%ROMPATH%",
Utils::FileSystem::getEscapedPath(getROMDirectory()));
#if defined(__ANDROID__)
command = Utils::String::replace(command, "%ANDROIDPACKAGE%", androidPackage);
size_t extraPos {command.find("%EXTRA_")};
while (extraPos != std::string::npos) {
if (extraPos != std::string::npos) {
bool invalidEntry {false};
bool isQuoted {false};
std::string extraName;
std::string extraValue;
size_t equalPos {command.find("=", extraPos)};
if (equalPos == std::string::npos)
invalidEntry = true;
if (!invalidEntry && extraPos + 8 >= command.size())
invalidEntry = true;
if (!invalidEntry) {
if (command.length() > equalPos && command[equalPos + 1] == '\"')
isQuoted = true;
extraName = command.substr(extraPos + 7, equalPos - (extraPos + 8));
if (isQuoted) {
const size_t closeQuotePos {command.find("\"", equalPos + 2)};
if (closeQuotePos != std::string::npos)
extraValue = command.substr(equalPos + 2, closeQuotePos - (equalPos + 2));
else
invalidEntry = true;
}
else {
const size_t spacePos {command.find(" ", extraPos)};
if (spacePos != std::string::npos)
extraValue = command.substr(equalPos + 1, spacePos - (equalPos + 1));
else
extraValue = command.substr(equalPos + 1, command.size() - equalPos);
}
if (invalidEntry) {
LOG(LogError) << "Invalid entry in systems configuration file es_systems.xml";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
window->queueInfoPopup("ERROR: INVALID ENTRY IN SYSTEMS CONFIGURATION FILE",
6000);
window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true);
return;
}
if (extraName != "" && extraValue != "")
androidExtras.emplace_back(make_pair(extraName, extraValue));
}
}
extraPos = command.find("%EXTRA_", extraPos + 1);
}
#endif
#if defined(_WIN64)
command = Utils::String::replace(
command, "%ESPATH%", Utils::String::replace(Utils::FileSystem::getExePath(), "/", "\\"));
command = Utils::String::replace(command, "%EMUDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(binaryPath, "\"", ""))));
Utils::String::replace(emulator.first, "\"", ""))));
command = Utils::String::replace(command, "%GAMEDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(romPath, "\"", ""))));
@ -1600,7 +1676,7 @@ void FileData::launchGame()
command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath());
command = Utils::String::replace(command, "%EMUDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(binaryPath, "\\", ""))));
Utils::String::replace(emulator.first, "\\", ""))));
command = Utils::String::replace(command, "%GAMEDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(romPath, "\\", ""))));
@ -1625,8 +1701,19 @@ void FileData::launchGame()
LOG(LogDebug) << "Raw emulator launch command:";
LOG(LogDebug) << commandRaw;
#if defined(__ANDROID__)
LOG(LogInfo) << "Expanded emulator launch parameters:";
LOG(LogInfo) << "Package: " << androidPackage;
LOG(LogInfo) << "Component: "
<< (androidComponent == "" ? "<package default>" : androidComponent);
for (auto& extra : androidExtras) {
LOG(LogInfo) << "Extra name: " << extra.first;
LOG(LogInfo) << "Extra value: " << extra.second;
}
#else
LOG(LogInfo) << "Expanded emulator launch command:";
LOG(LogInfo) << command;
#endif
#if defined(FLATPAK_BUILD)
// Break out of the sandbox.
@ -1645,6 +1732,9 @@ void FileData::launchGame()
returnValue = Utils::Platform::launchGameWindows(
Utils::String::stringToWideString(command),
Utils::String::stringToWideString(startDirectory), runInBackground, hideWindow);
#elif defined(__ANDROID__)
returnValue =
Utils::Platform::Android::launchGame(androidPackage, androidComponent, androidExtras);
#else
returnValue = Utils::Platform::launchGameUnix(command, startDirectory, runInBackground);
#endif
@ -1737,23 +1827,27 @@ void FileData::launchGame()
gameToUpdate->mSystem->onMetaDataSavePoint();
}
const std::string FileData::findEmulatorPath(std::string& command, const bool preCommand)
const std::pair<std::string, FileData::findEmulatorResult> FileData::findEmulator(
std::string& command, const bool preCommand)
{
// Extract the emulator executable from the launch command string. There are two ways
// that the emulator can be defined in es_systems.xml, either using the find rules in
// es_find_rules.xml or via the explicit emulator binary name. In the former case, we
// es_find_rules.xml or via the explicit emulator name. In the former case, we
// need to process any configured systempath and staticpath rules (and for Windows also
// winregistrypath and winregistryvalue rules), and in the latter case we simply search
// for the emulator binary in the system path.
// for the emulator in the system path.
std::string emuExecutable;
std::string exePath;
// Method 1, emulator binary is defined using find rules:
// Method 1, emulator is defined using find rules:
#if defined(_WIN64)
std::vector<std::string> emulatorWinRegistryPaths;
std::vector<std::string> emulatorWinRegistryValues;
#endif
#if defined(__ANDROID__)
std::vector<std::string> emulatorAndroidPackages;
#endif
std::vector<std::string> emulatorSystemPaths;
std::vector<std::string> emulatorStaticPaths;
@ -1782,6 +1876,10 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryPaths;
emulatorWinRegistryValues =
SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryValues;
#endif
#if defined(__ANDROID__)
emulatorAndroidPackages =
SystemData::sFindRules.get()->mEmulators[emulatorEntry].androidPackages;
#endif
emulatorSystemPaths = SystemData::sFindRules.get()->mEmulators[emulatorEntry].systemPaths;
@ -1793,10 +1891,13 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
if (emulatorEntry != "" && emulatorWinRegistryPaths.empty() &&
emulatorWinRegistryValues.empty() && emulatorSystemPaths.empty() &&
emulatorStaticPaths.empty())
#elif defined(__ANDROID__)
if (emulatorEntry != "" && emulatorAndroidPackages.empty() && emulatorSystemPaths.empty() &&
emulatorStaticPaths.empty())
#else
if (emulatorEntry != "" && emulatorSystemPaths.empty() && emulatorStaticPaths.empty())
#endif
return "NO EMULATOR RULE: " + emulatorEntry;
return std::make_pair(emulatorEntry, FileData::findEmulatorResult::NO_RULES);
#if defined(_WIN64)
for (std::string& path : emulatorWinRegistryPaths) {
@ -1834,19 +1935,19 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
continue;
}
// That a value was found does not guarantee that the emulator binary actually exists,
// so check for that as well.
// That a value was found does not guarantee that the emulator actually exists, so
// check for that as well.
if (pathStatus == ERROR_SUCCESS) {
if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(registryPath)) ||
Utils::FileSystem::isSymlink(Utils::String::wideStringToString(registryPath))) {
LOG(LogDebug) << "FileData::findEmulatorPath(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary")
LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command" : "Emulator")
<< " found via winregistrypath rule";
exePath = Utils::FileSystem::getEscapedPath(
Utils::String::wideStringToString(registryPath));
command.replace(startPos, endPos - startPos + 1, exePath);
RegCloseKey(registryKey);
return exePath;
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
}
}
RegCloseKey(registryKey);
@ -1906,25 +2007,45 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
if (!appendString.empty())
path.append(Utils::String::stringToWideString(appendString));
// That a value was found does not guarantee that the emulator binary actually exists,
// That a value was found does not guarantee that the emulator actually exists,
// so check for that as well.
if (pathStatus == ERROR_SUCCESS) {
if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(path)) ||
Utils::FileSystem::isSymlink(Utils::String::wideStringToString(path))) {
LOG(LogDebug) << "FileData::findEmulatorPath(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary")
LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command" : "Emulator")
<< " found via winregistryvalue rule";
exePath =
Utils::FileSystem::getEscapedPath(Utils::String::wideStringToString(path));
command.replace(startPos, endPos - startPos + 1, exePath);
RegCloseKey(registryKey);
return exePath;
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
}
}
RegCloseKey(registryKey);
}
#endif
#if defined(__ANDROID__)
for (std::string& androidpackage : emulatorAndroidPackages) {
// If a pipe character is present in the androidpackage entry it means an explicit Intent
// component should be used rather than the default one. The checkEmulatorInstalled()
// Java function will check for the component as well and if it's not found it flags
// the overall emulator entry as not found.
std::string packageName {androidpackage};
std::string component;
const size_t pipePos {packageName.find('|')};
if (pipePos != std::string::npos) {
component = packageName.substr(pipePos + 1);
packageName = packageName.substr(0, pipePos);
}
if (Utils::Platform::Android::checkEmulatorInstalled(packageName, component)) {
return std::make_pair(androidpackage,
FileData::findEmulatorResult::FOUND_ANDROID_PACKAGE);
}
}
#endif
for (std::string& path : emulatorSystemPaths) {
#if defined(_WIN64)
std::wstring pathWide {Utils::String::stringToWideString(path)};
@ -1945,30 +2066,30 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
}
}
if (exePath != "") {
LOG(LogDebug) << "FileData::findEmulatorPath(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary")
LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command" : "Emulator")
<< " found via systempath rule";
exePath += "\\" + path;
exePath = Utils::FileSystem::getEscapedPath(exePath);
command.replace(startPos, endPos - startPos + 1, exePath);
return exePath;
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
}
#else
exePath = Utils::FileSystem::getPathToBinary(path);
if (exePath != "") {
LOG(LogDebug) << "FileData::findEmulatorPath(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary")
LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command" : "Emulator")
<< " found via systempath rule";
exePath += "/" + path;
command.replace(startPos, endPos - startPos + 1, exePath);
return exePath;
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
}
#endif
}
for (std::string& path : emulatorStaticPaths) {
// If a pipe character is present in the staticpath entry it means we should substitute
// the emulator binary with whatever is defined after the pipe character.
// the emulator with whatever is defined after the pipe character.
std::string replaceCommand;
const size_t pipePos {path.find('|')};
@ -1998,23 +2119,23 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
}
if (Utils::FileSystem::isRegularFile(path) || Utils::FileSystem::isSymlink(path)) {
LOG(LogDebug) << "FileData::findEmulatorPath(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary")
LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command" : "Emulator")
<< " found via staticpath rule";
if (replaceCommand == "") {
exePath = Utils::FileSystem::getEscapedPath(path);
}
else {
LOG(LogDebug) << "FileData::findEmulatorPath(): Replacing emulator binary in "
LOG(LogDebug) << "FileData::findEmulator(): Replacing emulator in "
"staticpath rule with explicitly defined command";
exePath = replaceCommand;
}
command.replace(startPos, endPos - startPos + 1, exePath);
return exePath;
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
}
}
// Method 2, exact emulator binary name:
// Method 2, exact emulator name:
// If %ESPATH% is used, then expand it to the binary directory of ES-DE.
command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath());
@ -2052,7 +2173,7 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
exePath = Utils::String::wideStringToString(pathBuffer.data());
}
#else
#elif !defined(__ANDROID__)
if (Utils::FileSystem::isRegularFile(emuExecutable) ||
Utils::FileSystem::isSymlink(emuExecutable)) {
exePath = Utils::FileSystem::getEscapedPath(emuExecutable);
@ -2065,7 +2186,7 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
}
#endif
return exePath;
return std::make_pair(exePath, FileData::findEmulatorResult::NOT_FOUND);
}
CollectionFileData::CollectionFileData(FileData* file, SystemData* system)

View file

@ -123,8 +123,16 @@ public:
virtual FileData* getSourceFileData() { return this; }
const std::string& getSystemName() const { return mSystemName; }
enum class findEmulatorResult {
FOUND_FILE,
FOUND_ANDROID_PACKAGE,
NOT_FOUND,
NO_RULES
};
void launchGame();
const std::string findEmulatorPath(std::string& command, const bool preCommand);
const std::pair<std::string, FileData::findEmulatorResult> findEmulator(std::string& command,
const bool preCommand);
using ComparisonFunction = bool(const FileData* a, const FileData* b);
struct SortType {

View file

@ -56,6 +56,9 @@ void FindRules::loadFindRules()
#elif defined(__APPLE__)
filePath =
ResourceManager::getInstance().getResourcePath(":/systems/macos/es_find_rules.xml", false);
#elif defined(__ANDROID__)
filePath = ResourceManager::getInstance().getResourcePath(":/systems/android/es_find_rules.xml",
false);
#else
filePath =
ResourceManager::getInstance().getResourcePath(":/systems/unix/es_find_rules.xml", false);
@ -84,7 +87,6 @@ void FindRules::loadFindRules()
#else
const pugi::xml_parse_result& res {doc.load_file(path.c_str())};
#endif
if (!res) {
LOG(LogError) << "Couldn't parse es_find_rules.xml: " << res.description();
continue;
@ -126,6 +128,9 @@ void FindRules::loadFindRules()
#if defined(_WIN64)
if (ruleType != "winregistrypath" && ruleType != "winregistryvalue" &&
ruleType != "systempath" && ruleType != "staticpath") {
#elif defined(__ANDROID__)
if (ruleType != "androidpackage" && ruleType != "systempath" &&
ruleType != "staticpath") {
#else
if (ruleType != "systempath" && ruleType != "staticpath") {
#endif
@ -145,6 +150,9 @@ void FindRules::loadFindRules()
emulatorRules.winRegistryPaths.emplace_back(entryValue);
else if (ruleType == "winregistryvalue")
emulatorRules.winRegistryValues.emplace_back(entryValue);
#elif defined(__ANDROID__)
else if (ruleType == "androidpackage")
emulatorRules.androidPackages.emplace_back(entryValue);
#endif
}
}
@ -154,6 +162,8 @@ void FindRules::loadFindRules()
#if defined(_WIN64)
emulatorRules.winRegistryPaths.clear();
emulatorRules.winRegistryValues.clear();
#elif defined(__ANDROID__)
emulatorRules.androidPackages.clear();
#endif
}
@ -969,6 +979,8 @@ std::vector<std::string> SystemData::getConfigPath()
path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_systems.xml", true);
#elif defined(__APPLE__)
path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_systems.xml", true);
#elif defined(__ANDROID__)
path = ResourceManager::getInstance().getResourcePath(":/systems/android/es_systems.xml", true);
#else
path = ResourceManager::getInstance().getResourcePath(":/systems/unix/es_systems.xml", true);
#endif

View file

@ -44,6 +44,8 @@ private:
#if defined(_WIN64)
std::vector<std::string> winRegistryPaths;
std::vector<std::string> winRegistryValues;
#elif defined(__ANDROID__)
std::vector<std::string> androidPackages;
#endif
std::vector<std::string> systemPaths;
std::vector<std::string> staticPaths;

View file

@ -379,13 +379,60 @@ namespace Utils
// TODO: Wait for interface to close and check actual outcome.
JNIEnv* jniEnv {reinterpret_cast<JNIEnv*>(SDL_AndroidGetJNIEnv())};
jclass jniClass {jniEnv->FindClass("org/esde/esde/esde")};
jmethodID funcID {
jmethodID methodID {
jniEnv->GetStaticMethodID(jniClass, "requestStoragePermissions", "()Z")};
const bool result {
static_cast<bool>(jniEnv->CallStaticBooleanMethod(jniClass, funcID))};
static_cast<bool>(jniEnv->CallStaticBooleanMethod(jniClass, methodID))};
// jniEnv->DeleteLocalRef(jniClass);
return result;
}
bool checkEmulatorInstalled(const std::string& packageName,
const std::string& component)
{
JNIEnv* jniEnv {reinterpret_cast<JNIEnv*>(SDL_AndroidGetJNIEnv())};
jclass jniClass {jniEnv->FindClass("org/esde/esde/esde")};
jmethodID methodID {jniEnv->GetStaticMethodID(
jniClass, "checkEmulatorInstalled", "(Ljava/lang/String;Ljava/lang/String;)Z")};
bool returnValue {static_cast<bool>(jniEnv->CallStaticBooleanMethod(
jniClass, methodID, jniEnv->NewStringUTF(packageName.c_str()),
jniEnv->NewStringUTF(component.c_str())))};
// jniEnv->DeleteLocalRef(jniClass);
return returnValue;
}
int launchGame(const std::string& packageName,
const std::string& component,
std::vector<std::pair<std::string, std::string>>& extras)
{
JNIEnv* jniEnv {reinterpret_cast<JNIEnv*>(SDL_AndroidGetJNIEnv())};
jclass jniClass {jniEnv->FindClass("org/esde/esde/esde")};
jmethodID methodID {jniEnv->GetStaticMethodID(
jniClass, "launchGame",
"(Ljava/lang/String;Ljava/lang/String;Ljava/util/Vector;Ljava/util/Vector;)Z")};
jclass vectorClass {jniEnv->FindClass("java/util/Vector")};
jmethodID vectorMID {jniEnv->GetMethodID(vectorClass, "<init>", "()V")};
jmethodID addMethodID {
jniEnv->GetMethodID(vectorClass, "add", "(Ljava/lang/Object;)Z")};
jobject extrasNames {jniEnv->NewObject(vectorClass, vectorMID)};
jobject extrasValues {jniEnv->NewObject(vectorClass, vectorMID)};
for (auto& extra : extras) {
jniEnv->CallBooleanMethod(extrasNames, addMethodID,
jniEnv->NewStringUTF(extra.first.c_str()));
jniEnv->CallBooleanMethod(extrasValues, addMethodID,
jniEnv->NewStringUTF(extra.second.c_str()));
}
const bool returnValue {static_cast<bool>(jniEnv->CallStaticBooleanMethod(
jniClass, methodID, jniEnv->NewStringUTF(packageName.c_str()),
jniEnv->NewStringUTF(component.c_str()), extrasNames, extrasValues))};
// jniEnv->DeleteLocalRef(vectorClass);
// jniEnv->DeleteLocalRef(jniClass);
if (returnValue)
return -1;
else
return 0;
}
} // namespace Android
#endif
} // namespace Platform

View file

@ -60,7 +60,12 @@ namespace Utils
namespace Android
{
bool requestStoragePermission();
}; // namespace Android
bool checkEmulatorInstalled(const std::string& packageName,
const std::string& component);
int launchGame(const std::string& packageName,
const std::string& component,
std::vector<std::pair<std::string, std::string>>& extras);
} // namespace Android
#endif
static QuitMode sQuitMode = QuitMode::QUIT;