ANDROID: Use SAF if a directory is not writeable
This commit is contained in:
parent
e79e58e077
commit
4ac31d5481
5 changed files with 72 additions and 7 deletions
|
@ -68,7 +68,14 @@ bool POSIXFilesystemNode::isReadable() const {
|
|||
}
|
||||
|
||||
bool POSIXFilesystemNode::isWritable() const {
|
||||
return access(_path.c_str(), W_OK) == 0;
|
||||
bool retVal = access(_path.c_str(), W_OK) == 0;
|
||||
#if defined(ANDROID_PLAIN_PORT)
|
||||
if (!retVal) {
|
||||
// Update return value if going through Android's SAF grants the permission
|
||||
retVal = JNI::isDirectoryWritableWithSAF(_path);
|
||||
}
|
||||
#endif // ANDROID_PLAIN_PORT
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void POSIXFilesystemNode::setFlags() {
|
||||
|
|
|
@ -91,6 +91,7 @@ jmethodID JNI::_MID_deinitSurface = 0;
|
|||
jmethodID JNI::_MID_createDirectoryWithSAF = 0;
|
||||
jmethodID JNI::_MID_createFileWithSAF = 0;
|
||||
jmethodID JNI::_MID_closeFileWithSAF = 0;
|
||||
jmethodID JNI::_MID_isDirectoryWritableWithSAF = 0;
|
||||
|
||||
jmethodID JNI::_MID_EGL10_eglSwapBuffers = 0;
|
||||
|
||||
|
@ -561,6 +562,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
|
|||
FIND_METHOD(, createDirectoryWithSAF, "(Ljava/lang/String;)Z");
|
||||
FIND_METHOD(, createFileWithSAF, "(Ljava/lang/String;)Ljava/lang/String;");
|
||||
FIND_METHOD(, closeFileWithSAF, "(Ljava/lang/String;)V");
|
||||
FIND_METHOD(, isDirectoryWritableWithSAF, "(Ljava/lang/String;)Z");
|
||||
|
||||
_jobj_egl = env->NewGlobalRef(egl);
|
||||
_jobj_egl_display = env->NewGlobalRef(egl_display);
|
||||
|
@ -814,7 +816,6 @@ Common::U32String JNI::createFileWithSAF(const Common::String &filePath) {
|
|||
|
||||
Common::U32String hackyFilenameStr = convertFromJString(env, hackyFilenameJSTR);
|
||||
|
||||
//LOGD("JNI - _MID_createFileWithSAF returned %s", hackyFilenameStr.c_str());
|
||||
env->DeleteLocalRef(hackyFilenameJSTR);
|
||||
|
||||
return hackyFilenameStr;
|
||||
|
@ -836,4 +837,22 @@ void JNI::closeFileWithSAF(const Common::String &hackyFilename) {
|
|||
|
||||
}
|
||||
|
||||
bool JNI::isDirectoryWritableWithSAF(const Common::String &dirPath) {
|
||||
JNIEnv *env = JNI::getEnv();
|
||||
jstring javaDirPath = env->NewStringUTF(dirPath.c_str());
|
||||
|
||||
bool isWritable = env->CallBooleanMethod(_jobj, _MID_isDirectoryWritableWithSAF, javaDirPath);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("JNI - Failed to check if directory is writable SAF enhanced method");
|
||||
|
||||
env->ExceptionDescribe();
|
||||
env->ExceptionClear();
|
||||
isWritable = false;
|
||||
}
|
||||
|
||||
return isWritable;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -87,6 +87,7 @@ public:
|
|||
static bool createDirectoryWithSAF(const Common::String &dirPath);
|
||||
static Common::U32String createFileWithSAF(const Common::String &filePath);
|
||||
static void closeFileWithSAF(const Common::String &hackyFilename);
|
||||
static bool isDirectoryWritableWithSAF(const Common::String &dirPath);
|
||||
|
||||
private:
|
||||
static JavaVM *_vm;
|
||||
|
@ -119,6 +120,7 @@ private:
|
|||
static jmethodID _MID_createDirectoryWithSAF;
|
||||
static jmethodID _MID_createFileWithSAF;
|
||||
static jmethodID _MID_closeFileWithSAF;
|
||||
static jmethodID _MID_isDirectoryWritableWithSAF;
|
||||
|
||||
static jmethodID _MID_EGL10_eglSwapBuffers;
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
|
|||
abstract protected boolean createDirectoryWithSAF(String dirPath);
|
||||
abstract protected String createFileWithSAF(String filePath);
|
||||
abstract protected void closeFileWithSAF(String hackyFilename);
|
||||
abstract protected boolean isDirectoryWritableWithSAF(String dirPath);
|
||||
|
||||
public ScummVM(AssetManager asset_manager, SurfaceHolder holder, final MyScummVMDestroyedCallback scummVMDestroyedCallback) {
|
||||
_asset_manager = asset_manager;
|
||||
|
|
|
@ -417,19 +417,19 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
|||
|
||||
// TODO - "Swipe" behavior does not seem to work currently. Should we support it?
|
||||
public void swipeLeft() {
|
||||
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeLeft");
|
||||
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeLeft");
|
||||
}
|
||||
|
||||
public void swipeRight() {
|
||||
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeRight" );
|
||||
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeRight" );
|
||||
}
|
||||
|
||||
public void swipeDown() {
|
||||
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeDown" );
|
||||
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeDown" );
|
||||
}
|
||||
|
||||
public void swipeUp() {
|
||||
//Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeUp ");
|
||||
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeUp ");
|
||||
}
|
||||
public void onKey(int key, int[] keysAround) {
|
||||
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onKey key: " + key );
|
||||
|
@ -583,7 +583,6 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
private class MyScummVM extends ScummVM {
|
||||
|
||||
public MyScummVM(SurfaceHolder holder, final MyScummVMDestroyedCallback destroyedCallback) {
|
||||
|
@ -793,6 +792,36 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
|||
return retRes[0];
|
||||
}
|
||||
|
||||
|
||||
// This is a simplified version of createDirectoryWithSAF
|
||||
// TODO Maybe we could merge isDirectoryWritableWithSAF() with createDirectoryWithSAF() using an extra argument parameter
|
||||
@Override
|
||||
protected boolean isDirectoryWritableWithSAF(String dirPath) {
|
||||
final boolean[] retRes = {false};
|
||||
|
||||
Log.d(ScummVM.LOG_TAG, "Check if folder writable: " + dirPath);
|
||||
File folderToCheck = new File (dirPath);
|
||||
if (folderToCheck.canWrite()) {
|
||||
Log.d(ScummVM.LOG_TAG, "This path has write permission!" + dirPath);
|
||||
} else {
|
||||
Log.d(ScummVM.LOG_TAG, "Trying to get write access with SAF");
|
||||
if (getStorageAccessFrameworkTreeUri() == null) {
|
||||
requestStorageAccessFramework(dirPath);
|
||||
} else {
|
||||
Log.d(ScummVM.LOG_TAG, "Already requested Storage Access (Storage Access Framework) in the past (share prefs saved)!");
|
||||
}
|
||||
}
|
||||
|
||||
if (canWriteFile(folderToCheck, true)) {
|
||||
Log.d(ScummVM.LOG_TAG, "(post SAF request) Writing is possible for this directory node");
|
||||
retRes[0] = true;
|
||||
} else {
|
||||
Log.d(ScummVM.LOG_TAG, "(post SAF request) Error - writing is still not possible for this directory node");
|
||||
}
|
||||
|
||||
return retRes[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createFileWithSAF(String filePath) {
|
||||
final String[] retResStr = {""};
|
||||
|
@ -2158,6 +2187,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
|||
_scummvm.displayMessageOnOSD(getString(R.string.saf_request_prompt) + dirPathSample);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
// Directory picker
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
|
@ -2298,14 +2328,20 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
|
|||
} catch (Exception ignored) {
|
||||
originalDirectory = true;
|
||||
}
|
||||
|
||||
Uri treeUri;
|
||||
if ((treeUri = getStorageAccessFrameworkTreeUri()) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DocumentFile dof = DocumentFile.fromTreeUri(getApplicationContext(), treeUri);
|
||||
if (originalDirectory) {
|
||||
return dof;
|
||||
}
|
||||
|
||||
// Important note: We cannot assume that anything sent here is a relative path on top of the *ONLY* SAF "root" path
|
||||
// since the the user could select another SD Card (from multiple inserted or replaces the current one and inserts another)
|
||||
// TODO Can we translate our path string "/storage/XXXX-XXXXX/folder/doc.ext' a content URI? or a document URI?
|
||||
String[] parts = relPath.split("\\/");
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
DocumentFile nextDof = dof.findFile(parts[i]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue