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