Skip to content

Commit

Permalink
Fix[storage]: better ensure mounted storage
Browse files Browse the repository at this point in the history
Avoids several crashes caused by Pojav running on devices without always-mounted external storage.
  • Loading branch information
artdeell committed Jan 15, 2025
1 parent e6ccde2 commit f446e11
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ public void startActivity(Intent i) {
@Override
protected void onResume() {
super.onResume();
if(!Tools.checkStorageRoot(this)) {
startActivity(new Intent(this, MissingStorageActivity.class));
finish();
}
Tools.checkStorageInteractive(this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ public class ImportControlActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Tools.initContextConstants(getApplicationContext());
if(Tools.checkStorageInteractive(this)) {
Tools.initStorageConstants(getApplicationContext());
}else {
// Return early, no initialization needed.
return;
}

setContentView(R.layout.activity_import_control);
mEditText = findViewById(R.id.editText_import_control_file_name);
Expand All @@ -61,6 +66,12 @@ protected void onNewIntent(Intent intent) {
@Override
protected void onPostResume() {
super.onPostResume();
if(!Tools.checkStorageInteractive(this)) {
// Don't try to read the file as when this check fails, external storage paths
// are no longer valid (likely unmounted).
// checkStorageInteractive() will finish this activity for us.
return;
}
if(!mHasIntentChanged) return;
mIsFileVerified = false;
getUriData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if (requestCode == 1 && resultCode == Activity.RESULT_OK) {
// Reload PREF_DEFAULTCTRL_PATH
// If the storage root got unmounted/unreadable we won't be able to load the file anyway,
// and MissingStorageActivity will be started.
if(!Tools.checkStorageRoot(this)) return;
LauncherPreferences.loadPreferences(getApplicationContext());
try {
mControlLayout.loadLayout(LauncherPreferences.PREF_DEFAULTCTRL_PATH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ public void onCreate() {

try {
super.onCreate();

Tools.DIR_DATA = getDir("files", MODE_PRIVATE).getParent();
Tools.DIR_CACHE = getCacheDir();
Tools.DIR_ACCOUNT_NEW = Tools.DIR_DATA + "/accounts";
Tools.initEarlyConstants(this);
Tools.DEVICE_ARCHITECTURE = Architecture.getDeviceArchitecture();
//Force x86 lib directory for Asus x86 based zenfones
if(Architecture.isx86Device() && Architecture.is32BitsDevice()){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ private void exit() {
startActivity(new Intent(this, MissingStorageActivity.class));
return;
}
//Only run them once we get a definitive green light to use storage
//Initialize constants after we confirm that we have storage.
Tools.initStorageConstants(getApplicationContext());
AsyncAssetManager.unpackComponents(this);
AsyncAssetManager.unpackSingleFiles(this);

Expand Down
40 changes: 33 additions & 7 deletions app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
import android.util.ArrayMap;
Expand Down Expand Up @@ -164,14 +163,42 @@ public static boolean checkStorageRoot(Context context) {
}

/**
* Since some constant requires the use of the Context object
* You can call this function to initialize them.
* Any value (in)directly dependant on DIR_DATA should be set only here.
* Checks if the Pojav's storage root is accessible and read-writable. If it's not, starts
* the MissingStorageActivity and finishes the supplied activity.
* @param context the Activity that checks for storage availability
* @return whether the storage is available or not.
*/
public static void initContextConstants(Context ctx){
public static boolean checkStorageInteractive(Activity context) {
if(!Tools.checkStorageRoot(context)) {
context.startActivity(new Intent(context, MissingStorageActivity.class));
context.finish();
return false;
}
return true;
}

/**
* Initialize context constants most necessary for launcher's early startup phase
* that are not dependent on user storage.
* All values that depend on DIR_DATA and are not dependent on DIR_GAME_HOME must
* be initialized here.
* @param ctx the context for initialization.
*/
public static void initEarlyConstants(Context ctx) {
DIR_CACHE = ctx.getCacheDir();
DIR_DATA = ctx.getFilesDir().getParent();
MULTIRT_HOME = DIR_DATA+"/runtimes";
MULTIRT_HOME = DIR_DATA + "/runtimes";
DIR_ACCOUNT_NEW = DIR_DATA + "/accounts";
NATIVE_LIB_DIR = ctx.getApplicationInfo().nativeLibraryDir;
}

/**
* Initialize context constants that depend on user storage.
* Any value (in)directly dependent on DIR_GAME_HOME should be set only here.
* You ABSOLUTELY MUST check for storage presence using checkStorageRoot() before calling this.
*/
public static void initStorageConstants(Context ctx){
initEarlyConstants(ctx);
DIR_GAME_HOME = getPojavStorageRoot(ctx).getAbsolutePath();
DIR_GAME_NEW = DIR_GAME_HOME + "/.minecraft";
DIR_HOME_VERSION = DIR_GAME_NEW + "/versions";
Expand All @@ -181,7 +208,6 @@ public static void initContextConstants(Context ctx){
OBSOLETE_RESOURCES_PATH = DIR_GAME_NEW + "/resources";
CTRLMAP_PATH = DIR_GAME_HOME + "/controlmap";
CTRLDEF_FILE = DIR_GAME_HOME + "/controlmap/default.json";
NATIVE_LIB_DIR = ctx.getApplicationInfo().nativeLibraryDir;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ public class LauncherPreferences {


public static void loadPreferences(Context ctx) {
//Required for the data folder.
Tools.initContextConstants(ctx);
//Required for CTRLDEF_FILE and MultiRT
Tools.initStorageConstants(ctx);
boolean isDevicePowerful = isDevicePowerful(ctx);

PREF_RENDERER = DEFAULT_PREF.getString("renderer", "opengles2");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

import androidx.preference.*;
import java.util.*;
import net.kdt.pojavlaunch.prefs.*;

public class LocaleUtils extends ContextWrapper {

Expand All @@ -22,7 +21,10 @@ public LocaleUtils(Context base) {
public static ContextWrapper setLocale(Context context) {
if (DEFAULT_PREF == null) {
DEFAULT_PREF = PreferenceManager.getDefaultSharedPreferences(context);
LauncherPreferences.loadPreferences(context);
// Too early to initialize all prefs here, as this is called by PojavApplication
// before storage checks are done and before the storage paths are initialized.
// So only initialize PREF_FORCE_ENGLISH for the check below.
PREF_FORCE_ENGLISH = DEFAULT_PREF.getBoolean("force_english", false);
}

if(PREF_FORCE_ENGLISH){
Expand Down

0 comments on commit f446e11

Please sign in to comment.