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"
>
-
+