diff --git a/app_pojavlauncher/src/main/AndroidManifest.xml b/app_pojavlauncher/src/main/AndroidManifest.xml index 8822a610c..8afb1be0c 100644 --- a/app_pojavlauncher/src/main/AndroidManifest.xml +++ b/app_pojavlauncher/src/main/AndroidManifest.xml @@ -3,101 +3,106 @@ xmlns:tools="http://schemas.android.com/tools" package="net.kdt.pojavlaunch"> - - - - - + + + + + + - + + android:roundIcon="@mipmap/ic_launcher_round" + android:theme="@style/AppTheme"> + - + android:value="ratio_float" /> - + android:label="@string/app_short_name" + android:launchMode="singleTop"> + - - - + android:name=".LauncherActivity" + android:label="@string/app_short_name" /> - - + - - - - - - + + + + + + + + - + android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation" + android:theme="@style/Theme.AppCompat.DayNight.Dialog" /> - + android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation" + android:theme="@style/Theme.AppCompat.DayNight.Dialog" /> - + android:configChanges="keyboardHidden|orientation|screenSize|keyboard|navigation" + android:screenOrientation="sensorLandscape" /> + android:exported="true" + android:screenOrientation="sensorLandscape"> + - + android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|keyboard|navigation|uiMode" + android:launchMode="standard" + android:process=":game" + android:screenOrientation="sensorLandscape" /> - - - + + - + \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java index 248fa7b34..98e5ab932 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/BaseActivity.java @@ -34,6 +34,15 @@ public abstract class BaseActivity extends AppCompatActivity { //new Throwable("StartActivity").printStackTrace(); } + @Override + protected void onResume() { + super.onResume(); + if(!Tools.checkStorageRoot(this)) { + startActivity(new Intent(this, MissingStorageActivity.class)); + finish(); + } + } + @Override protected void onPostResume() { super.onPostResume(); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java index 77702d4c4..57c7e0e53 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/ImportControlActivity.java @@ -67,6 +67,10 @@ public class ImportControlActivity extends Activity { if(!mHasIntentChanged) return; mIsFileVerified = false; getUriData(); + if(mUriData == null) { + finishAndRemoveTask(); + return; + } mEditText.setText(getNameFromURI(mUriData)); mHasIntentChanged = false; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MissingStorageActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MissingStorageActivity.java new file mode 100644 index 000000000..f5e48c3c9 --- /dev/null +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/MissingStorageActivity.java @@ -0,0 +1,13 @@ +package net.kdt.pojavlaunch; + +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; + +public class MissingStorageActivity extends AppCompatActivity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.storage_test_no_sdcard); + } +} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java index a4860caef..1548bcf23 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/PojavApplication.java @@ -28,8 +28,8 @@ public class PojavApplication extends Application { @Override public void onCreate() { Thread.setDefaultUncaughtExceptionHandler((thread, th) -> { - boolean storagePermAllowed = Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 29 || - ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; + boolean storagePermAllowed = (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 29 || + ActivityCompat.checkSelfPermission(PojavApplication.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) && Tools.checkStorageRoot(PojavApplication.this); File crashFile = new File(storagePermAllowed ? Tools.DIR_GAME_HOME : Tools.DIR_DATA, "latestcrash.txt"); try { // Write to file, since some devices may not able to show error diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TestStorageActivity.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TestStorageActivity.java index a95297916..1d413d54a 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TestStorageActivity.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/TestStorageActivity.java @@ -56,6 +56,10 @@ public class TestStorageActivity extends Activity { } private void exit() { + if(!Tools.checkStorageRoot(this)) { + startActivity(new Intent(this, MissingStorageActivity.class)); + return; + } //Only run them once we get a definitive green light to use storage AsyncAssetManager.unpackComponents(this); AsyncAssetManager.unpackSingleFiles(this); diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java index e3d054cc3..74417dd03 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java @@ -86,6 +86,26 @@ public final class Tools { public static final String LIBNAME_OPTIFINE = "optifine:OptiFine"; public static final int RUN_MOD_INSTALLER = 2050; + + private static File getPojavStorageRoot(Context ctx) { + if(SDK_INT >= 29) { + return ctx.getExternalFilesDir(null); + }else{ + return new File(Environment.getExternalStorageDirectory(),"games/PojavLauncher"); + } + } + + /** + * Checks if the Pojav's storage root is accessible and read-writable + * @param context context to get the storage root if it's not set yet + * @return true if storage is fine, false if storage is not accessible + */ + public static boolean checkStorageRoot(Context context) { + File externalFilesDir = DIR_GAME_HOME == null ? Tools.getPojavStorageRoot(context) : new File(DIR_GAME_HOME); + //externalFilesDir == null when the storage is not mounted if it was obtained with the context call + return externalFilesDir != null && Environment.getExternalStorageState(externalFilesDir).equals(Environment.MEDIA_MOUNTED); + } + /** * Since some constant requires the use of the Context object * You can call this function to initialize them. @@ -94,11 +114,7 @@ public final class Tools { public static void initContextConstants(Context ctx){ DIR_DATA = ctx.getFilesDir().getParent(); MULTIRT_HOME = DIR_DATA+"/runtimes"; - if(SDK_INT >= 29) { - DIR_GAME_HOME = ctx.getExternalFilesDir(null).getAbsolutePath(); - }else{ - DIR_GAME_HOME = new File(Environment.getExternalStorageDirectory(),"games/PojavLauncher").getAbsolutePath(); - } + DIR_GAME_HOME = getPojavStorageRoot(ctx).getAbsolutePath(); DIR_GAME_NEW = DIR_GAME_HOME + "/.minecraft"; DIR_HOME_VERSION = DIR_GAME_NEW + "/versions"; DIR_HOME_LIBRARY = DIR_GAME_NEW + "/libraries"; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java index d81f0bc82..897a8c171 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/multirt/MultiRTUtils.java @@ -161,7 +161,7 @@ public class MultiRTUtils { public static Runtime read(String name) { if(sCache.containsKey(name)) return sCache.get(name); Runtime returnRuntime; - File release = new File(RUNTIME_FOLDER,"/"+name+"/release"); + File release = new File(RUNTIME_FOLDER,name+"/release"); if(!release.exists()) { return new Runtime(name); } diff --git a/app_pojavlauncher/src/main/res/drawable/storage_alert.xml b/app_pojavlauncher/src/main/res/drawable/storage_alert.xml new file mode 100644 index 000000000..3b5f2d80d --- /dev/null +++ b/app_pojavlauncher/src/main/res/drawable/storage_alert.xml @@ -0,0 +1,5 @@ + + + diff --git a/app_pojavlauncher/src/main/res/layout/storage_test_no_sdcard.xml b/app_pojavlauncher/src/main/res/layout/storage_test_no_sdcard.xml new file mode 100644 index 000000000..0c62f6881 --- /dev/null +++ b/app_pojavlauncher/src/main/res/layout/storage_test_no_sdcard.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app_pojavlauncher/src/main/res/values/strings.xml b/app_pojavlauncher/src/main/res/values/strings.xml index 035f46c25..be4953d12 100644 --- a/app_pojavlauncher/src/main/res/values/strings.xml +++ b/app_pojavlauncher/src/main/res/values/strings.xml @@ -52,7 +52,7 @@ News Development console Crash log - + Connected Local @@ -171,13 +171,13 @@ File is being verified, please wait and try again… Invalid name or file already exists Importation done - Editing %s Remove %s? - + Keycode Toggleable Size @@ -190,7 +190,7 @@ Corner radius Stroke width Stroke color - + Manual Dynamic position Dynamic X Dynamic Y @@ -349,4 +349,5 @@ Gyroscope sampling rate If you have performance issues with the gyroscope controls, increase this Too many requests, please try again later. + PojavLauncher requires an attached external storage. Please reconnect your storage and restart the app. diff --git a/app_pojavlauncher/src/main/res/xml/pref_control.xml b/app_pojavlauncher/src/main/res/xml/pref_control.xml index 5f0ec9eb2..96c30bbab 100644 --- a/app_pojavlauncher/src/main/res/xml/pref_control.xml +++ b/app_pojavlauncher/src/main/res/xml/pref_control.xml @@ -10,7 +10,7 @@ android:summary="@string/preference_edit_controls_summary" app2:icon="@drawable/ic_menu_custom_controls" > - +