[Scummvm-git-logs] scummvm branch-2-2 -> 9d18d03dce0f52abb67ddf4f982378a69caf9053
antoniou79
a.antoniou79 at gmail.com
Thu Sep 24 11:52:17 UTC 2020
This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
b4081e12b0 ANDROID: get version info (wip) and use androidx for annotations
d268cf28b9 ANDROID: Use custom handler for long key press detection
7c4f9df1a5 ANDROID: Upgrade to 2.3 version re-using any old configuration file
7fe7f0c226 ANDROID: Revert chnage for long press AC_BACK handler
3edb4e3e58 ANDROID: Copy asset files in internal app folder
aeeffa1e48 ANDROID: Remove unnecessary check for isFile in a sideUpgrade
495420a027 ANDROID: Add internal app path to SearchSet
d95066e04d ANDROID: Migrate old save files
b15b394f0c ANDROID: Comment out the logfile code
7a6776f121 ANDROID: Set new version code(s) for 2.3.0
9d18d03dce ANDROID: Account for possible v2.2.1 in build.gradle
Commit: b4081e12b0047b512acf9c4b377bb9665177d236
https://github.com/scummvm/scummvm/commit/b4081e12b0047b512acf9c4b377bb9665177d236
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:08+03:00
Commit Message:
ANDROID: get version info (wip) and use androidx for annotations
Also androidx is replacing the Android Support library so it's best to use this one
According to https://developer.android.com/jetpack/androidx
AndroidX is a major improvement to the original Android Support Library, which is no longer maintained. androidx packages fully replace the Support Library by providing feature parity and new libraries.
AndroidX replaces the original support library APIs with packages in the androidx namespace. Only the package and Maven artifact names changed; class, method, and field names did not change.
Changed paths:
backends/platform/android/android.mk
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
dists/android/build.gradle
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index d4b48b8357..b558bef675 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -23,6 +23,8 @@ $(PATH_BUILD_GRADLE): $(GRADLE_FILES) | $(PATH_BUILD)
$(INSTALL) -c -m 644 $(PATH_DIST)/build.gradle $(PATH_BUILD)
$(ECHO) "srcdir=$(realpath $(srcdir))\n" > $(PATH_BUILD)/gradle.properties
$(ECHO) "org.gradle.jvmargs=-Xmx4096m\n" >> $(PATH_BUILD)/gradle.properties
+ $(ECHO) "android.useAndroidX=true\n" >> $(PATH_BUILD)/gradle.properties
+ $(ECHO) "android.enableJetifier=true\n" >> $(PATH_BUILD)/gradle.properties
$(ECHO) "sdk.dir=$(realpath $(ANDROID_SDK_ROOT))\n" > $(PATH_BUILD)/local.properties
$(ECHO) "ndk.dir=$(realpath $(ANDROID_NDK_ROOT))\n" >> $(PATH_BUILD)/local.properties
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 1a1c79c6af..31a9ee8dab 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -1,43 +1,55 @@
package org.scummvm.scummvm;
import android.Manifest;
-import android.content.pm.PackageManager;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.media.AudioManager;
import android.net.Uri;
-import android.net.wifi.WifiManager;
import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
import android.text.ClipboardManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.PointerIcon;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
-import android.view.SurfaceView;
-import android.view.SurfaceHolder;
-import android.view.MotionEvent;
-import android.view.PointerIcon;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.Toast;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import java.io.BufferedReader;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.IOException;
+import java.io.Reader;
import java.io.UnsupportedEncodingException;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+
+//import android.os.Environment;
+//import java.util.List;
public class ScummVMActivity extends Activity implements OnKeyboardVisibilityListener {
@@ -182,7 +194,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXT_STORAGE);
} else {
- return _externalStorage.getAllStorageLocations().toArray(new String[0]);
+ return ExternalStorage.getAllStorageLocations().toArray(new String[0]);
}
return new String[0]; // an array of zero length
}
@@ -193,8 +205,8 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private ScummVMEvents _events;
private MouseHelper _mouseHelper;
private Thread _scummvm_thread;
- private ExternalStorage _externalStorage;
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -214,7 +226,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// REMOVED: Dialogue prompt with only option to Quit the app if !Environment.getExternalStorageDirectory().canRead()
- SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
+ SurfaceView main_surface = findViewById(R.id.main_surface);
main_surface.requestFocus();
@@ -224,16 +236,16 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// 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:
+ // Exceptions (storage locations that are persisted or methods to access files across apps) 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
+ // so app's internal space (which would be deleted on uninstall) was 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 this makes 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
+ // seekAndInitScummvmConfiguration() returns false if something went wrong
+ // when initializing configuration (or when seeking and trying to use an existing 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)
@@ -267,7 +279,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
// On screen button listener
- ((ImageView)findViewById(R.id.show_keyboard)).setOnClickListener(keyboardBtnOnClickListener);
+ findViewById(R.id.show_keyboard).setOnClickListener(keyboardBtnOnClickListener);
// Keyboard visibility listener
setKeyboardVisibilityListener(this);
@@ -337,22 +349,18 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
@Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
- switch (requestCode) {
- case MY_PERMISSIONS_REQUEST_READ_EXT_STORAGE:
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ if (requestCode == MY_PERMISSIONS_REQUEST_READ_EXT_STORAGE) {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
- && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted
Log.i(ScummVM.LOG_TAG, "Read External Storage permission was granted at Runtime");
} else {
// permission denied! We won't be able to make use of functionality depending on this permission.
Toast.makeText(this, "Until permission is granted, some storage locations may be inaccessible!", Toast.LENGTH_SHORT)
- .show();
+ .show();
}
- break;
- default:
- break;
}
}
@@ -386,9 +394,10 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// TODO setSystemUiVisibility is introduced in API 11 and deprecated in API 30 - When we move to API 30 we will have to replace this code
// https://developer.android.com/training/system-ui/immersive.html#java
//
- // The code sample in the url below contains code to switch between immersive and default mode
+ // The code sample in the url below contains code to switch between immersive and default mode
// https://github.com/android/user-interface-samples/tree/master/AdvancedImmersiveMode
- // We could do something similar by making it a Global UI option.
+ // We could do something similar by making it a Global UI option.
+ @TargetApi(Build.VERSION_CODES.KITKAT)
private void hideSystemUI() {
// Enables regular immersive mode.
// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
@@ -406,20 +415,22 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
| View.SYSTEM_UI_FLAG_FULLSCREEN);
}
- // Shows the system bars by removing all the flags
- // except for the ones that make the content appear under the system bars.
- private void showSystemUI() {
- View decorView = getWindow().getDecorView();
- decorView.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
- }
+// // Shows the system bars by removing all the flags
+// // except for the ones that make the content appear under the system bars.
+// @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+// private void showSystemUI() {
+// View decorView = getWindow().getDecorView();
+// decorView.setSystemUiVisibility(
+// View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+// | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+// | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
+// }
// Show or hide the Android keyboard.
// Called by the override of showVirtualKeyboard()
+ @TargetApi(Build.VERSION_CODES.CUPCAKE)
private void showKeyboard(boolean show) {
- SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
+ SurfaceView main_surface = findViewById(R.id.main_surface);
InputMethodManager imm = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
@@ -432,8 +443,9 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// Toggle showing or hiding the virtual keyboard.
// Called by keyboardBtnOnClickListener()
+ @TargetApi(Build.VERSION_CODES.CUPCAKE)
private void toggleKeyboard() {
- SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
+ SurfaceView main_surface = findViewById(R.id.main_surface);
InputMethodManager imm = (InputMethodManager)
getSystemService(INPUT_METHOD_SERVICE);
@@ -445,7 +457,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// Show or hide the semi-transparent keyboard btn (which is used to explicitly bring up the android keyboard).
// Called by the override of showKeyboardControl()
private void showKeyboardView(boolean show) {
- ImageView keyboardBtn = (ImageView)findViewById(R.id.show_keyboard);
+ ImageView keyboardBtn = findViewById(R.id.show_keyboard);
if (show) {
keyboardBtn.setVisibility(View.VISIBLE);
@@ -456,7 +468,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private void showMouseCursor(boolean show) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
+ SurfaceView main_surface = findViewById(R.id.main_surface);
int type = show ? PointerIcon.TYPE_DEFAULT : PointerIcon.TYPE_NULL;
main_surface.setPointerIcon(PointerIcon.getSystemIcon(this, type));
} else {
@@ -482,6 +494,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private final int EstimatedKeyboardDP = defaultKeyboardHeightDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);
private final Rect rect = new Rect();
+ @TargetApi(Build.VERSION_CODES.CUPCAKE)
@Override
public void onGlobalLayout() {
int estimatedKeyboardHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, parentView.getResources().getDisplayMetrics());
@@ -506,25 +519,58 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
// Auxiliary function to overwrite a file (used for overwriting the scummvm.ini file with an existing other one)
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
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);
+ try (InputStream is = new FileInputStream(source); OutputStream 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();
}
}
+ /**
+ * Auxiliary function to read our ini configuration file
+ * Code is from https://stackoverflow.com/a/41084504
+ * returns The sections of the ini file as a Map of the header Strings to a Properties object (the key=value list of each section)
+ */
+ @TargetApi(Build.VERSION_CODES.GINGERBREAD)
+ private static Map<String, Properties> parseINI(Reader reader) throws IOException {
+ final HashMap<String, Properties> result = new HashMap<>();
+ new Properties() {
+
+ private Properties section;
+
+ @Override
+ public Object put(Object key, Object value) {
+ String header = (key + " " + value).trim();
+ if (header.startsWith("[") && header.endsWith("]"))
+ return result.put(header.substring(1, header.length() - 1),
+ section = new Properties());
+ else
+ return section.put(key, value);
+ }
+
+ }.load(reader);
+ return result;
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+ private static String getVersionInfoFromScummvmConfiguration(String fullIniFilePath) {
+ try (BufferedReader bufferedReader = new BufferedReader(new FileReader(fullIniFilePath))) {
+ Map<String, Properties> parsedIniMap = parseINI(bufferedReader);
+ if (!parsedIniMap.isEmpty() && parsedIniMap.containsKey("scummvm")) {
+ return Objects.requireNonNull(parsedIniMap.get("scummvm")).getProperty("versioninfo", "");
+ }
+ } catch (IOException ignored) {
+ } catch (NullPointerException ignored) {
+ }
+ return "";
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
private boolean seekAndInitScummvmConfiguration() {
- boolean retVal = false;
_actualScummVMDataDir = getExternalFilesDir(null);
if (_actualScummVMDataDir == null || !_actualScummVMDataDir.canRead()) {
@@ -533,26 +579,27 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
.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();
- }
- })
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ })
.show();
- retVal = false;
- return retVal;
+ return false;
}
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());
+ if (extfiles != null) {
+ Log.d(ScummVM.LOG_TAG, "Size: "+ extfiles.length);
+ for (File extfile : extfiles) {
+ Log.d(ScummVM.LOG_TAG, "FileName:" + extfile.getName());
+ }
}
File externalScummVMConfigDir = new File(_actualScummVMDataDir, ".config/scummvm");
- if (externalScummVMConfigDir.mkdirs()) {
+ if (!externalScummVMConfigDir.exists() && 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());
@@ -563,30 +610,43 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
.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();
- }
- })
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ })
.show();
}
+ // TODO search in other known places for scummvm.ini too
_configScummvmFile = new File(_actualScummVMDataDir, "scummvm.ini");
try {
- if (!_configScummvmFile.createNewFile()) {
+ if (_configScummvmFile.exists() || !_configScummvmFile.createNewFile()) {
Log.d(ScummVM.LOG_TAG, "ScummVM Config file already exists!");
- Log.d(ScummVM.LOG_TAG, "Existing Scummvm INI: " + _configScummvmFile.getPath());
+ Log.d(ScummVM.LOG_TAG, "Existing ScummVM INI: " + _configScummvmFile.getPath());
+ String existingVersionInfo = getVersionInfoFromScummvmConfiguration(_configScummvmFile.getPath());
+ if (!"".equals(existingVersionInfo.trim())) {
+ Log.d(ScummVM.LOG_TAG, "Existing ScummVM Version: " + existingVersionInfo.trim());
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Could not find info on existing ScummVM version. Old or corrupt file?");
+ }
} else {
Log.d(ScummVM.LOG_TAG, "ScummVM Config file was created!");
- Log.d(ScummVM.LOG_TAG, "New Scummvm INI: " + _configScummvmFile.getPath());
+ 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!");
+ Log.d(ScummVM.LOG_TAG, "Old config (scummvmrc) ScummVM file was not found!");
} else {
- Log.d(ScummVM.LOG_TAG, "Old config Scummvm file was found!");
+ Log.d(ScummVM.LOG_TAG, "Old config (scummvmrc) ScummVM file was found!");
+ String existingVersionInfo = getVersionInfoFromScummvmConfiguration(_configScummvmFile.getPath());
+ if (!"".equals(existingVersionInfo.trim())) {
+ Log.d(ScummVM.LOG_TAG, "Existing ScummVM Version: " + existingVersionInfo.trim());
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Could not find info on existing ScummVM version. Old or corrupt file?");
+ }
copyFileUsingStream(oldScummVMconfig, _configScummvmFile);
- Log.d(ScummVM.LOG_TAG, "Old config Scummvm file overwrites the new (empty) scummvm.ini");
+ Log.d(ScummVM.LOG_TAG, "Old config (scummvmrc) ScummVM file was renamed and overwrote the new (empty) scummvm.ini");
}
}
} catch(Exception e) {
@@ -596,11 +656,11 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
.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();
- }
- })
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ })
.show();
}
@@ -612,11 +672,12 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// - 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!
+ // By default choose to store savegames on app's external storage, which means they're ACCESSIBLE BY OTHER APPS, BUT they will still 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()) {
+ if (!_defaultScummVMSavesDir.exists() && _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());
@@ -627,16 +688,15 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
.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();
- }
- })
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ })
.show();
}
- retVal = true;
- return retVal;
+ return true;
}
}
diff --git a/dists/android/build.gradle b/dists/android/build.gradle
index 094eebfed8..ffb7ebbbea 100644
--- a/dists/android/build.gradle
+++ b/dists/android/build.gradle
@@ -66,3 +66,7 @@ android {
abortOnError false
}
}
+
+dependencies {
+ implementation "androidx.annotation:annotation:1.1.0"
+}
Commit: d268cf28b9d32c97e27ac833a17c6c73ff900219
https://github.com/scummvm/scummvm/commit/d268cf28b9d32c97e27ac833a17c6c73ff900219
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:08+03:00
Commit Message:
ANDROID: Use custom handler for long key press detection
To avoid possible mem leaks (see "This Handler Class Should Be Static Or Leaks Might Occurâ warning
Also a few optimizations based on recommendations from the Android Studio error highlighting/fix suggestions (F2)
Changed paths:
backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
backends/platform/android/org/scummvm/scummvm/ScummVM.java
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
diff --git a/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java b/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
index 01482a3d5a..31b754280a 100644
--- a/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
+++ b/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
@@ -51,13 +51,13 @@ public class ExternalStorage {
}
private static Pattern
- /** Pattern that SD card device should match */
+ // Pattern that SD card device should match
devicePattern = Pattern.compile("/dev/(block/.*vold.*|fuse)|/mnt/.*"),
- /** Pattern that SD card mount path should match */
+ // Pattern that SD card mount path should match
pathPattern = Pattern.compile("/(mnt|storage|external_sd|extsd|_ExternalSD|Removable|.*MicroSD).*", Pattern.CASE_INSENSITIVE),
- /** Pattern that the mount path should not match.
- * 'emulated' indicates an internal storage location, so skip it.
- * 'asec' is an encrypted package file, decrypted and mounted as a directory. */
+ // Pattern that the mount path should not match.
+ //' emulated' indicates an internal storage location, so skip it.
+ // 'asec' is an encrypted package file, decrypted and mounted as a directory.
pathAntiPattern = Pattern.compile(".*(/secure|/asec|/emulated).*"),
/** These are expected fs types, including vfat. tmpfs is not OK.
* fuse can be removable SD card (as on Moto E or Asus ZenPad), or can be internal (Huawei G610). */
@@ -116,14 +116,14 @@ public class ExternalStorage {
public static LinkedHashSet<File> findSdCardPath() {
String[] mountFields;
BufferedReader bufferedReader = null;
- String lineRead = null;
+ String lineRead;
- /** Possible SD card paths */
- LinkedHashSet<File> candidatePaths = new LinkedHashSet<File>();
+ // Possible SD card paths
+ LinkedHashSet<File> candidatePaths = new LinkedHashSet<>();
- /** Build a list of candidate paths, roughly in order of preference. That way if
- * we can't definitively detect removable storage, we at least can pick a more likely
- * candidate. */
+ // Build a list of candidate paths, roughly in order of preference. That way if
+ // we can't definitively detect removable storage, we at least can pick a more likely
+ // candidate.
// Could do: use getExternalStorageState(File path), with and without an argument, when
// available. With an argument is available since API level 21.
@@ -153,7 +153,7 @@ public class ExternalStorage {
}
// Get listing of mounted devices with their properties.
- ArrayList<File> mountedPaths = new ArrayList<File>();
+ ArrayList<File> mountedPaths = new ArrayList<>();
try {
// Note: Despite restricting some access to /proc (http://stackoverflow.com/a/38728738/423105),
// Android 7.0 does *not* block access to /proc/mounts, according to our test on George's Alcatel A30 GSM.
@@ -334,10 +334,7 @@ public class ExternalStorage {
*/
public static boolean isAvailable() {
String state = Environment.getExternalStorageState();
- if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
- return true;
- }
- return false;
+ return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
}
public static String getSdCardPath() {
@@ -349,10 +346,7 @@ public class ExternalStorage {
*/
public static boolean isWritable() {
String state = Environment.getExternalStorageState();
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- return true;
- }
- return false;
+ return Environment.MEDIA_MOUNTED.equals(state);
}
@@ -360,10 +354,10 @@ public class ExternalStorage {
* @return list of locations available. Odd elements are names, even are paths
*/
public static List<String> getAllStorageLocations() {
- List<String> map = new ArrayList<String>(20);
+ List<String> map = new ArrayList<>(20);
- List<String> mMounts = new ArrayList<String>(10);
- List<String> mVold = new ArrayList<String>(10);
+ List<String> mMounts = new ArrayList<>(10);
+ List<String> mVold = new ArrayList<>(10);
mMounts.add("/mnt/sdcard");
mVold.add("/mnt/sdcard");
@@ -417,27 +411,27 @@ public class ExternalStorage {
}
mVold.clear();
- List<String> mountHash = new ArrayList<String>(10);
+ List<String> mountHash = new ArrayList<>(10);
for (String mount : mMounts) {
File root = new File(mount);
if (root.exists() && root.isDirectory() && root.canRead()) {
File[] list = root.listFiles();
- String hash = "[";
+ StringBuilder hash = new StringBuilder("[");
if (list != null) {
for (File f : list) {
- hash += f.getName().hashCode() + ":" + f.length() + ", ";
+ hash.append(f.getName().hashCode()).append(":").append(f.length()).append(", ");
}
}
- hash += "]";
- if (!mountHash.contains(hash)) {
+ hash.append("]");
+ if (!mountHash.contains(hash.toString())) {
String key = SD_CARD + "_" + (map.size() / 2);
if (map.size() == 0) {
key = SD_CARD;
} else if (map.size() == 2) {
key = EXTERNAL_SD_CARD;
}
- mountHash.add(hash);
+ mountHash.add(hash.toString());
map.add(key);
map.add(root.getAbsolutePath());
}
@@ -456,7 +450,6 @@ public class ExternalStorage {
//Retrieve the External Storages root directory:
String externalStorageRootDir;
- int count = 0;
if ((externalStorageRootDir = primaryExternalStorage.getParent()) == null) { // no parent...
String key = primaryExternalStorage.getAbsolutePath();
if (!map.contains(key)) {
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
index 22cf3fceca..0c28a83f47 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVM.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
@@ -1,23 +1,21 @@
package org.scummvm.scummvm;
-import android.util.Log;
import android.content.res.AssetManager;
-import android.view.SurfaceHolder;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.UnsupportedEncodingException;
+import java.util.LinkedHashMap;
-import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
-
-import java.io.File;
-import java.io.UnsupportedEncodingException;
-import java.util.LinkedHashMap;
-import java.util.List;
+import javax.microedition.khronos.opengles.GL10;
public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
final protected static String LOG_TAG = "ScummVM";
@@ -37,13 +35,15 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
private String[] _args;
- final private native void create(AssetManager asset_manager,
- EGL10 egl, EGLDisplay egl_display,
- AudioTrack audio_track,
- int sample_rate, int buffer_size);
- final private native void destroy();
- final private native void setSurface(int width, int height);
- final private native int main(String[] args);
+ private native void create(AssetManager asset_manager,
+ EGL10 egl,
+ EGLDisplay egl_display,
+ AudioTrack audio_track,
+ int sample_rate,
+ int buffer_size);
+ private native void destroy();
+ private native void setSurface(int width, int height);
+ private native int main(String[] args);
// pause the engine and all native threads
final public native void setPause(boolean pause);
@@ -152,7 +152,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
System.exit(res);
}
- final private void initEGL() throws Exception {
+ private void initEGL() throws Exception {
_egl = (EGL10)EGLContext.getEGL();
_egl_display = _egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
@@ -219,7 +219,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
_egl_surface = EGL10.EGL_NO_SURFACE;
}
- final private void deinitEGL() {
+ private void deinitEGL() {
if (_egl_display != EGL10.EGL_NO_DISPLAY) {
_egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
@@ -240,7 +240,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
_egl = null;
}
- final private void initAudio() throws Exception {
+ private void initAudio() throws Exception {
_sample_rate = AudioTrack.getNativeOutputSampleRate(
AudioManager.STREAM_MUSIC);
_buffer_size = AudioTrack.getMinBufferSize(_sample_rate,
@@ -273,7 +273,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
_audio_track.getState()));
}
- final private void deinitAudio() {
+ private void deinitAudio() {
if (_audio_track != null)
_audio_track.stop();
@@ -406,9 +406,9 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
return s;
}
- };
+ }
- final private EGLConfig chooseEglConfig(EGLConfig[] configs) {
+ private EGLConfig chooseEglConfig(EGLConfig[] configs) {
EGLConfig res = configs[0];
int bestScore = -1;
@@ -447,7 +447,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
if (sleep_for_debugger) {
try {
Thread.sleep(20 * 1000);
- } catch (InterruptedException e) {
+ } catch (InterruptedException ignored) {
}
}
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 31a9ee8dab..07965ae275 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -334,6 +334,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
super.onDestroy();
if (_events != null) {
+ _events.clearEventHandler();
_events.sendQuitEvent();
try {
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
index 07c4233f0a..414033ab78 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
@@ -1,5 +1,6 @@
package org.scummvm.scummvm;
+import androidx.annotation.NonNull;
import android.os.Handler;
import android.os.Message;
import android.content.Context;
@@ -12,6 +13,8 @@ import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.inputmethod.InputMethodManager;
+import java.lang.ref.WeakReference;
+
public class ScummVMEvents implements
android.view.View.OnKeyListener,
android.view.View.OnTouchListener,
@@ -48,6 +51,8 @@ public class ScummVMEvents implements
final protected int _longPress;
final protected MouseHelper _mouseHelper;
+ final private ScummVMEventHandler keyHandler;
+
public ScummVMEvents(Context context, ScummVM scummvm, MouseHelper mouseHelper) {
_context = context;
_scummvm = scummvm;
@@ -58,6 +63,28 @@ public class ScummVMEvents implements
_gd.setIsLongpressEnabled(false);
_longPress = ViewConfiguration.getLongPressTimeout();
+
+ keyHandler = new ScummVMEventHandler(new ScummVMEventHandler.OnMessageReceivedListener() {
+ @Override
+ public void handleMessage(final Message msg) {
+ if (msg.what == MSG_SMENU_LONG_PRESS) {
+ // this displays the android keyboard (see showVirtualKeyboard() in ScummVMActivity.java)
+ // when menu key is long-pressed
+ InputMethodManager imm = (InputMethodManager)
+ _context.getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ if (imm != null)
+ imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ } else if (msg.what == MSG_SBACK_LONG_PRESS) {
+ _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+ _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+ }
+ }
+ });
+ }
+
+ public void clearEventHandler() {
+ keyHandler.clear();
}
final public void sendQuitEvent() {
@@ -79,23 +106,31 @@ public class ScummVMEvents implements
final static int MSG_SMENU_LONG_PRESS = 1;
final static int MSG_SBACK_LONG_PRESS = 2;
- final private Handler keyHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_SMENU_LONG_PRESS) {
- // this displays the android keyboard (see showVirtualKeyboard() in ScummVMActivity.java)
- // when menu key is long-pressed
- InputMethodManager imm = (InputMethodManager)
- _context.getSystemService(Context.INPUT_METHOD_SERVICE);
-
- if (imm != null)
- imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
- } else if (msg.what == MSG_SBACK_LONG_PRESS) {
- _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
- _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+ // Custom handler code (to avoid mem leaks, see warning "This Handler Class Should Be Static Or Leaks Might Occurâ) based on:
+ // https://stackoverflow.com/a/57926736
+ public static class ScummVMEventHandler extends Handler {
+
+ WeakReference<OnMessageReceivedListener> mListenerReference;
+
+ public ScummVMEventHandler(OnMessageReceivedListener listener) {
+ mListenerReference = new WeakReference<>(listener);
+ }
+
+ public synchronized void handleMessage(@NonNull Message msg) {
+ OnMessageReceivedListener listener = mListenerReference.get();
+ if(listener != null) {
+ listener.handleMessage(msg);
}
}
- };
+
+ public void clear() {
+ mListenerReference.clear();
+ }
+
+ public interface OnMessageReceivedListener {
+ void handleMessage(final Message message);
+ }
+ }
// OnKeyListener
@Override
Commit: 7c4f9df1a543914e5cba096d1949d0180f62ca8a
https://github.com/scummvm/scummvm/commit/7c4f9df1a543914e5cba096d1949d0180f62ca8a
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:08+03:00
Commit Message:
ANDROID: Upgrade to 2.3 version re-using any old configuration file
Changed paths:
A backends/platform/android/org/scummvm/scummvm/Version.java
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 07965ae275..d27fd64130 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -44,6 +44,7 @@ import java.io.OutputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
@@ -573,7 +574,38 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private boolean seekAndInitScummvmConfiguration() {
- _actualScummVMDataDir = getExternalFilesDir(null);
+ // https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)
+ // The returned path may change over time if the calling app is moved to an adopted storage device, so only relative paths should be persisted.
+ // Returns the absolute path to the directory on the primary shared/external storage device where the application can place persistent files it owns.
+ // These files are internal to the applications, and not typically visible to the user as media.
+ //
+ // This is like getFilesDir() in that these files will be deleted when the application is uninstalled, however there are some important differences:
+ //
+ // - Shared storage may not always be available, since removable media can be ejected by the user. Media state can be checked using Environment#getExternalStorageState(File).
+ // - There is no security enforced with these files. For example, any application holding Manifest.permission.WRITE_EXTERNAL_STORAGE can write to these files.
+ //
+ // If a shared storage device is emulated (as determined by Environment#isExternalStorageEmulated(File)), it's contents are backed by a private user data partition,
+ // !! which means there is little benefit to storing data here instead of the private directories returned by getFilesDir(), etc.!!
+ // TODO Maybe also make use Environment#isExternalStorageEmulated(File)) since this is not deprecated, to have more info available on storage
+ // TODO (other methods *are* deprecated -- such as getExternalStoragePublicDirectory)
+ // Starting in Build.VERSION_CODES.KITKAT, no permissions are required to read or write to the returned path; it's always accessible to the calling app.
+ // This only applies to paths generated for package name of the calling application. To access paths belonging to other packages,
+ // Manifest.permission.WRITE_EXTERNAL_STORAGE and/or Manifest.permission.READ_EXTERNAL_STORAGE are required.
+ //
+ // On devices with multiple users (as described by UserManager), each user has their own isolated shared storage. Applications only have access to the shared storage for the user they're running as.
+ //
+ // WARNING: The returned path may change over time if different shared storage media is inserted, so only relative paths should be persisted.
+ //
+ // If you supply a non-null type to this function, the returned file will be a path to a sub-directory of the given type.
+ //
+ File externalPossibleAlternateScummVMFilesDir = getExternalFilesDir(null);
+
+ // Unlike getExternalFilesDir, this is guaranteed to ALWAYS be available
+ //
+ // NOTE: It is better to just always use the internal app path anyway for ScummVM, as "_actualScummVMDataDir" that is,
+ // to avoid issues with unavailable shared / external storage and to be (mostly) compatible with what the older versions did
+ // WARNING: The returned path may change over time if the calling app is moved to an adopted storage device, so only relative paths should be persisted.
+ _actualScummVMDataDir = getFilesDir();
if (_actualScummVMDataDir == null || !_actualScummVMDataDir.canRead()) {
new AlertDialog.Builder(this)
.setTitle(R.string.no_external_files_dir_access_title)
@@ -599,13 +631,13 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
}
- File externalScummVMConfigDir = new File(_actualScummVMDataDir, ".config/scummvm");
- if (!externalScummVMConfigDir.exists() && 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());
+ File internalScummVMConfigDir = new File(_actualScummVMDataDir, ".config/scummvm");
+ if (!internalScummVMConfigDir.exists() && internalScummVMConfigDir.mkdirs()) {
+ Log.d(ScummVM.LOG_TAG, "Created ScummVM Config path: " + internalScummVMConfigDir.getPath());
+ } else if (internalScummVMConfigDir.isDirectory()) {
+ Log.d(ScummVM.LOG_TAG, "ScummVM Config path already exists: " + internalScummVMConfigDir.getPath());
} else {
- Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM Config path: " + externalScummVMConfigDir.getPath());
+ Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM Config path: " + internalScummVMConfigDir.getPath());
new AlertDialog.Builder(this)
.setTitle(R.string.no_config_file_title)
.setIcon(android.R.drawable.ic_dialog_alert)
@@ -619,7 +651,23 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
.show();
}
- // TODO search in other known places for scummvm.ini too
+ LinkedHashMap<String, File> candidateOldLocationsOfScummVMConfigMap = new LinkedHashMap<>();
+ // Note: The "missing" case below for: (scummvm.ini)) (SDL port - A) is checked above; it is the same path we store the config file for 2.3+
+ // SDL port was officially on the Play Store for versions 1.9+ up until and including 2.0)
+ // Using LinkedHashMap because the order of searching is important
+ // We want to re-use the more recent ScummVM old version too
+ // TODO try getDir too without a path? just "." ??
+ candidateOldLocationsOfScummVMConfigMap.put("(scummvm.ini) (SDL port - B)", new File(_actualScummVMDataDir, "../.config/scummvm/scummvm.ini"));
+ candidateOldLocationsOfScummVMConfigMap.put("(scummvm.ini) (SDL port - C)", new File(externalPossibleAlternateScummVMFilesDir, ".config/scummvm/scummvm.ini"));
+ candidateOldLocationsOfScummVMConfigMap.put("(scummvm.ini) (SDL port - D)", new File(externalPossibleAlternateScummVMFilesDir, "../.config/scummvm/scummvm.ini"));
+ candidateOldLocationsOfScummVMConfigMap.put("(scummvmrc) (version 1.8.1- or PlayStore 2.1.0) - Internal", new File(_actualScummVMDataDir, "scummvmrc"));
+ candidateOldLocationsOfScummVMConfigMap.put("(scummvmrc) (version 1.8.1- or PlayStore 2.1.0) - External", new File(externalPossibleAlternateScummVMFilesDir, "scummvmrc"));
+ candidateOldLocationsOfScummVMConfigMap.put("(.scummvmrc) (POSIX conformance) - Internal", new File(_actualScummVMDataDir, ".scummvmrc"));
+ candidateOldLocationsOfScummVMConfigMap.put("(.scummvmrc) (POSIX conformance) - External", new File(externalPossibleAlternateScummVMFilesDir, ".scummvmrc"));
+
+ boolean scummVMConfigHandled = false;
+ Version maxOldVersionFound = new Version("0"); // dummy initializer
+
_configScummvmFile = new File(_actualScummVMDataDir, "scummvm.ini");
try {
if (_configScummvmFile.exists() || !_configScummvmFile.createNewFile()) {
@@ -628,26 +676,61 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
String existingVersionInfo = getVersionInfoFromScummvmConfiguration(_configScummvmFile.getPath());
if (!"".equals(existingVersionInfo.trim())) {
Log.d(ScummVM.LOG_TAG, "Existing ScummVM Version: " + existingVersionInfo.trim());
+ Version tmpOldVersionFound = new Version(existingVersionInfo.trim());
+ if (tmpOldVersionFound.compareTo(maxOldVersionFound) > 0) {
+ maxOldVersionFound = tmpOldVersionFound;
+ scummVMConfigHandled = false; // invalidate the handled flag
+ }
} else {
- Log.d(ScummVM.LOG_TAG, "Could not find info on existing ScummVM version. Old or corrupt file?");
+ Log.d(ScummVM.LOG_TAG, "Could not find info on existing ScummVM version. Unsupported or corrupt file?");
}
+ scummVMConfigHandled = true;
} else {
- Log.d(ScummVM.LOG_TAG, "ScummVM Config file was created!");
+ Log.d(ScummVM.LOG_TAG, "An empty 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 (scummvmrc) ScummVM file was not found!");
- } else {
- Log.d(ScummVM.LOG_TAG, "Old config (scummvmrc) ScummVM file was found!");
- String existingVersionInfo = getVersionInfoFromScummvmConfiguration(_configScummvmFile.getPath());
+ }
+
+ //
+ // NOTE: Android app's version number (in build.gradle) avoids the need to check against "upgrading" to a lower version,
+ // since Android will not allow that and will force the user to uninstall first any current higher version.
+
+ // Do an exhaustive search to discover all old configs in order to:
+ // - find a useable / recent existing one that we might want to upgrade from
+ // - remove them as old remnants and avoid re-checking / re-using them in a subsequent installation
+ for (String oldConfigFiledescription : candidateOldLocationsOfScummVMConfigMap.keySet()) {
+ File oldCandidateScummVMConfig = candidateOldLocationsOfScummVMConfigMap.get(oldConfigFiledescription);
+ Log.d(ScummVM.LOG_TAG, "Looking for old config " + oldConfigFiledescription + " ScummVM file...");
+ Log.d(ScummVM.LOG_TAG, "at Path: " + oldCandidateScummVMConfig.getPath() + "...");
+ if (oldCandidateScummVMConfig.exists() && oldCandidateScummVMConfig.isFile()) {
+ Log.d(ScummVM.LOG_TAG, "Old config " + oldConfigFiledescription + " ScummVM file was found!");
+ String existingVersionInfo = getVersionInfoFromScummvmConfiguration(oldCandidateScummVMConfig.getPath());
if (!"".equals(existingVersionInfo.trim())) {
- Log.d(ScummVM.LOG_TAG, "Existing ScummVM Version: " + existingVersionInfo.trim());
+ Log.d(ScummVM.LOG_TAG, "Old config's ScummVM version: " + existingVersionInfo.trim());
+ Version tmpOldVersionFound = new Version(existingVersionInfo.trim());
+ if (tmpOldVersionFound.compareTo(maxOldVersionFound) > 0) {
+ maxOldVersionFound = tmpOldVersionFound;
+ scummVMConfigHandled = false; // invalidate the handled flag, since we found a new great(er) version so we should re-use that one
+ }
} else {
- Log.d(ScummVM.LOG_TAG, "Could not find info on existing ScummVM version. Old or corrupt file?");
+ Log.d(ScummVM.LOG_TAG, "Could not find info on the old config's ScummVM version. Unsupported or corrupt file?");
+ }
+ if (!scummVMConfigHandled) {
+ // We copy the old file over the new one.
+ // This will happen once during this installation, but on a subsequent one it will again copy that old config file
+ // if we don't remove it
+ copyFileUsingStream(oldCandidateScummVMConfig, _configScummvmFile);
+ Log.d(ScummVM.LOG_TAG, "Old config " + oldConfigFiledescription + " ScummVM file was renamed and overwrote the new (empty) scummvm.ini");
+ scummVMConfigHandled = true;
}
- copyFileUsingStream(oldScummVMconfig, _configScummvmFile);
- Log.d(ScummVM.LOG_TAG, "Old config (scummvmrc) ScummVM file was renamed and overwrote the new (empty) scummvm.ini");
+
+ // Here we remove the old config
+ if (oldCandidateScummVMConfig.delete()) {
+ Log.d(ScummVM.LOG_TAG, "The old config " + oldConfigFiledescription + " ScummVM file is now deleted!");
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Failed to delete the old config " + oldConfigFiledescription + " ScummVM file!");
+ }
+ } else {
+ Log.d(ScummVM.LOG_TAG, "...not found!");
}
}
} catch(Exception e) {
@@ -665,6 +748,11 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
.show();
}
+ if (maxOldVersionFound.compareTo(new Version("0")) != 0) {
+ Log.d(ScummVM.LOG_TAG, "Maximum ScummVM version found and (re)used is: " + maxOldVersionFound.getDescription() +" (" + maxOldVersionFound.get() +")");
+ } else {
+ Log.d(ScummVM.LOG_TAG, "No viable existing ScummVM config version found");
+ }
// 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)
diff --git a/backends/platform/android/org/scummvm/scummvm/Version.java b/backends/platform/android/org/scummvm/scummvm/Version.java
new file mode 100644
index 0000000000..3ae3dd8958
--- /dev/null
+++ b/backends/platform/android/org/scummvm/scummvm/Version.java
@@ -0,0 +1,62 @@
+package org.scummvm.scummvm;
+
+// Based on code from: https://stackoverflow.com/a/11024200
+public class Version implements Comparable<Version> {
+
+ private String versionOnlyDigits;
+ private String versionDescription;
+
+ public final String getDescription() {
+ return this.versionDescription;
+ }
+
+ public final String get() {
+ return this.versionOnlyDigits;
+ }
+
+ public Version(String version) {
+ if(version == null) {
+ this.versionOnlyDigits = "0";
+ this.versionDescription = "0";
+ } else {
+ this.versionDescription = version;
+ // cleanup from any non-digit characters in the version string
+ String strippedVersion = version.replaceAll("[^\\d.]", "");
+ if (!strippedVersion.matches("[0-9]+(\\.[0-9]+)*")) {
+ this.versionOnlyDigits = "0";
+ } else {
+ this.versionOnlyDigits = strippedVersion;
+ }
+ }
+ }
+
+ @Override public int compareTo(Version that) {
+ if(that == null)
+ return 1;
+ String[] thisParts = this.get().split("\\.");
+ String[] thatParts = that.get().split("\\.");
+ int length = Math.max(thisParts.length, thatParts.length);
+ for(int i = 0; i < length; i++) {
+ int thisPart = i < thisParts.length ?
+ Integer.parseInt(thisParts[i]) : 0;
+ int thatPart = i < thatParts.length ?
+ Integer.parseInt(thatParts[i]) : 0;
+ if(thisPart < thatPart)
+ return -1;
+ if(thisPart > thatPart)
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override public boolean equals(Object that) {
+ if(this == that)
+ return true;
+ if(that == null)
+ return false;
+ if(this.getClass() != that.getClass())
+ return false;
+ return this.compareTo((Version) that) == 0;
+ }
+
+}
Commit: 7fe7f0c226b3e0da63fe950356bdfc817a9adabc
https://github.com/scummvm/scummvm/commit/7fe7f0c226b3e0da63fe950356bdfc817a9adabc
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:09+03:00
Commit Message:
ANDROID: Revert chnage for long press AC_BACK handler
Huawei Android 9 seemed to not be working ok (or at all) with the change
Changed paths:
backends/platform/android/android.cpp
backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index ab52125a81..84a838a460 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -311,11 +311,10 @@ void OSystem_Android::initBackend() {
ConfMan.registerDefault("aspect_ratio", true);
ConfMan.registerDefault("touchpad_mouse_mode", true);
ConfMan.registerDefault("onscreen_control", true);
- // The swap_menu_and_back is a legacy configuration key
+ // The swap_menu_and_back is a deprecated configuration key
// It is no longer relevant, after introducing the keymapper functionality
// since the behaviour of the menu and back buttons is now handled by the keymapper.
- // The key is thus registered to default to a "false" value
- ConfMan.registerDefault("swap_menu_and_back", false);
+ // We now ignore it completely
ConfMan.registerDefault("autosave_period", 0);
ConfMan.setBool("FM_high_quality", false);
@@ -328,10 +327,12 @@ void OSystem_Android::initBackend() {
ConfMan.set("browser_lastpath", "/");
}
- if (ConfMan.hasKey("touchpad_mouse_mode"))
+ if (ConfMan.hasKey("touchpad_mouse_mode")) {
_touchpad_mode = ConfMan.getBool("touchpad_mouse_mode");
- else
+ } else {
ConfMan.setBool("touchpad_mouse_mode", true);
+ _touchpad_mode = true;
+ }
if (ConfMan.hasKey("onscreen_control"))
JNI::showKeyboardControl(ConfMan.getBool("onscreen_control"));
@@ -425,18 +426,10 @@ Common::KeymapperDefaultBindings *OSystem_Android::getKeymapperDefaultBindings()
Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
// The swap_menu_and_back is a legacy configuration key
- // It is only checked here for compatibility with old config files
- // where it may have been set as "true"
- // TODO Why not just ignore it entirely anyway?
- if (ConfMan.hasKey("swap_menu_and_back") && ConfMan.getBool("swap_menu_and_back")) {
- keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "MENU", "AC_BACK");
- keymapperDefaultBindings->setDefaultBinding("engine-default", Common::kStandardActionSkip, "MENU");
- keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "CLOS", "MENU");
- } else {
- keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "MENU", "MENU");
- keymapperDefaultBindings->setDefaultBinding("engine-default", Common::kStandardActionSkip, "AC_BACK");
- keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "CLOS", "AC_BACK");
- }
+ // We now ignore it entirely (it as always false -- ie. back short press is AC_BACK)
+ keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "MENU", "MENU");
+ keymapperDefaultBindings->setDefaultBinding("engine-default", Common::kStandardActionSkip, "AC_BACK");
+ keymapperDefaultBindings->setDefaultBinding(Common::kGuiKeymapName, "CLOS", "AC_BACK");
return keymapperDefaultBindings;
}
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
index 414033ab78..632adbf2de 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
@@ -1,9 +1,10 @@
package org.scummvm.scummvm;
-import androidx.annotation.NonNull;
+//import androidx.annotation.NonNull;
import android.os.Handler;
import android.os.Message;
import android.content.Context;
+//import android.util.Log;
import android.view.KeyEvent;
import android.view.KeyCharacterMap;
import android.view.MotionEvent;
@@ -13,7 +14,7 @@ import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.inputmethod.InputMethodManager;
-import java.lang.ref.WeakReference;
+//import java.lang.ref.WeakReference;
public class ScummVMEvents implements
android.view.View.OnKeyListener,
@@ -51,7 +52,29 @@ public class ScummVMEvents implements
final protected int _longPress;
final protected MouseHelper _mouseHelper;
- final private ScummVMEventHandler keyHandler;
+ // Reverted code back to using the native Handler function instead of a static custom,
+ // since that had issues detecting the long-presses for some reason
+ // So for now we shall ignore the Android Studio warning for "This Handler class should be static or leaks might occur (anonymous android.os.Handler)"
+ //
+ // TODO investigate further why our static custom Handler based on https://stackoverflow.com/a/57926736 was not receiving messages *especially* on a recent enough Android 9 device (Huawei MediaPad M5 CMR-W09)
+ //
+ final private Handler _keyHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_SMENU_LONG_PRESS) {
+ // this displays the android keyboard (see showVirtualKeyboard() in ScummVMActivity.java)
+ // when menu key is long-pressed
+ InputMethodManager imm = (InputMethodManager)
+ _context.getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ if (imm != null)
+ imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+ } else if (msg.what == MSG_SBACK_LONG_PRESS) {
+ _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+ _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+ }
+ }
+ };
public ScummVMEvents(Context context, ScummVM scummvm, MouseHelper mouseHelper) {
_context = context;
@@ -63,29 +86,9 @@ public class ScummVMEvents implements
_gd.setIsLongpressEnabled(false);
_longPress = ViewConfiguration.getLongPressTimeout();
-
- keyHandler = new ScummVMEventHandler(new ScummVMEventHandler.OnMessageReceivedListener() {
- @Override
- public void handleMessage(final Message msg) {
- if (msg.what == MSG_SMENU_LONG_PRESS) {
- // this displays the android keyboard (see showVirtualKeyboard() in ScummVMActivity.java)
- // when menu key is long-pressed
- InputMethodManager imm = (InputMethodManager)
- _context.getSystemService(Context.INPUT_METHOD_SERVICE);
-
- if (imm != null)
- imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
- } else if (msg.what == MSG_SBACK_LONG_PRESS) {
- _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
- _scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
- }
- }
- });
}
- public void clearEventHandler() {
- keyHandler.clear();
- }
+ public void clearEventHandler() { }
final public void sendQuitEvent() {
_scummvm.pushEvent(JE_QUIT, 0, 0, 0, 0, 0, 0);
@@ -106,32 +109,6 @@ public class ScummVMEvents implements
final static int MSG_SMENU_LONG_PRESS = 1;
final static int MSG_SBACK_LONG_PRESS = 2;
- // Custom handler code (to avoid mem leaks, see warning "This Handler Class Should Be Static Or Leaks Might Occurâ) based on:
- // https://stackoverflow.com/a/57926736
- public static class ScummVMEventHandler extends Handler {
-
- WeakReference<OnMessageReceivedListener> mListenerReference;
-
- public ScummVMEventHandler(OnMessageReceivedListener listener) {
- mListenerReference = new WeakReference<>(listener);
- }
-
- public synchronized void handleMessage(@NonNull Message msg) {
- OnMessageReceivedListener listener = mListenerReference.get();
- if(listener != null) {
- listener.handleMessage(msg);
- }
- }
-
- public void clear() {
- mListenerReference.clear();
- }
-
- public interface OnMessageReceivedListener {
- void handleMessage(final Message message);
- }
- }
-
// OnKeyListener
@Override
final public boolean onKey(View v, int keyCode, KeyEvent e) {
@@ -179,13 +156,12 @@ public class ScummVMEvents implements
typeOfLongPressMessage = MSG_SBACK_LONG_PRESS;
}
- final boolean fired = !keyHandler.hasMessages(typeOfLongPressMessage);
+ final boolean fired = !_keyHandler.hasMessages(typeOfLongPressMessage);
- keyHandler.removeMessages(typeOfLongPressMessage);
+ _keyHandler.removeMessages(typeOfLongPressMessage);
if (action == KeyEvent.ACTION_DOWN) {
- keyHandler.sendMessageDelayed(keyHandler.obtainMessage(
- typeOfLongPressMessage), _longPress);
+ _keyHandler.sendMessageDelayed(_keyHandler.obtainMessage(typeOfLongPressMessage), _longPress);
return true;
} else if (action != KeyEvent.ACTION_UP) {
return true;
Commit: 3edb4e3e58f095452e20b6585e433b2989c24d2a
https://github.com/scummvm/scummvm/commit/3edb4e3e58f095452e20b6585e433b2989c24d2a
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:09+03:00
Commit Message:
ANDROID: Copy asset files in internal app folder
Changed paths:
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index d27fd64130..25259b9326 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -8,6 +8,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.AssetManager;
import android.graphics.Rect;
import android.media.AudioManager;
import android.net.Uri;
@@ -58,6 +59,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private static boolean _hoverAvailable;
private ClipboardManager _clipboard;
+ private Version _currentScummVMVersion;
private File _configScummvmFile;
private File _actualScummVMDataDir;
private File _defaultScummVMSavesDir;
@@ -231,6 +233,11 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
main_surface.requestFocus();
+ _clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
+
+ _currentScummVMVersion = new Version(BuildConfig.VERSION_NAME);
+ Log.d(ScummVM.LOG_TAG, "Current ScummVM version being installed is: " + _currentScummVMVersion.getDescription() + " (" + _currentScummVMVersion.get() + ")");
+
// 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/"
@@ -248,48 +255,45 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// seekAndInitScummvmConfiguration() returns false if something went wrong
// when initializing configuration (or when seeking and trying to use an existing 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)
- }
+ Log.e(ScummVM.LOG_TAG, "Error while trying to find and/or initialize ScummVM configuration file!");
+ // in fact in all the cases where we return false, we also called finish()
+ } else {
+ // We should have a valid path to a configuration file here
+
+ // Start ScummVM
+ _scummvm = new MyScummVM(main_surface.getHolder());
+
+ _scummvm.setArgs(new String[]{
+ "ScummVM",
+ "--config=" + _configScummvmFile.getPath(),
+ "--path=" + _actualScummVMDataDir.getPath(),
+ "--savepath=" + _defaultScummVMSavesDir.getPath()
+ });
+
+ Log.d(ScummVM.LOG_TAG, "Hover available: " + _hoverAvailable);
+ if (_hoverAvailable) {
+ _mouseHelper = new MouseHelper(_scummvm);
+ _mouseHelper.attach(main_surface);
+ }
- _clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
+ _events = new ScummVMEvents(this, _scummvm, _mouseHelper);
+ } else {
+ _events = new ScummVMEventsHoneycomb(this, _scummvm, _mouseHelper);
+ }
- // Start ScummVM
- _scummvm = new MyScummVM(main_surface.getHolder());
+ // On screen button listener
+ findViewById(R.id.show_keyboard).setOnClickListener(keyboardBtnOnClickListener);
- _scummvm.setArgs(new String[] {
- "ScummVM",
- "--config=" + _configScummvmFile.getPath(),
- "--path=" + _actualScummVMDataDir.getPath(),
- "--savepath=" + _defaultScummVMSavesDir.getPath()
- });
+ // Keyboard visibility listener
+ setKeyboardVisibilityListener(this);
- Log.d(ScummVM.LOG_TAG, "Hover available: " + _hoverAvailable);
- if (_hoverAvailable) {
- _mouseHelper = new MouseHelper(_scummvm);
- _mouseHelper.attach(main_surface);
- }
+ main_surface.setOnKeyListener(_events);
+ main_surface.setOnTouchListener(_events);
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1)
- {
- _events = new ScummVMEvents(this, _scummvm, _mouseHelper);
- }
- else
- {
- _events = new ScummVMEventsHoneycomb(this, _scummvm, _mouseHelper);
+ _scummvm_thread = new Thread(_scummvm, "ScummVM");
+ _scummvm_thread.start();
}
-
- // On screen button listener
- findViewById(R.id.show_keyboard).setOnClickListener(keyboardBtnOnClickListener);
-
- // Keyboard visibility listener
- setKeyboardVisibilityListener(this);
-
- main_surface.setOnKeyListener(_events);
- main_surface.setOnTouchListener(_events);
-
- _scummvm_thread = new Thread(_scummvm, "ScummVM");
- _scummvm_thread.start();
}
@Override
@@ -524,11 +528,15 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private static void copyFileUsingStream(File source, File dest) throws IOException {
try (InputStream is = new FileInputStream(source); OutputStream os = new FileOutputStream(dest)) {
- byte[] buffer = new byte[1024];
- int length;
- while ((length = is.read(buffer)) > 0) {
- os.write(buffer, 0, length);
- }
+ copyStreamToStream(is, os);
+ }
+ }
+
+ private static void copyStreamToStream(InputStream is, OutputStream os) throws IOException {
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = is.read(buffer)) > 0) {
+ os.write(buffer, 0, length);
}
}
@@ -649,6 +657,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
})
.show();
+ return false;
}
LinkedHashMap<String, File> candidateOldLocationsOfScummVMConfigMap = new LinkedHashMap<>();
@@ -746,6 +755,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
})
.show();
+ return false;
}
if (maxOldVersionFound.compareTo(new Version("0")) != 0) {
@@ -754,6 +764,15 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
Log.d(ScummVM.LOG_TAG, "No viable existing ScummVM config version found");
}
+ //
+ // TODO The assets cleanup upgrading system is not perfect but it will have to do
+ // A more efficient way would be to compare hash (when we deem that an upgrade is happening, so we will also still have to compare versions)
+ // Note that isSideUpgrading is also true each time we re-launch the app
+ // Also even during a side-upgrade we cleanup any redundant files (no longer part of our assets)
+ boolean isSideUpgrading = (maxOldVersionFound.compareTo(_currentScummVMVersion) == 0);
+ copyAssetsToInternalMemory(isSideUpgrading);
+
+ //
// 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:
@@ -783,9 +802,103 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
})
.show();
+ return false;
}
return true;
}
+
+ private boolean containsStringEntry(@NonNull String[] stringItenary, String targetEntry) {
+ for (String sourceEntry : stringItenary) {
+ // Log.d(ScummVM.LOG_TAG, "Comparing filename: " + sourceEntry + " to filename: " + targetEntry);
+ if (sourceEntry.compareToIgnoreCase(targetEntry) == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // clear up any possibly deprecated assets (when upgrading to a new version)
+ // Don't remove the scummvm.ini file!
+ // Remove any files not in the filesItenary, even in a sideUpgrade
+ // Remove any files in the filesItenary only if not a sideUpgrade
+ private void internalAppFolderCleanup(String[] filesItenary, boolean sideUpgrade) {
+ if (_actualScummVMDataDir != null) {
+ File[] extfiles = _actualScummVMDataDir.listFiles();
+ if (extfiles != null) {
+ Log.d(ScummVM.LOG_TAG, "Cleaning up files in internal app space");
+ for (File extfile : extfiles) {
+ if (extfile.isFile()) {
+ if (extfile.getName().compareToIgnoreCase("scummvm.ini") != 0
+ && (!containsStringEntry(filesItenary, extfile.getName())
+ || !sideUpgrade)
+ ) {
+ Log.d(ScummVM.LOG_TAG, "Deleting file:" + extfile.getName());
+ if (!extfile.delete()) {
+ Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + extfile.getName());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // code based on https://stackoverflow.com/a/4530294
+ // Note, the following assumptions are made (since they are true as of yet)
+ // - We don't need to copy (sub)folders
+ // - We copy all the files from our assets (not a subset of them)
+ // Otherwise we would probably need to create a specifically named zip file with the selection of files we'd need to extract to the internal memory
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+ private void copyAssetsToInternalMemory(boolean sideUpgrade) {
+ // sideUpgrade is set to true, if we upgrade to the same version -- just check for the files existence before copying
+ if (_actualScummVMDataDir != null) {
+ AssetManager assetManager = getAssets();
+ String[] files = null;
+ try {
+ files = assetManager.list("");
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to get asset file list.", e);
+ }
+
+ internalAppFolderCleanup(files, sideUpgrade);
+
+ if (files != null) {
+ for (String filename : files) {
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ in = assetManager.open(filename);
+ File outFile = new File(_actualScummVMDataDir, filename);
+ if (sideUpgrade && outFile.exists() && outFile.isFile()) {
+ Log.d(ScummVM.LOG_TAG, "Side-upgrade. No need to update asset file: " + filename);
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Copying asset file: " + filename);
+ out = new FileOutputStream(outFile);
+ copyStreamToStream(in, out);
+ }
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to copy asset file: " + filename);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
}
Commit: aeeffa1e48e128e9174dcddf0730d4ae22f37b0e
https://github.com/scummvm/scummvm/commit/aeeffa1e48e128e9174dcddf0730d4ae22f37b0e
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:09+03:00
Commit Message:
ANDROID: Remove unnecessary check for isFile in a sideUpgrade
Changed paths:
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 25259b9326..4632b85659 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -871,7 +871,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
try {
in = assetManager.open(filename);
File outFile = new File(_actualScummVMDataDir, filename);
- if (sideUpgrade && outFile.exists() && outFile.isFile()) {
+ if (sideUpgrade && outFile.exists()) {
Log.d(ScummVM.LOG_TAG, "Side-upgrade. No need to update asset file: " + filename);
} else {
Log.d(ScummVM.LOG_TAG, "Copying asset file: " + filename);
Commit: 495420a027e51a5c2af67ecae9e0e1a6363940bc
https://github.com/scummvm/scummvm/commit/495420a027e51a5c2af67ecae9e0e1a6363940bc
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:09+03:00
Commit Message:
ANDROID: Add internal app path to SearchSet
Also have it with higher priority than the Android's assets structure which is too slow
Fixes a bug whereby a large font.dat file was very slow to be accessed during launch (for the modern themes), due to it being accessed from the Assets rather than the file system
Changed paths:
backends/platform/android/jni-android.cpp
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/jni-android.cpp b/backends/platform/android/jni-android.cpp
index 225cb4c2a1..10419a5474 100644
--- a/backends/platform/android/jni-android.cpp
+++ b/backends/platform/android/jni-android.cpp
@@ -378,11 +378,15 @@ void JNI::showKeyboardControl(bool enable) {
}
}
+// The following adds assets folder to search set.
+// However searching and retrieving from "assets" on Android this is slow
+// so we also make sure to add the "path" directory, with a higher priority
+// This is done via a call to ScummVMActivity's (java) getSysArchives
void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
JNIEnv *env = JNI::getEnv();
- s.add("ASSET", _asset_archive, priority, false);
-
+ // get any additional specified paths (from ScummVMActivity code)
+ // Insert them with "priority" priority.
jobjectArray array =
(jobjectArray)env->CallObjectMethod(_jobj, _MID_getSysArchives);
@@ -407,6 +411,15 @@ void JNI::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
env->DeleteLocalRef(path_obj);
}
+
+ // add the internal asset (android's structure) with a lower priority,
+ // since:
+ // 1. It is very slow in accessing large files (eg our growing fonts.dat)
+ // 2. we extract the asset contents anyway to the internal app path
+ // 3. we pass the internal app path in the process above (via _MID_getSysArchives)
+ // However, we keep android APK's "assets" as a fall back, in case something went wrong with the extraction process
+ // and since we had the code anyway
+ s.add("ASSET", _asset_archive, priority - 1, false);
}
char *JNI::convertEncoding(const char *to, const char *from, const char *string, size_t length) {
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 4632b85659..4135f73ea7 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -181,7 +181,8 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
@Override
protected String[] getSysArchives() {
- return new String[0];
+ Log.d(ScummVM.LOG_TAG, "Adding to Search Archive: " + _actualScummVMDataDir.getPath());
+ return new String[] {_actualScummVMDataDir.getPath()};
}
@Override
Commit: d95066e04ddb4fb6a6b002d3b15a0a09a031747a
https://github.com/scummvm/scummvm/commit/d95066e04ddb4fb6a6b002d3b15a0a09a031747a
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:09+03:00
Commit Message:
ANDROID: Migrate old save files
More testing pending
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 84a838a460..b054df033f 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -342,6 +342,7 @@ void OSystem_Android::initBackend() {
// BUG: "transient" ConfMan settings get nuked by the options
// screen. Passing the savepath in this way makes it stick
// (via ConfMan.registerDefault)
+ // TODO is this right to save full path?
_savefileManager = new DefaultSaveFileManager(ConfMan.get("savepath"));
// TODO remove the debug message eventually
LOGD("Setting DefaultSaveFileManager path to: %s", ConfMan.get("savepath").c_str());
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 4135f73ea7..19ed5160eb 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -16,6 +16,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
+import android.os.Environment;
import android.text.ClipboardManager;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -62,7 +63,8 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private Version _currentScummVMVersion;
private File _configScummvmFile;
private File _actualScummVMDataDir;
- private File _defaultScummVMSavesDir;
+ private File _usingScummVMSavesDir;
+ private File _usingLogFile;
/**
@@ -264,11 +266,17 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// Start ScummVM
_scummvm = new MyScummVM(main_surface.getHolder());
+// Log.d(ScummVM.LOG_TAG, "CONFIG: " + _configScummvmFile.getPath());
+// Log.d(ScummVM.LOG_TAG, "PATH: " + _actualScummVMDataDir.getPath());
+// Log.d(ScummVM.LOG_TAG, "LOG: " + _usingLogFile.getPath());
+// Log.d(ScummVM.LOG_TAG, "SAVEPATH: " + _usingScummVMSavesDir.getPath());
+
+ // TODO log file setting via "--logfile=" + _usingLogFile.getPath() causes crash
_scummvm.setArgs(new String[]{
"ScummVM",
"--config=" + _configScummvmFile.getPath(),
"--path=" + _actualScummVMDataDir.getPath(),
- "--savepath=" + _defaultScummVMSavesDir.getPath()
+ "--savepath=" + _usingScummVMSavesDir.getPath()
});
Log.d(ScummVM.LOG_TAG, "Hover available: " + _hoverAvailable);
@@ -580,6 +588,19 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return "";
}
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+ private static String getSavepathInfoFromScummvmConfiguration(String fullIniFilePath) {
+ try (BufferedReader bufferedReader = new BufferedReader(new FileReader(fullIniFilePath))) {
+ Map<String, Properties> parsedIniMap = parseINI(bufferedReader);
+ if (!parsedIniMap.isEmpty() && parsedIniMap.containsKey("scummvm")) {
+ return Objects.requireNonNull(parsedIniMap.get("scummvm")).getProperty("savepath", "");
+ }
+ } catch (IOException ignored) {
+ } catch (NullPointerException ignored) {
+ }
+ return "";
+ }
+
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private boolean seekAndInitScummvmConfiguration() {
@@ -607,6 +628,19 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
//
// If you supply a non-null type to this function, the returned file will be a path to a sub-directory of the given type.
//
+ // ----
+ // Also note (via https://stackoverflow.com/a/41262228)
+ // The getExternalFilesDir(String type) will call getExternalFilesDirs(String type) (notice the 's' at the final of the second method name).
+ // The getExternalFilesDirs(String type) will find all dirs of the type, and calls ensureDirsExistOrFilter() at the end to ensure the directories exist.
+ //
+ // If the dir can't be reached, it will print a warning!
+ //
+ // Log.w(TAG, "Failed to ensure directory: " + dir);
+ // dir = null;
+ //
+ // So, if your device has two sdcard paths, it will produce two dirs. If one is not available, the warning will come up.
+ // ----
+
File externalPossibleAlternateScummVMFilesDir = getExternalFilesDir(null);
// Unlike getExternalFilesDir, this is guaranteed to ALWAYS be available
@@ -615,11 +649,47 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// to avoid issues with unavailable shared / external storage and to be (mostly) compatible with what the older versions did
// WARNING: The returned path may change over time if the calling app is moved to an adopted storage device, so only relative paths should be persisted.
_actualScummVMDataDir = getFilesDir();
- if (_actualScummVMDataDir == null || !_actualScummVMDataDir.canRead()) {
+ // Checking for null only makes sense if we were using external storage
+// 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();
+// return false;
+// }
+
+ Log.d(ScummVM.LOG_TAG, "Base ScummVM data folder is: " + _actualScummVMDataDir.getPath());
+ String smallNodeDesc;
+ File[] extfiles = _actualScummVMDataDir.listFiles();
+ if (extfiles != null) {
+ Log.d(ScummVM.LOG_TAG, "Size: "+ extfiles.length);
+ for (File extfile : extfiles) {
+ smallNodeDesc = "(F)";
+ if (extfile.isDirectory()) {
+ smallNodeDesc = "(D)";
+ }
+ Log.d(ScummVM.LOG_TAG, "Name: " + smallNodeDesc + " " + extfile.getName());
+ }
+ }
+
+ File internalScummVMLogsDir = new File(_actualScummVMDataDir, ".cache/scummvm/logs");
+ if (!internalScummVMLogsDir.exists() && internalScummVMLogsDir.mkdirs()) {
+ Log.d(ScummVM.LOG_TAG, "Created ScummVM Logs path: " + internalScummVMLogsDir.getPath());
+ } else if (internalScummVMLogsDir.isDirectory()) {
+ Log.d(ScummVM.LOG_TAG, "ScummVM Logs path already exists: " + internalScummVMLogsDir.getPath());
+ } else {
+ Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM Logs path: " + internalScummVMLogsDir.getPath());
new AlertDialog.Builder(this)
- .setTitle(R.string.no_external_files_dir_access_title)
+ .setTitle(R.string.no_log_file_title)
.setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.no_external_files_dir_access)
+ .setMessage(R.string.no_log_file)
.setNegativeButton(R.string.quit,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
@@ -630,14 +700,29 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return false;
}
- Log.d(ScummVM.LOG_TAG, "Base ScummVM data folder is: " + _actualScummVMDataDir.getPath());
-
- File[] extfiles = _actualScummVMDataDir.listFiles();
- if (extfiles != null) {
- Log.d(ScummVM.LOG_TAG, "Size: "+ extfiles.length);
- for (File extfile : extfiles) {
- Log.d(ScummVM.LOG_TAG, "FileName:" + extfile.getName());
+ _usingLogFile = new File(internalScummVMLogsDir, "scummvm.log");
+ try {
+ if (_usingLogFile.exists() || !_usingLogFile.createNewFile()) {
+ Log.d(ScummVM.LOG_TAG, "ScummVM Log file already exists!");
+ Log.d(ScummVM.LOG_TAG, "Existing ScummVM Log: " + _usingLogFile.getPath());
+ } else {
+ Log.d(ScummVM.LOG_TAG, "An empty ScummVM log file was created!");
+ Log.d(ScummVM.LOG_TAG, "New ScummVM Log: " + _usingLogFile.getPath());
}
+ } catch (Exception e) {
+ e.printStackTrace();
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.no_log_file_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.no_log_file)
+ .setNegativeButton(R.string.quit,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ })
+ .show();
+ return false;
}
File internalScummVMConfigDir = new File(_actualScummVMDataDir, ".config/scummvm");
@@ -707,12 +792,12 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// Do an exhaustive search to discover all old configs in order to:
// - find a useable / recent existing one that we might want to upgrade from
// - remove them as old remnants and avoid re-checking / re-using them in a subsequent installation
- for (String oldConfigFiledescription : candidateOldLocationsOfScummVMConfigMap.keySet()) {
- File oldCandidateScummVMConfig = candidateOldLocationsOfScummVMConfigMap.get(oldConfigFiledescription);
- Log.d(ScummVM.LOG_TAG, "Looking for old config " + oldConfigFiledescription + " ScummVM file...");
+ for (String oldConfigFileDescription : candidateOldLocationsOfScummVMConfigMap.keySet()) {
+ File oldCandidateScummVMConfig = candidateOldLocationsOfScummVMConfigMap.get(oldConfigFileDescription);
+ Log.d(ScummVM.LOG_TAG, "Looking for old config " + oldConfigFileDescription + " ScummVM file...");
Log.d(ScummVM.LOG_TAG, "at Path: " + oldCandidateScummVMConfig.getPath() + "...");
if (oldCandidateScummVMConfig.exists() && oldCandidateScummVMConfig.isFile()) {
- Log.d(ScummVM.LOG_TAG, "Old config " + oldConfigFiledescription + " ScummVM file was found!");
+ Log.d(ScummVM.LOG_TAG, "Old config " + oldConfigFileDescription + " ScummVM file was found!");
String existingVersionInfo = getVersionInfoFromScummvmConfiguration(oldCandidateScummVMConfig.getPath());
if (!"".equals(existingVersionInfo.trim())) {
Log.d(ScummVM.LOG_TAG, "Old config's ScummVM version: " + existingVersionInfo.trim());
@@ -729,15 +814,15 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// This will happen once during this installation, but on a subsequent one it will again copy that old config file
// if we don't remove it
copyFileUsingStream(oldCandidateScummVMConfig, _configScummvmFile);
- Log.d(ScummVM.LOG_TAG, "Old config " + oldConfigFiledescription + " ScummVM file was renamed and overwrote the new (empty) scummvm.ini");
+ Log.d(ScummVM.LOG_TAG, "Old config " + oldConfigFileDescription + " ScummVM file was renamed and overwrote the new (empty) scummvm.ini");
scummVMConfigHandled = true;
}
// Here we remove the old config
if (oldCandidateScummVMConfig.delete()) {
- Log.d(ScummVM.LOG_TAG, "The old config " + oldConfigFiledescription + " ScummVM file is now deleted!");
+ Log.d(ScummVM.LOG_TAG, "The old config " + oldConfigFileDescription + " ScummVM file is now deleted!");
} else {
- Log.d(ScummVM.LOG_TAG, "Failed to delete the old config " + oldConfigFiledescription + " ScummVM file!");
+ Log.d(ScummVM.LOG_TAG, "Failed to delete the old config " + oldConfigFileDescription + " ScummVM file!");
}
} else {
Log.d(ScummVM.LOG_TAG, "...not found!");
@@ -775,27 +860,54 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
//
// 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 choose to store savegames on app's external storage, which means they're ACCESSIBLE BY OTHER APPS, BUT they will still get DELETED ON UNINSTALL!
+ // First see in ScummVM if there is a saved "savepath" in the config file
+ // This is the case where the user has set the global save path from the GUI, explicitly to something other than Default
+ //
+ // Main logic:
+ // - Create an internal savepath ANYWAY if it does not exist
+ // - If our internal savepath is empty (and only then):
+ // a. TODO maybe create a dummy file in it (to skip the process next time)
+ // b. we search for the largest save folder of a previous ScummVM version
+ // TODO we could take into account which versions tended to save in which locations, so as to prioritize a recent version
+ // but for now we will go with absolute size as the only comparison criteria
+ // So we store the path with max num of files (or none if all are empty)
+ // c. After the search, if we have a valid folder with non-zero size, we copy all files to our internal save path
+ //
+ // Then we look for two main cases:
+ // 1. If there is a valid "savepath" persisted in the config file,
+ // and it is a directory that exists and we can list its contents (even if 0 contents)
+ // then we use that one as savepath
+ // 2. If not, we fall back to our internal savepath
//
- _defaultScummVMSavesDir = new File(_actualScummVMDataDir, "saves");
+
+ // TODO We should always keep in mind that *STORING* full paths (in general) in config files or elsewhere is considered bad practice on Android
+ // due to features like being able to switch storage for applications between internal and external
+ // or external storage not always being available (but then eg. a save file on the storage should be correctly shown as not available)
+ // or maybe among Android OS versions the same external storage could be mounted to a (somewhat) different path?
+ // However, it seems unavoidable when user has set paths explicitly (ie not using the defaults)
+ // We always set the default save path as a launch parameter
+ //
+ // By default choose to store savegames on app's internal storage, which is always available
//
- // TODO what about old save paths from plain android port? do we favor them?
- if (!_defaultScummVMSavesDir.exists() && _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());
+ File defaultScummVMSavesPath = new File(_actualScummVMDataDir, "saves");
+ // By default use this as the saves path
+ _usingScummVMSavesDir = new File(defaultScummVMSavesPath.getPath());
+
+ if (defaultScummVMSavesPath.exists() && defaultScummVMSavesPath.isDirectory()) {
+ try {
+ Log.d(ScummVM.LOG_TAG, "ScummVM default saves path already exists: " + defaultScummVMSavesPath.getPath());
+ } catch (Exception e) {
+ Log.d(ScummVM.LOG_TAG, "ScummVM default saves path exception CAUGHT!");
+ }
+ } else if (!defaultScummVMSavesPath.exists() && defaultScummVMSavesPath.mkdirs()) {
+ Log.d(ScummVM.LOG_TAG, "Created ScummVM default saves path: " + defaultScummVMSavesPath.getPath());
} else {
- Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM saves path: " + _defaultScummVMSavesDir.getPath());
+ Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM default saves path: " + defaultScummVMSavesPath.getPath());
new AlertDialog.Builder(this)
- .setTitle(R.string.no_config_file_title)
+ .setTitle(R.string.no_save_path_title)
.setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.no_config_file)
+ .setMessage(R.string.no_save_path_configured)
.setNegativeButton(R.string.quit,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
@@ -806,6 +918,172 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return false;
}
+ File[] defaultSaveDirFiles = defaultScummVMSavesPath.listFiles();
+ if (defaultSaveDirFiles != null) {
+ Log.d(ScummVM.LOG_TAG, "Size: "+ defaultSaveDirFiles.length);
+
+ if (defaultSaveDirFiles.length > 0 ) {
+ Log.d(ScummVM.LOG_TAG, "Listing ScummVM save files in default saves path...");
+ for (File savfile : defaultSaveDirFiles) {
+ smallNodeDesc = "(F)";
+ if (savfile.isDirectory()) {
+ smallNodeDesc = "(D)";
+ }
+ Log.d(ScummVM.LOG_TAG, "Name: " + smallNodeDesc + " " + savfile.getName());
+ }
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Default ScummVM save path is empty. Scanning for a previous usable one...");
+ // Note: A directory named "Saves" is NOT the same as "saves" in internal storage.
+ // ie. paths and filenames in internal storage (including emulated external) are case sensitive!
+ // BUT: It could be the same in external SD card or other FAT formatted storage
+ //
+ // TODO add code here for creating a dummy place holder file in order to not repeat the process?
+
+ File candidateOldScummVMSavesPath = null;
+ int maxSavesFolderFoundSize = 0;
+
+ LinkedHashMap<String, File> candidateOldLocationsOfScummVMSavesMap = new LinkedHashMap<>();
+
+ // TODO some of these entries are an overkill, but better safe than sorry
+
+ // due to case sensitivity this is different than "saves"
+ candidateOldLocationsOfScummVMSavesMap.put("A01", new File(_actualScummVMDataDir, "Saves"));
+ // This is a potential one, when internal storage for app was used
+ candidateOldLocationsOfScummVMSavesMap.put("A02", new File(_actualScummVMDataDir, ".local/share/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A03", new File(_actualScummVMDataDir, ".local/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A04", new File(_actualScummVMDataDir, "scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A05", new File(_actualScummVMDataDir, "../.local/share/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A06", new File(_actualScummVMDataDir, "../.local/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A07", new File(_actualScummVMDataDir, "../saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A08", new File(_actualScummVMDataDir, "../scummvm/saves"));
+ // this is a popular one
+ candidateOldLocationsOfScummVMSavesMap.put("A09", new File(externalPossibleAlternateScummVMFilesDir, ".local/share/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A10", new File(externalPossibleAlternateScummVMFilesDir, ".local/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A11", new File(externalPossibleAlternateScummVMFilesDir, "saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A12", new File(externalPossibleAlternateScummVMFilesDir, "scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A13", new File(externalPossibleAlternateScummVMFilesDir, "../.local/share/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A14", new File(externalPossibleAlternateScummVMFilesDir, "../.local/scummvm/saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A15", new File(externalPossibleAlternateScummVMFilesDir, "../saves"));
+ candidateOldLocationsOfScummVMSavesMap.put("A16", new File(externalPossibleAlternateScummVMFilesDir, "../scummvm/saves"));
+ // this was for old Android plain port
+ candidateOldLocationsOfScummVMSavesMap.put("A17", new File(Environment.getExternalStorageDirectory(), "ScummVM/Saves"));
+
+ for (String oldSavesPathDescription : candidateOldLocationsOfScummVMSavesMap.keySet()) {
+ File iterCandidateScummVMSavesPath = candidateOldLocationsOfScummVMSavesMap.get(oldSavesPathDescription);
+ Log.d(ScummVM.LOG_TAG, "Looking for old saves path " + oldSavesPathDescription + "...");
+ try {
+ Log.d(ScummVM.LOG_TAG, " at Path: " + iterCandidateScummVMSavesPath.getPath());
+ if (iterCandidateScummVMSavesPath.exists() && iterCandidateScummVMSavesPath.isDirectory()) {
+ File[] sgfiles = iterCandidateScummVMSavesPath.listFiles();
+ if (sgfiles != null) {
+ Log.d(ScummVM.LOG_TAG, "Size: " + sgfiles.length);
+ for (File sgfile : sgfiles) {
+ smallNodeDesc = "(F)";
+ if (sgfile.isDirectory()) {
+ smallNodeDesc = "(D)";
+ }
+ Log.d(ScummVM.LOG_TAG, "Name: " + smallNodeDesc + " " + sgfile.getName());
+ }
+
+ if (sgfiles.length > maxSavesFolderFoundSize) {
+ maxSavesFolderFoundSize = sgfiles.length;
+ candidateOldScummVMSavesPath = iterCandidateScummVMSavesPath;
+ }
+ }
+ } else {
+ Log.d(ScummVM.LOG_TAG, "...not found.");
+ }
+ } catch (Exception e) {
+ Log.d(ScummVM.LOG_TAG, "ScummVM Saves path exception CAUGHT!");
+ }
+ }
+
+ if (candidateOldScummVMSavesPath != null) {
+ //
+ Log.d(ScummVM.LOG_TAG, "Copying files from old saves folder: " + candidateOldScummVMSavesPath.getPath() + " to: " + defaultScummVMSavesPath.getPath());
+ File[] sgfiles = candidateOldScummVMSavesPath.listFiles();
+ if (sgfiles != null) {
+ for (File sgfile : sgfiles) {
+ String filename = sgfile.getName();
+ if (!sgfile.isDirectory()) {
+ Log.d(ScummVM.LOG_TAG, "Copying: " + filename);
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ in = new FileInputStream(sgfile);
+ File outFile = new File(defaultScummVMSavesPath, filename);
+ out = new FileOutputStream(outFile);
+ copyStreamToStream(in, out);
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to copy save file: " + filename);
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ }
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Not copying directory: " + filename);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ File persistentGlobalSavePath = null;
+ if (_configScummvmFile.exists() && _configScummvmFile.isFile()) {
+ Log.d(ScummVM.LOG_TAG, "Looking into config file for save path: " + _configScummvmFile.getPath());
+ String persistentGlobalSavePathStr = getSavepathInfoFromScummvmConfiguration(_configScummvmFile.getPath());
+ if (!"".equals(persistentGlobalSavePathStr.trim())) {
+ Log.d(ScummVM.LOG_TAG, "Found explicit save path: " + persistentGlobalSavePathStr);
+ persistentGlobalSavePath = new File(persistentGlobalSavePathStr);
+ if (persistentGlobalSavePath.exists() && persistentGlobalSavePath.isDirectory() && persistentGlobalSavePath.listFiles() != null) {
+ try {
+ Log.d(ScummVM.LOG_TAG, "ScummVM explicit saves path folder exists and it is list-able");
+ } catch (Exception e) {
+ persistentGlobalSavePath = null;
+ Log.e(ScummVM.LOG_TAG, "ScummVM explicit saves path exception CAUGHT!");
+ }
+ } else {
+ // We won't bother creating it, it's not in our scope to do that (and it would probably result in potential permission issues)
+ Log.e(ScummVM.LOG_TAG, "Could not access explicit save folder for ScummVM: " + persistentGlobalSavePath.getPath());
+ persistentGlobalSavePath = null;
+ // We should *not* quit or return here,
+ // TODO But, how do we override this explicit set path? Do we leave it to the user to reset it?
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.no_save_path_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.bad_explicit_save_path_configured)
+ .setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+
+ }
+ })
+ .show();
+ }
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Could not find explicit save path info in ScummVM's config file");
+ }
+ }
+
+ if (persistentGlobalSavePath != null) {
+ // Use the persistent savepath
+ _usingScummVMSavesDir = new File(persistentGlobalSavePath.getPath());
+ }
+ Log.d(ScummVM.LOG_TAG, "Resulting save path is: " + _usingScummVMSavesDir.getPath());
+
return true;
}
diff --git a/dists/android/res/values/strings.xml b/dists/android/res/values/strings.xml
index 830a30fe13..3c8ba8f966 100644
--- a/dists/android/res/values/strings.xml
+++ b/dists/android/res/values/strings.xml
@@ -1,30 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="app_name">ScummVM</string>
- <string name="app_desc">Graphic adventure game engine</string>
- <string name="quit">Quit</string>
- <string name="scummvm_perm_plugin_label">ScummVM plugin</string>
- <string name="scummvm_perm_plugin_desc">Allows the application to
- provide a ScummVM loadable plugin: code that will be executed in the
- ScummVM application. Malicious plugins may do anything ScummVM
- itself could do: write to your SD card, delete your savegames,
- change the ScummVM background to puce, replace menu labels with rude
- words, etc.</string>
- <string name="no_sdcard_title">No SD card?</string>
- <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
- packages, from wherever you found ScummVM.</string>
- <string name="to_market">To Market</string>
+ <string name="app_name">ScummVM</string>
+ <string name="app_desc">Graphic adventure game engine</string>
+ <string name="ok">Ok</string>
+ <string name="quit">Quit</string>
+ <string name="scummvm_perm_plugin_label">ScummVM plugin</string>
+ <string name="scummvm_perm_plugin_desc">Allows the application to
+ provide a ScummVM loadable plugin: code that will be executed in the
+ ScummVM application. Malicious plugins may do anything ScummVM
+ itself could do: write to your SD card, delete your savegames,
+ change the ScummVM background to puce, replace menu labels with rude
+ words, etc.</string>
+ <string name="no_sdcard_title">No SD card?</string>
+ <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_log_file_title">Log File Error</string>
+ <string name="no_log_file">Unable to read ScummVM log file or create a new one!</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="bad_explicit_save_path_configured">Unable to access the globally set save path! Please revert to default from ScummVM Options</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
+ packages, from wherever you found ScummVM.</string>
+ <string name="to_market">To Market</string>
</resources>
Commit: b15b394f0c6629d80349622f0024fd11d824cb78
https://github.com/scummvm/scummvm/commit/b15b394f0c6629d80349622f0024fd11d824cb78
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:18:09+03:00
Commit Message:
ANDROID: Comment out the logfile code
Since currently the logFile stuff are specific to SDL_BACKED
Changed paths:
backends/platform/android/android.h
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 050efd804e..c5c887e163 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -129,8 +129,7 @@ public:
virtual Audio::Mixer *getMixer();
virtual void getTimeAndDate(TimeDate &t) const;
virtual void logMessage(LogMessageType::Type type, const char *message);
- virtual void addSysArchivesToSearchSet(Common::SearchSet &s,
- int priority = 0);
+ virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
virtual bool openUrl(const Common::String &url);
virtual bool hasTextInClipboard();
virtual Common::String getTextFromClipboard();
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 19ed5160eb..a7ce50bd56 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -64,7 +64,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private File _configScummvmFile;
private File _actualScummVMDataDir;
private File _usingScummVMSavesDir;
- private File _usingLogFile;
+// private File _usingLogFile;
/**
@@ -272,6 +272,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// Log.d(ScummVM.LOG_TAG, "SAVEPATH: " + _usingScummVMSavesDir.getPath());
// TODO log file setting via "--logfile=" + _usingLogFile.getPath() causes crash
+ // probably because this option is specific to SDL_BACKEND (see: base/commandLine.cpp)
_scummvm.setArgs(new String[]{
"ScummVM",
"--config=" + _configScummvmFile.getPath(),
@@ -679,51 +680,51 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
}
- File internalScummVMLogsDir = new File(_actualScummVMDataDir, ".cache/scummvm/logs");
- if (!internalScummVMLogsDir.exists() && internalScummVMLogsDir.mkdirs()) {
- Log.d(ScummVM.LOG_TAG, "Created ScummVM Logs path: " + internalScummVMLogsDir.getPath());
- } else if (internalScummVMLogsDir.isDirectory()) {
- Log.d(ScummVM.LOG_TAG, "ScummVM Logs path already exists: " + internalScummVMLogsDir.getPath());
- } else {
- Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM Logs path: " + internalScummVMLogsDir.getPath());
- new AlertDialog.Builder(this)
- .setTitle(R.string.no_log_file_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.no_log_file)
- .setNegativeButton(R.string.quit,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- })
- .show();
- return false;
- }
-
- _usingLogFile = new File(internalScummVMLogsDir, "scummvm.log");
- try {
- if (_usingLogFile.exists() || !_usingLogFile.createNewFile()) {
- Log.d(ScummVM.LOG_TAG, "ScummVM Log file already exists!");
- Log.d(ScummVM.LOG_TAG, "Existing ScummVM Log: " + _usingLogFile.getPath());
- } else {
- Log.d(ScummVM.LOG_TAG, "An empty ScummVM log file was created!");
- Log.d(ScummVM.LOG_TAG, "New ScummVM Log: " + _usingLogFile.getPath());
- }
- } catch (Exception e) {
- e.printStackTrace();
- new AlertDialog.Builder(this)
- .setTitle(R.string.no_log_file_title)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(R.string.no_log_file)
- .setNegativeButton(R.string.quit,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- finish();
- }
- })
- .show();
- return false;
- }
+// File internalScummVMLogsDir = new File(_actualScummVMDataDir, ".cache/scummvm/logs");
+// if (!internalScummVMLogsDir.exists() && internalScummVMLogsDir.mkdirs()) {
+// Log.d(ScummVM.LOG_TAG, "Created ScummVM Logs path: " + internalScummVMLogsDir.getPath());
+// } else if (internalScummVMLogsDir.isDirectory()) {
+// Log.d(ScummVM.LOG_TAG, "ScummVM Logs path already exists: " + internalScummVMLogsDir.getPath());
+// } else {
+// Log.e(ScummVM.LOG_TAG, "Could not create folder for ScummVM Logs path: " + internalScummVMLogsDir.getPath());
+// new AlertDialog.Builder(this)
+// .setTitle(R.string.no_log_file_title)
+// .setIcon(android.R.drawable.ic_dialog_alert)
+// .setMessage(R.string.no_log_file)
+// .setNegativeButton(R.string.quit,
+// new DialogInterface.OnClickListener() {
+// public void onClick(DialogInterface dialog, int which) {
+// finish();
+// }
+// })
+// .show();
+// return false;
+// }
+//
+// _usingLogFile = new File(internalScummVMLogsDir, "scummvm.log");
+// try {
+// if (_usingLogFile.exists() || !_usingLogFile.createNewFile()) {
+// Log.d(ScummVM.LOG_TAG, "ScummVM Log file already exists!");
+// Log.d(ScummVM.LOG_TAG, "Existing ScummVM Log: " + _usingLogFile.getPath());
+// } else {
+// Log.d(ScummVM.LOG_TAG, "An empty ScummVM log file was created!");
+// Log.d(ScummVM.LOG_TAG, "New ScummVM Log: " + _usingLogFile.getPath());
+// }
+// } catch (Exception e) {
+// e.printStackTrace();
+// new AlertDialog.Builder(this)
+// .setTitle(R.string.no_log_file_title)
+// .setIcon(android.R.drawable.ic_dialog_alert)
+// .setMessage(R.string.no_log_file)
+// .setNegativeButton(R.string.quit,
+// new DialogInterface.OnClickListener() {
+// public void onClick(DialogInterface dialog, int which) {
+// finish();
+// }
+// })
+// .show();
+// return false;
+// }
File internalScummVMConfigDir = new File(_actualScummVMDataDir, ".config/scummvm");
if (!internalScummVMConfigDir.exists() && internalScummVMConfigDir.mkdirs()) {
Commit: 7a6776f121a22ff3332be256a85b90b85f77aebb
https://github.com/scummvm/scummvm/commit/7a6776f121a22ff3332be256a85b90b85f77aebb
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:38:41+03:00
Commit Message:
ANDROID: Set new version code(s) for 2.3.0
Changed paths:
dists/android/build.gradle
diff --git a/dists/android/build.gradle b/dists/android/build.gradle
index ffb7ebbbea..df23b1695a 100644
--- a/dists/android/build.gradle
+++ b/dists/android/build.gradle
@@ -35,11 +35,12 @@ android {
minSdkVersion 16
targetSdkVersion 28
- versionName "2.2.0git"
- versionCode 45
+ versionName "2.3.0git"
+ versionCode 49
// versioncode must be incremented for each market upload
- // ScummVM 2.2.2: 45-48 (arm-v7a, arm64-v8a, x86, x86_64 respectively -- armeabi was dropped)
+ // ScummVM 2.3.0: 49-52 (arm-v7a, arm64-v8a, x86, x86_64 respectively)
// Historical version codes:
+ // ScummVM 2.2.0: 45-48 (arm-v7a, arm64-v8a, x86, x86_64 respectively -- armeabi was dropped)
// ScummVM 2.1.1: 40-44 (armeabi, arm-v7a, arm64-v8a, x86, x86_64 respectively)
// ScummVM 2.1.0: 35-39 (armeabi, arm-v7a, arm64-v8a, x86, x86_64 respectively)
// ScummVM 2.0.0: 30-34
Commit: 9d18d03dce0f52abb67ddf4f982378a69caf9053
https://github.com/scummvm/scummvm/commit/9d18d03dce0f52abb67ddf4f982378a69caf9053
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-24T14:38:43+03:00
Commit Message:
ANDROID: Account for possible v2.2.1 in build.gradle
Changed paths:
dists/android/build.gradle
diff --git a/dists/android/build.gradle b/dists/android/build.gradle
index df23b1695a..b27a3e38ef 100644
--- a/dists/android/build.gradle
+++ b/dists/android/build.gradle
@@ -36,10 +36,11 @@ android {
targetSdkVersion 28
versionName "2.3.0git"
- versionCode 49
+ versionCode 53
// versioncode must be incremented for each market upload
- // ScummVM 2.3.0: 49-52 (arm-v7a, arm64-v8a, x86, x86_64 respectively)
+ // ScummVM 2.3.0: 53-56 (arm-v7a, arm64-v8a, x86, x86_64 respectively)
// Historical version codes:
+ // ScummVM 2.2.1: 49-52 (arm-v7a, arm64-v8a, x86, x86_64 respectively)
// ScummVM 2.2.0: 45-48 (arm-v7a, arm64-v8a, x86, x86_64 respectively -- armeabi was dropped)
// ScummVM 2.1.1: 40-44 (armeabi, arm-v7a, arm64-v8a, x86, x86_64 respectively)
// ScummVM 2.1.0: 35-39 (armeabi, arm-v7a, arm64-v8a, x86, x86_64 respectively)
More information about the Scummvm-git-logs
mailing list