mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-11 15:13:37 +02:00
Merge pull request #14813 from hrydgard/scoped-storage-shortcut-fix
Various Android shortcut fixes
This commit is contained in:
@@ -98,7 +98,7 @@ static void WorkerThreadFunc(GlobalThreadContext *global, ThreadContext *thread)
|
||||
}
|
||||
|
||||
void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) {
|
||||
if (!global_->threads_.empty()) {
|
||||
if (IsInitialized()) {
|
||||
Teardown();
|
||||
}
|
||||
|
||||
@@ -118,6 +118,8 @@ void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) {
|
||||
}
|
||||
|
||||
void ThreadManager::EnqueueTask(Task *task, TaskType taskType) {
|
||||
_assert_msg_(IsInitialized(), "ThreadManager not initialized");
|
||||
|
||||
int maxThread;
|
||||
int threadOffset = 0;
|
||||
if (taskType == TaskType::CPU_COMPUTE) {
|
||||
@@ -158,7 +160,7 @@ void ThreadManager::EnqueueTask(Task *task, TaskType taskType) {
|
||||
}
|
||||
|
||||
void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task, TaskType taskType) {
|
||||
_assert_(threadNum >= 0 && threadNum < (int)global_->threads_.size());
|
||||
_assert_msg_(threadNum >= 0 && threadNum < (int)global_->threads_.size(), "Bad threadnum or not initialized");
|
||||
ThreadContext *thread = global_->threads_[threadNum];
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(thread->mutex);
|
||||
@@ -172,5 +174,9 @@ int ThreadManager::GetNumLooperThreads() const {
|
||||
}
|
||||
|
||||
void ThreadManager::TryCancelTask(uint64_t taskID) {
|
||||
// Do nothing
|
||||
// Do nothing for now, just let it finish.
|
||||
}
|
||||
|
||||
bool ThreadManager::IsInitialized() const {
|
||||
return !global_->threads_.empty();
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ public:
|
||||
void EnqueueTaskOnThread(int threadNum, Task *task, TaskType taskType);
|
||||
void Teardown();
|
||||
|
||||
bool IsInitialized() const;
|
||||
|
||||
// Currently does nothing. It will always be best-effort - maybe it cancels,
|
||||
// maybe it doesn't. Note that the id is the id() returned by the task. You need to make that
|
||||
// something meaningful yourself.
|
||||
@@ -58,7 +60,8 @@ public:
|
||||
int GetNumLooperThreads() const;
|
||||
|
||||
private:
|
||||
GlobalThreadContext *global_ = nullptr;
|
||||
// This is always pointing to a context, initialized in the constructor.
|
||||
GlobalThreadContext *global_;
|
||||
|
||||
int numThreads_ = 0;
|
||||
int numComputeThreads_ = 0;
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
|
||||
}
|
||||
|
||||
if (!fileLoader->Exists()) {
|
||||
*errorString = "IdentifyFile: File doesn't exist" + fileLoader->GetPath().ToString();
|
||||
*errorString = "IdentifyFile: File doesn't exist: " + fileLoader->GetPath().ToString();
|
||||
return IdentifiedFileType::ERROR_IDENTIFYING;
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -46,6 +46,7 @@
|
||||
|
||||
#include "Common/Net/HTTPClient.h"
|
||||
#include "Common/Net/Resolve.h"
|
||||
#include "Common/Net/URL.h"
|
||||
#include "Common/Render/TextureAtlas.h"
|
||||
#include "Common/Render/Text/draw_text.h"
|
||||
#include "Common/GPU/OpenGL/GLFeatures.h"
|
||||
@@ -683,7 +684,14 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
}
|
||||
}
|
||||
if (okToLoad) {
|
||||
boot_filename = Path(std::string(argv[i]));
|
||||
std::string str = std::string(argv[i]);
|
||||
// Handle file:/// URIs, since you get those when creating shortcuts on some Android systems.
|
||||
if (startsWith(str, "file:///")) {
|
||||
str = UriDecode(str.substr(7));
|
||||
INFO_LOG(IO, "Decoding '%s' to '%s'", argv[i], str.c_str());
|
||||
}
|
||||
|
||||
boot_filename = Path(str);
|
||||
skipLogo = true;
|
||||
}
|
||||
if (okToLoad && okToCheck) {
|
||||
|
||||
@@ -1441,15 +1441,30 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: This is defunct and not working, due to how the Android storage functions currently require
|
||||
// a PpssppActivity specifically and we don't have one here.
|
||||
extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv *env, jclass, jstring jpath) {
|
||||
bool teardownThreadManager = false;
|
||||
if (!g_threadManager.IsInitialized()) {
|
||||
INFO_LOG(SYSTEM, "No thread manager - initializing one");
|
||||
// Need a thread manager.
|
||||
teardownThreadManager = true;
|
||||
g_threadManager.Init(1, 1);
|
||||
}
|
||||
|
||||
Path path = Path(GetJavaString(env, jpath));
|
||||
|
||||
INFO_LOG(SYSTEM, "queryGameName(%s)", path.c_str());
|
||||
|
||||
std::string result = "";
|
||||
|
||||
GameInfoCache *cache = new GameInfoCache();
|
||||
std::shared_ptr<GameInfo> info = cache->GetInfo(nullptr, path, 0);
|
||||
// Wait until it's done: this is synchronous, unfortunately.
|
||||
if (info) {
|
||||
INFO_LOG(SYSTEM, "GetInfo successful, waiting");
|
||||
cache->WaitUntilDone(info);
|
||||
INFO_LOG(SYSTEM, "Done waiting");
|
||||
if (info->fileType != IdentifiedFileType::UNKNOWN) {
|
||||
result = info->GetTitle();
|
||||
|
||||
@@ -1458,9 +1473,19 @@ extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv
|
||||
if (result.length() > strlen("The ") && startsWithNoCase(result, "The ")) {
|
||||
result = result.substr(strlen("The "));
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "queryGameName: Got '%s'", result.c_str());
|
||||
} else {
|
||||
INFO_LOG(SYSTEM, "queryGameName: Filetype unknown");
|
||||
}
|
||||
} else {
|
||||
INFO_LOG(SYSTEM, "No info from cache");
|
||||
}
|
||||
delete cache;
|
||||
|
||||
if (teardownThreadManager) {
|
||||
g_threadManager.Teardown();
|
||||
}
|
||||
|
||||
return env->NewStringUTF(result.c_str());
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class PpssppActivity extends NativeActivity {
|
||||
// String action = intent.getAction();
|
||||
Uri data = intent.getData();
|
||||
if (data != null) {
|
||||
String path = intent.getData().getPath();
|
||||
String path = data.toString();
|
||||
Log.i(TAG, "Found Shortcut Parameter in data: " + path);
|
||||
super.setShortcutParam("\"" + path.replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
|
||||
// Toast.makeText(getApplicationContext(), path, Toast.LENGTH_SHORT).show();
|
||||
|
||||
@@ -5,11 +5,13 @@ import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
import android.content.Intent.ShortcutIconResource;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* This class will respond to android.intent.action.CREATE_SHORTCUT intent from launcher homescreen.
|
||||
@@ -18,35 +20,114 @@ import java.io.File;
|
||||
public class ShortcutActivity extends Activity {
|
||||
private static final String TAG = "PPSSPP";
|
||||
|
||||
private boolean scoped = false;
|
||||
private static final int RESULT_OPEN_DOCUMENT = 2;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Show file selector dialog here.
|
||||
SimpleFileChooser fileDialog = new SimpleFileChooser(this, Environment.getExternalStorageDirectory(), onFileSelectedListener);
|
||||
fileDialog.showDialog();
|
||||
// Show file selector dialog here. If Android version is more than or equal to 11,
|
||||
// use the native document file browser instead of our SimpleFileChooser.
|
||||
scoped = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
|
||||
|
||||
if (scoped) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
||||
// Possible alternative approach:
|
||||
// String[] mimeTypes = {"application/octet-stream", "/x-iso9660-image"};
|
||||
// intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
|
||||
startActivityForResult(intent, RESULT_OPEN_DOCUMENT);
|
||||
// intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
|
||||
Log.i(TAG, "Starting open document activity");
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.toString());
|
||||
}
|
||||
} else {
|
||||
SimpleFileChooser fileDialog = new SimpleFileChooser(this, Environment.getExternalStorageDirectory(), onFileSelectedListener);
|
||||
fileDialog.showDialog();
|
||||
}
|
||||
}
|
||||
|
||||
// Respond to native file dialog.
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == RESULT_OPEN_DOCUMENT && data != null) {
|
||||
Uri selectedFile = data.getData();
|
||||
if (selectedFile != null) {
|
||||
// Grab permanent permission so we can show it in recents list etc.
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
Log.i(TAG, "Taking URI permission");
|
||||
getContentResolver().takePersistableUriPermission(selectedFile, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
Log.i(TAG, "Browse file finished:" + selectedFile.toString());
|
||||
respondToShortcutRequest(selectedFile); // finishes.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We're done, no matter how it went.
|
||||
finish();
|
||||
}
|
||||
|
||||
public static native String queryGameName(String path);
|
||||
|
||||
// Create shortcut as response for ACTION_CREATE_SHORTCUT intent.
|
||||
private void respondToShortcutRequest(String path) {
|
||||
private void respondToShortcutRequest(Uri uri) {
|
||||
// This is Intent that will be sent when user execute our shortcut on
|
||||
// homescreen. Set our app as target Context. Set Main activity as
|
||||
// target class. Add any parameter as data.
|
||||
Intent shortcutIntent = new Intent(this, PpssppActivity.class);
|
||||
Uri uri = Uri.fromFile(new File(path));
|
||||
Intent shortcutIntent = new Intent(getApplicationContext(), PpssppActivity.class);
|
||||
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Log.i(TAG, "Shortcut URI: " + uri.toString());
|
||||
shortcutIntent.setData(uri);
|
||||
|
||||
String path = uri.toString();
|
||||
shortcutIntent.putExtra(PpssppActivity.SHORTCUT_EXTRA_KEY, path);
|
||||
|
||||
// We can't call C++ functions here that use storage APIs since there's no
|
||||
// NativeActivity and all the AndroidStorage methods are methods on that.
|
||||
// Should probably change that. In the meantime, let's just process the URI to make
|
||||
// up a name.
|
||||
|
||||
String name = "PPSSPP Game";
|
||||
String pathStr = "PPSSPP Game";
|
||||
if (path.startsWith("content://")) {
|
||||
String [] segments = path.split("/");
|
||||
try {
|
||||
pathStr = java.net.URLDecoder.decode(segments[segments.length - 1], StandardCharsets.UTF_8.name());
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "Exception getting name: " + e);
|
||||
}
|
||||
} else if (path.startsWith("file:///")) {
|
||||
try {
|
||||
pathStr = java.net.URLDecoder.decode(path.substring(7), StandardCharsets.UTF_8.name());
|
||||
} catch (Exception e) {
|
||||
Log.i(TAG, "Exception getting name: " + e);
|
||||
}
|
||||
} else {
|
||||
pathStr = path;
|
||||
}
|
||||
|
||||
String[] pathSegments = pathStr.split("/");
|
||||
name = pathSegments[pathSegments.length - 1];
|
||||
|
||||
/*
|
||||
// No longer working for various reasons.
|
||||
|
||||
PpssppActivity.CheckABIAndLoadLibrary();
|
||||
String name = queryGameName(path);
|
||||
if (name.equals("")) {
|
||||
Log.i(TAG, "Failed to retrieve game name - ignoring.");
|
||||
showBadGameMessage();
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
Log.i(TAG, "Game name: " + name + " : Creating shortcut to " + uri.toString());
|
||||
|
||||
// This is Intent that will be returned by this method, as response to
|
||||
// ACTION_CREATE_SHORTCUT. Wrap shortcut intent inside this intent.
|
||||
@@ -80,8 +161,6 @@ public class ShortcutActivity extends Activity {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
// Event when a file is selected on file dialog.
|
||||
@@ -89,7 +168,8 @@ public class ShortcutActivity extends Activity {
|
||||
@Override
|
||||
public void onFileSelected(File file) {
|
||||
// create shortcut using file path
|
||||
respondToShortcutRequest(file.getAbsolutePath());
|
||||
Uri uri = Uri.fromFile(new File(file.getAbsolutePath()));
|
||||
respondToShortcutRequest(uri);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user