[Scummvm-git-logs] scummvm master -> 3c9741a4c3a2ea5d8f6ee2601fe998fe4c029bbf

antoniou79 a.antoniou79 at gmail.com
Fri Jan 31 15:28:32 UTC 2020


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
3c9741a4c3 ANDROID: Early fix for Android 9+ crash and config/save path issues


Commit: 3c9741a4c3a2ea5d8f6ee2601fe998fe4c029bbf
    https://github.com/scummvm/scummvm/commit/3c9741a4c3a2ea5d8f6ee2601fe998fe4c029bbf
Author: Thanasis Antoniou (a.antoniou79 at gmail.com)
Date: 2020-01-31T17:23:15+02:00

Commit Message:
ANDROID: Early fix for Android 9+ crash and config/save path issues

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
    dists/android/res/values/strings.xml


diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 8514d4c..b24f4a4 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -313,8 +313,12 @@ void OSystem_Android::initBackend() {
 	ConfMan.setBool("FM_high_quality", false);
 	ConfMan.setBool("FM_medium_quality", true);
 
-	if (!ConfMan.hasKey("browser_lastpath") || (ConfMan.hasKey("browser_lastpath") && (ConfMan.get("browser_lastpath") == "/storage")))
-		ConfMan.set("browser_lastpath", getenv("SDCARD"));
+
+	if (!ConfMan.hasKey("browser_lastpath")) {
+		// TODO remove the debug message eventually
+		LOGD("Setting Browser Lastpath to root");
+		ConfMan.set("browser_lastpath", "/");
+	}
 
 	if (ConfMan.hasKey("touchpad_mouse_mode"))
 		_touchpad_mode = ConfMan.getBool("touchpad_mouse_mode");
@@ -335,6 +339,9 @@ void OSystem_Android::initBackend() {
 	// screen. Passing the savepath in this way makes it stick
 	// (via ConfMan.registerDefault)
 	_savefileManager = new DefaultSaveFileManager(ConfMan.get("savepath"));
+	// TODO remove the debug message eventually
+	LOGD("Setting DefaultSaveFileManager path to: %s", ConfMan.get("savepath").c_str());
+
 	_mutexManager = new PthreadMutexManager();
 	_timerManager = new DefaultTimerManager();
 
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 20fa482..d434ed8 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -27,6 +27,11 @@ import android.widget.ImageView;
 import android.widget.Toast;
 
 import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
 import java.util.List;
 
 public class ScummVMActivity extends Activity {
@@ -35,6 +40,10 @@ public class ScummVMActivity extends Activity {
 	private static boolean _hoverAvailable;
 
 	private ClipboardManager _clipboard;
+	private File _configScummvmFile;
+	private File _actualScummVMDataDir;
+	private File _defaultScummVMSavesDir;
+
 
 	/**
 	* Id to identify an external storage read request.
@@ -206,39 +215,31 @@ public class ScummVMActivity extends Activity {
 			requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXT_STORAGE);
 		}
 
-		// This is a common enough error that we should warn about it
-		// explicitly.
-		if (!Environment.getExternalStorageDirectory().canRead()) {
-			new AlertDialog.Builder(this)
-				.setTitle(R.string.no_sdcard_title)
-				.setIcon(android.R.drawable.ic_dialog_alert)
-				.setMessage(R.string.no_sdcard)
-				.setNegativeButton(R.string.quit,
-									new DialogInterface.OnClickListener() {
-										public void onClick(DialogInterface dialog,
-															int which) {
-											finish();
-										}
-									})
-				.show();
-
-			return;
-		}
+		// REMOVED: Dialogue prompt with only option to Quit the app if !Environment.getExternalStorageDirectory().canRead()
 
 		SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
 
 		main_surface.requestFocus();
 
-		getFilesDir().mkdirs();
-
-		// Store savegames on external storage if we can, which means they're
-		// world-readable and don't get deleted on uninstall.
-		String savePath = Environment.getExternalStorageDirectory() + "/ScummVM/Saves/";
-		File saveDir = new File(savePath);
-		saveDir.mkdirs();
-		if (!saveDir.isDirectory()) {
-			// If it doesn't work, resort to the internal app path.
-			savePath = getDir("saves", Context.MODE_PRIVATE).getPath();
+		// REMOVED: Since getFilesDir() is guaranteed to exist, getFilesDir().mkdirs() might be related to crashes in Android version 9+ (Pie or above, API 28+)!
+
+		// REMOVED: Setting savePath to Environment.getExternalStorageDirectory() + "/ScummVM/Saves/" 
+		//                            so that it will be in persistent external storage and not deleted on uninstall
+		//                            This has the issue for external storage being unavailable on some devices
+		//                            Is this persistence really important considering that Android does not really support it anymore
+		//                               Exceptions are:
+		//                                 - shareable media files (images, audio, video)
+		//                                 - files stored with Storage Access Framework (SAF) which requires user interaction with FilePicker)
+		//          Original fallback was getDir()
+		//                            so app's internal space, which would be deleted on uninstall) set as WORLD_READABLE which is no longer supported in newer versions of Android API
+		//                            In newer APIs we can set that path as Context.MODE_PRIVATE which is the default - but will make the files inaccessible to other apps
+
+		//
+		// seekAndInitScummvmConfiguration() returns false if something went wrong when
+		// initializing configuration (or finding and using an old ini file) for ScummVM
+		if (!seekAndInitScummvmConfiguration()) {
+			Log.e(ScummVM.LOG_TAG, "Error while trying to find and/or initialize scummvm configuration file!");
+			// TODO error prompt (popup to user)
 		}
 
 		_clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
@@ -247,10 +248,10 @@ public class ScummVMActivity extends Activity {
 		_scummvm = new MyScummVM(main_surface.getHolder());
 
 		_scummvm.setArgs(new String[] {
-			"ScummVM",
-			"--config=" + getFileStreamPath("scummvmrc").getPath(),
-			"--path=" + Environment.getExternalStorageDirectory().getPath(),
-			"--savepath=" + savePath
+		    "ScummVM",
+		    "--config=" + _configScummvmFile.getPath(),
+		    "--path=" + _actualScummVMDataDir.getPath(),
+		    "--savepath=" + _defaultScummVMSavesDir.getPath()
 		});
 
 		Log.d(ScummVM.LOG_TAG, "Hover available: " + _hoverAvailable);
@@ -419,4 +420,139 @@ public class ScummVMActivity extends Activity {
 			sendBroadcast(intent);
 		}
 	}
+
+	// Auxilliary function to overwrite a file (used for overwriting the scummvm.ini file with an existing other one)
+	private static void copyFileUsingStream(File source, File dest) throws IOException {
+		InputStream is = null;
+		OutputStream os = null;
+		try {
+			is = new FileInputStream(source);
+			os = new FileOutputStream(dest);
+			byte[] buffer = new byte[1024];
+			int length;
+			while ((length = is.read(buffer)) > 0) {
+				os.write(buffer, 0, length);
+			}
+		} finally {
+			is.close();
+			os.close();
+		}
+	}
+
+	private boolean seekAndInitScummvmConfiguration() {
+		boolean retVal = false;
+
+		_actualScummVMDataDir = getExternalFilesDir(null);
+		if (_actualScummVMDataDir == null || !_actualScummVMDataDir.canRead()) {
+			new AlertDialog.Builder(this)
+				.setTitle(R.string.no_external_files_dir_access_title)
+				.setIcon(android.R.drawable.ic_dialog_alert)
+				.setMessage(R.string.no_external_files_dir_access)
+				.setNegativeButton(R.string.quit,
+							new DialogInterface.OnClickListener() {
+								public void onClick(DialogInterface dialog, int which) {
+									finish();
+								}
+							})
+				.show();
+			retVal = false;
+			return retVal;
+		}
+
+		Log.d(ScummVM.LOG_TAG, "Base ScummVM data folder is: " + _actualScummVMDataDir.getPath());
+
+		File[] extfiles = _actualScummVMDataDir.listFiles();
+		Log.d(ScummVM.LOG_TAG, "Size: "+ extfiles.length);
+		for (int i = 0; i < extfiles.length; i++) {
+			Log.d(ScummVM.LOG_TAG, "FileName:" + extfiles[i].getName());
+		}
+
+		File externalScummVMConfigDir = new File(_actualScummVMDataDir, ".config/scummvm");
+		if (externalScummVMConfigDir.mkdirs()) {
+			Log.d(ScummVM.LOG_TAG, "Created ScummVM Config path: " + externalScummVMConfigDir.getPath());
+		} else if (externalScummVMConfigDir.isDirectory()) {
+			Log.d(ScummVM.LOG_TAG, "ScummVM Config path already exists: " + externalScummVMConfigDir.getPath());
+		} else {
+			Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM Config path: " + externalScummVMConfigDir.getPath());
+			new AlertDialog.Builder(this)
+				.setTitle(R.string.no_config_file_title)
+				.setIcon(android.R.drawable.ic_dialog_alert)
+				.setMessage(R.string.no_config_file)
+				.setNegativeButton(R.string.quit,
+							new DialogInterface.OnClickListener() {
+								public void onClick(DialogInterface dialog, int which) {
+									finish();
+								}
+							})
+				.show();
+		}
+
+		_configScummvmFile = new File(_actualScummVMDataDir, "scummvm.ini");
+		try {
+			if (!_configScummvmFile.createNewFile()) {
+				Log.d(ScummVM.LOG_TAG, "ScummVM Config file already exists!");
+				Log.d(ScummVM.LOG_TAG, "Existing Scummvm INI: " + _configScummvmFile.getPath());
+			} else {
+				Log.d(ScummVM.LOG_TAG, "ScummVM Config file was created!");
+				Log.d(ScummVM.LOG_TAG, "New Scummvm INI: " + _configScummvmFile.getPath());
+				// if there was an old scummvmrc file (old config file), then copy that over the empty new scummvm.ini
+				File oldScummVMconfig = getFileStreamPath("scummvmrc");
+				if (!oldScummVMconfig.exists()) {
+					Log.d(ScummVM.LOG_TAG, "Old config Scummvm file was not found!");
+				} else {
+					Log.d(ScummVM.LOG_TAG, "Old config Scummvm file was found!");
+					copyFileUsingStream(oldScummVMconfig, _configScummvmFile);
+					Log.d(ScummVM.LOG_TAG, "Old config Scummvm file overwrites the new (empty) scummvm.ini");
+				}
+			}
+		} catch(Exception e) {
+			e.printStackTrace();
+			new AlertDialog.Builder(this)
+				.setTitle(R.string.no_config_file_title)
+				.setIcon(android.R.drawable.ic_dialog_alert)
+				.setMessage(R.string.no_config_file)
+				.setNegativeButton(R.string.quit,
+							new DialogInterface.OnClickListener() {
+								public void onClick(DialogInterface dialog, int which) {
+									finish();
+								}
+							})
+				.show();
+		}
+
+
+		// Set global savepath
+		// TODO what if the old save-game path is no longer accessible (due to missing SD card, or newer Android API/OS version more strict restrictions)
+		// TODO changing the save path to this, app specific location we should consider:
+		//      - moving or copying old save files from old location (if accessible)
+		//      - allowing the user to set a user-defined location via Storage Access Framework, that would override this location!
+		// TODO This would override/ overwrite(?) actual old save-game path stored in the config file!
+		//
+		// By default shoose to store savegames on app's external storage, which means they're accessible by other apps BUT will get deleted on uninstall!
+		//
+		_defaultScummVMSavesDir = new File(_actualScummVMDataDir, "saves");
+		// TODO what about old save paths from plain android port? do we favor them?
+		if (_defaultScummVMSavesDir.mkdirs()) {
+			Log.d(ScummVM.LOG_TAG, "Created ScummVM saves path: " + _defaultScummVMSavesDir.getPath());
+		} else if (_defaultScummVMSavesDir.isDirectory()) {
+			Log.d(ScummVM.LOG_TAG, "ScummVM saves path already exists: " + _defaultScummVMSavesDir.getPath());
+		} else {
+			Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM saves path: " + _defaultScummVMSavesDir.getPath());
+			new AlertDialog.Builder(this)
+				.setTitle(R.string.no_config_file_title)
+				.setIcon(android.R.drawable.ic_dialog_alert)
+				.setMessage(R.string.no_config_file)
+				.setNegativeButton(R.string.quit,
+							new DialogInterface.OnClickListener() {
+								public void onClick(DialogInterface dialog, int which) {
+									finish();
+								}
+							})
+				.show();
+		}
+
+		retVal = true;
+		return retVal;
+	}
+
 }
diff --git a/dists/android/res/values/strings.xml b/dists/android/res/values/strings.xml
index e06509d..830a30f 100644
--- a/dists/android/res/values/strings.xml
+++ b/dists/android/res/values/strings.xml
@@ -14,6 +14,14 @@
   <string name="no_sdcard">Unable to read your SD card.  This usually
   means you still have it mounted on your PC.  Unmount, reinsert,
   whatever and then try again.</string>
+  <string name="no_external_files_dir_access_title">External storage error</string>
+  <string name="no_external_files_dir_access">Unable to access external storage
+  to retrieve ScummVM config info! Please grant storage access permissions to
+  the ScummVM app, in order to function properly!</string>
+  <string name="no_config_file_title">Config File Error</string>
+  <string name="no_config_file">Unable to read ScummVM config file or create a new one!</string>
+  <string name="no_save_path_title">Save Path Error</string>
+  <string name="no_save_path_configured">Unable to create or access default save path!</string>
   <string name="no_plugins_title">No plugins found</string>
   <string name="no_plugins_found">ScummVM requires at least one <i>game
   engine</i> to be useful.  Engines are available as separate plugin




More information about the Scummvm-git-logs mailing list