diff --git a/forge-adventure/pom.xml b/forge-adventure/pom.xml
index 9677ab11dc4..e460df493c5 100644
--- a/forge-adventure/pom.xml
+++ b/forge-adventure/pom.xml
@@ -12,8 +12,11 @@
Forge Adventure
- gdx-nightlies
- https://oss.sonatype.org/content/repositories/snapshots/
+ 4thline-repo
+ http://4thline.org/m2
+
+ false
+
jitpack.io
@@ -29,6 +32,7 @@
**/*.vert
**/*.frag
**/title_bg_lq.png
+ **/title_bg_lq_portrait.png
**/transition.png
**/adv_bg_texture.jpg
**/adv_bg_splash.png
@@ -231,36 +235,36 @@
com.badlogicgames.gdx
gdx
- 1.11.0
+ 1.12.1
compile
com.badlogicgames.gdx
gdx-platform
- 1.11.0
+ 1.12.1
natives-desktop
com.badlogicgames.gdx
gdx-freetype
- 1.11.0
+ 1.12.1
com.badlogicgames.gdx
gdx-backend-lwjgl
- 1.11.0
+ 1.12.1
compile
com.badlogicgames.gdx
gdx-tools
- 1.11.0
+ 1.12.1
compile
com.badlogicgames.gdx
gdx-freetype-platform
- 1.11.0
+ 1.12.1
natives-desktop
@@ -287,7 +291,13 @@
com.badlogicgames.gdx-controllers
gdx-controllers-desktop
- 2.2.3-SNAPSHOT
+ 2.2.3
+
+
+ com.badlogicgames.gdx
+ gdx
+
+
diff --git a/forge-core/pom.xml b/forge-core/pom.xml
index a9bfc658a86..14c1dcef60f 100644
--- a/forge-core/pom.xml
+++ b/forge-core/pom.xml
@@ -16,7 +16,7 @@
com.google.guava
guava
- 32.0.0-android
+ 33.2.1-android
org.apache.commons
diff --git a/forge-gui-android/AndroidManifest.xml b/forge-gui-android/AndroidManifest.xml
index 3e10e483e4e..2e6e5308476 100644
--- a/forge-gui-android/AndroidManifest.xml
+++ b/forge-gui-android/AndroidManifest.xml
@@ -5,10 +5,11 @@
android:versionName="1.6.64" >
+ android:minSdkVersion="26"
+ android:targetSdkVersion="28" />
+
@@ -24,17 +25,9 @@
android:label="@string/app_name"
android:largeHeap="true">
-
-
+ android:name=".Launcher"
+ android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
+ android:theme="@style/Theme.Transparent">
@@ -45,8 +38,26 @@
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/forge-gui-android/filters/build.txt b/forge-gui-android/filters/build.txt
new file mode 100644
index 00000000000..aca99ef22d7
--- /dev/null
+++ b/forge-gui-android/filters/build.txt
@@ -0,0 +1 @@
+${timestamp}
\ No newline at end of file
diff --git a/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so b/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so
index e562acc0b86..f3a8a41cdcc 100644
Binary files a/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so and b/forge-gui-android/libs/arm64-v8a/libgdx-box2d.so differ
diff --git a/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so b/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so
index df49aac07f3..9f7e218abc9 100644
Binary files a/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so and b/forge-gui-android/libs/arm64-v8a/libgdx-freetype.so differ
diff --git a/forge-gui-android/libs/arm64-v8a/libgdx.so b/forge-gui-android/libs/arm64-v8a/libgdx.so
index 74e129d29f2..ffb154277e7 100644
Binary files a/forge-gui-android/libs/arm64-v8a/libgdx.so and b/forge-gui-android/libs/arm64-v8a/libgdx.so differ
diff --git a/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so b/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so
index eef089879ed..00700e9d50c 100644
Binary files a/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so and b/forge-gui-android/libs/armeabi-v7a/libgdx-box2d.so differ
diff --git a/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so b/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so
index 922f56bccea..6ceab900ad0 100644
Binary files a/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so and b/forge-gui-android/libs/armeabi-v7a/libgdx-freetype.so differ
diff --git a/forge-gui-android/libs/armeabi-v7a/libgdx.so b/forge-gui-android/libs/armeabi-v7a/libgdx.so
index 83c72a3395f..7192dc626f0 100644
Binary files a/forge-gui-android/libs/armeabi-v7a/libgdx.so and b/forge-gui-android/libs/armeabi-v7a/libgdx.so differ
diff --git a/forge-gui-android/libs/gdx-backend-android-sources.jar b/forge-gui-android/libs/gdx-backend-android-sources.jar
index c44e7889e7d..524836a1f35 100644
Binary files a/forge-gui-android/libs/gdx-backend-android-sources.jar and b/forge-gui-android/libs/gdx-backend-android-sources.jar differ
diff --git a/forge-gui-android/libs/gdx-backend-android.jar b/forge-gui-android/libs/gdx-backend-android.jar
index 528dde1cfe6..f67fc316ccd 100644
Binary files a/forge-gui-android/libs/gdx-backend-android.jar and b/forge-gui-android/libs/gdx-backend-android.jar differ
diff --git a/forge-gui-android/libs/gdx-freetype.jar b/forge-gui-android/libs/gdx-freetype.jar
index b0c5060437f..7882e998dda 100644
Binary files a/forge-gui-android/libs/gdx-freetype.jar and b/forge-gui-android/libs/gdx-freetype.jar differ
diff --git a/forge-gui-android/libs/gdx-sources.jar b/forge-gui-android/libs/gdx-sources.jar
index 22d94b50342..85793e30966 100644
Binary files a/forge-gui-android/libs/gdx-sources.jar and b/forge-gui-android/libs/gdx-sources.jar differ
diff --git a/forge-gui-android/libs/gdx.jar b/forge-gui-android/libs/gdx.jar
index 1a0381b8566..cca18342888 100644
Binary files a/forge-gui-android/libs/gdx.jar and b/forge-gui-android/libs/gdx.jar differ
diff --git a/forge-gui-android/libs/publicfileprovider.jar b/forge-gui-android/libs/publicfileprovider.jar
new file mode 100644
index 00000000000..6ede1654e9b
Binary files /dev/null and b/forge-gui-android/libs/publicfileprovider.jar differ
diff --git a/forge-gui-android/libs/relinker.jar b/forge-gui-android/libs/relinker.jar
new file mode 100644
index 00000000000..22fc82b4b09
Binary files /dev/null and b/forge-gui-android/libs/relinker.jar differ
diff --git a/forge-gui-android/libs/x86/libgdx-box2d.so b/forge-gui-android/libs/x86/libgdx-box2d.so
index df1fef60837..98a5aefa823 100644
Binary files a/forge-gui-android/libs/x86/libgdx-box2d.so and b/forge-gui-android/libs/x86/libgdx-box2d.so differ
diff --git a/forge-gui-android/libs/x86/libgdx-freetype.so b/forge-gui-android/libs/x86/libgdx-freetype.so
index e2cd515dbe1..b98bf59da7b 100644
Binary files a/forge-gui-android/libs/x86/libgdx-freetype.so and b/forge-gui-android/libs/x86/libgdx-freetype.so differ
diff --git a/forge-gui-android/libs/x86/libgdx.so b/forge-gui-android/libs/x86/libgdx.so
index f9e1e416fd1..623b66290d5 100644
Binary files a/forge-gui-android/libs/x86/libgdx.so and b/forge-gui-android/libs/x86/libgdx.so differ
diff --git a/forge-gui-android/libs/x86_64/libgdx-box2d.so b/forge-gui-android/libs/x86_64/libgdx-box2d.so
index 852d26455f4..6d8d101fb9b 100644
Binary files a/forge-gui-android/libs/x86_64/libgdx-box2d.so and b/forge-gui-android/libs/x86_64/libgdx-box2d.so differ
diff --git a/forge-gui-android/libs/x86_64/libgdx-freetype.so b/forge-gui-android/libs/x86_64/libgdx-freetype.so
index 67c46fe75a6..b71ab3b08f0 100644
Binary files a/forge-gui-android/libs/x86_64/libgdx-freetype.so and b/forge-gui-android/libs/x86_64/libgdx-freetype.so differ
diff --git a/forge-gui-android/libs/x86_64/libgdx.so b/forge-gui-android/libs/x86_64/libgdx.so
index 0f8457506b5..87a2ca594ed 100644
Binary files a/forge-gui-android/libs/x86_64/libgdx.so and b/forge-gui-android/libs/x86_64/libgdx.so differ
diff --git a/forge-gui-android/pom.xml b/forge-gui-android/pom.xml
index 0c5ee1e7e22..3e078f2dbed 100644
--- a/forge-gui-android/pom.xml
+++ b/forge-gui-android/pom.xml
@@ -2,7 +2,8 @@
4.0.0
- yyyyMMdd-HHmm
+ ${maven.build.timestamp}
+ yyyy-MM-dd HH:mm:ss
jar
-Xms1024m
-Xmx1536m
@@ -26,6 +27,13 @@
${packaging.type}
Forge Android
+
+
+ Google Maven
+ https://maven.google.com/
+
+
+
src
@@ -45,30 +53,44 @@
forge-android-${alpha-version}
-
-
- gdx-nightlies
- https://oss.sonatype.org/content/repositories/snapshots/
-
-
- com.google.android
- android
- 4.1.1.4
+ org.robolectric
+ android-all
+ 8.0.0_r4-robolectric-0
provided
+
+ de.cketti.fileprovider
+ public-fileprovider
+ 1.0.0
+ system
+ ${pom.basedir}/libs/publicfileprovider.jar
+
+
+ com.getkeepsafe.relinker
+ relinker
+ 1.4.5
+ system
+ ${pom.basedir}/libs/relinker.jar
+
org.apache.httpcomponents
httpclient
- 4.5.13
+ 4.5.14
+
+
+ commons-codec
+ commons-codec
+
+
commons-codec
commons-codec
- 1.15
+ 1.16.0
forge
@@ -104,7 +126,9 @@
com.badlogicgames.gdx
gdx-backend-android
- 1.11.0
+ 1.12.1
+ system
+ ${pom.basedir}/libs/gdx-backend-android.jar
io.sentry
@@ -176,8 +200,14 @@
com.badlogicgames.gdx-controllers
gdx-controllers-android
- 2.2.3-SNAPSHOT
+ 2.2.3
aar
+
+
+ com.badlogicgames.gdx
+ gdx-backend-android
+
+
@@ -423,6 +453,11 @@
+
+
+
+
+
diff --git a/forge-gui-android/proguard.cfg b/forge-gui-android/proguard.cfg
index 35c2b4eae3d..b4cc8fcab34 100644
--- a/forge-gui-android/proguard.cfg
+++ b/forge-gui-android/proguard.cfg
@@ -4,12 +4,16 @@
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
--optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
+-optimizations !code/simplification/*,!field/*,!class/merging/*,!code/allocation/variable,!library/gson
## Uncomment the line below and set it to the location of rt.jar in JDK if the Proguard step fails to find the libraries
## and spits out a thousand-something Class Not Found errors
##-libraryjars /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar
##-libraryjars /jmods/java.base.jmod(!**.jar;!module-info.class)
+##-libraryjars /jmods/java.datatransfer.jmod(!**.jar;!module-info.class)
+##-libraryjars /jmods/java.prefs.jmod(!**.jar;!module-info.class)
+##-libraryjars /jmods/java.xml.jmod(!**.jar;!module-info.class)
+##-libraryjars /jmods/java.desktop.jmod(!**.jar;!module-info.class)
##-libraryjars /jmods/jdk.xml.dom.jmod(!**.jar;!module-info.class)
-dontwarn afu.org.checkerframework.**
@@ -57,18 +61,20 @@
-keep class org.apache.commons.lang3.** { *; }
-keep class com.google.guava.** { *; }
-keep class com.google.common.** { *; }
--keep class com.google.gson.GsonBuilder
--keep class io.sentry.event.Event { *; }
--keep class io.sentry.android.core.SentryAndroidOptions
--keep class io.sentry.android.core.SentryAndroid
+#-keep class com.google.gson.GsonBuilder
+##-keep class io.sentry.event.Event { *; }
+##-keep class io.sentry.android.core.SentryAndroidOptions
+##-keep class io.sentry.android.core.SentryAndroid
--keep class io.sentry.android.core.SentryInitProvider
--keep class io.sentry.android.core.SentryPerformanceProvider
+##-keep class io.sentry.android.core.SentryInitProvider
+##-keep class io.sentry.android.core.SentryPerformanceProvider
-keep class com.badlogic.gdx.controllers.android.AndroidControllers { *; }
-keep class com.github.tommyettinger.textra.** { *; }
--keep class io.sentry.android.ndk.SentryNdk
--keep class io.sentry.Sentry
+##-keep class io.sentry.android.ndk.SentryNdk
+##-keep class io.sentry.Sentry
+-keep class io.sentry.** { *; }
+-keepclassmembers enum io.sentry.** { *; }
-keep class io.netty.util.internal.logging.** { *; }
-keep class net.jpountz.** { *; }
-keep class com.ray3k.** { *; }
diff --git a/forge-gui-android/res/drawable/bg_gradient.xml b/forge-gui-android/res/drawable/bg_gradient.xml
new file mode 100644
index 00000000000..a040e21cd84
--- /dev/null
+++ b/forge-gui-android/res/drawable/bg_gradient.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/forge-gui-android/res/drawable/logo.png b/forge-gui-android/res/drawable/logo.png
new file mode 100644
index 00000000000..71598bc678d
Binary files /dev/null and b/forge-gui-android/res/drawable/logo.png differ
diff --git a/forge-gui-android/res/drawable/splash_background.xml b/forge-gui-android/res/drawable/splash_background.xml
new file mode 100644
index 00000000000..8b82397d93e
--- /dev/null
+++ b/forge-gui-android/res/drawable/splash_background.xml
@@ -0,0 +1,7 @@
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/forge-gui-android/res/layout/main.xml b/forge-gui-android/res/layout/main.xml
index 777a3e48e4e..b074850f1e5 100644
--- a/forge-gui-android/res/layout/main.xml
+++ b/forge-gui-android/res/layout/main.xml
@@ -1,7 +1,38 @@
-
+
-
\ No newline at end of file
+
+
+
+
+
+
\ No newline at end of file
diff --git a/forge-gui-android/res/layout/splash.xml b/forge-gui-android/res/layout/splash.xml
new file mode 100644
index 00000000000..ab8302b1005
--- /dev/null
+++ b/forge-gui-android/res/layout/splash.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/forge-gui-android/res/values-w820dp/dimens.xml b/forge-gui-android/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000000..63fc8164446
--- /dev/null
+++ b/forge-gui-android/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/forge-gui-android/res/values/colors.xml b/forge-gui-android/res/values/colors.xml
new file mode 100644
index 00000000000..c33b8418321
--- /dev/null
+++ b/forge-gui-android/res/values/colors.xml
@@ -0,0 +1,8 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+ #258cec
+ #000000
+
diff --git a/forge-gui-android/res/values/dimens.xml b/forge-gui-android/res/values/dimens.xml
new file mode 100644
index 00000000000..47c82246738
--- /dev/null
+++ b/forge-gui-android/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/forge-gui-android/res/values/styles.xml b/forge-gui-android/res/values/styles.xml
new file mode 100644
index 00000000000..90ec268463f
--- /dev/null
+++ b/forge-gui-android/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
\ No newline at end of file
diff --git a/forge-gui-android/res/values/themes.xml b/forge-gui-android/res/values/themes.xml
new file mode 100644
index 00000000000..226e82a0912
--- /dev/null
+++ b/forge-gui-android/res/values/themes.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/forge-gui-android/res/xml/publicfileprovider_paths.xml b/forge-gui-android/res/xml/publicfileprovider_paths.xml
new file mode 100644
index 00000000000..c589ed2ebc7
--- /dev/null
+++ b/forge-gui-android/res/xml/publicfileprovider_paths.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/forge-gui-android/src/forge/app/Launcher.java b/forge-gui-android/src/forge/app/Launcher.java
index 84dabfd9797..701d91f90d4 100644
--- a/forge-gui-android/src/forge/app/Launcher.java
+++ b/forge-gui-android/src/forge/app/Launcher.java
@@ -5,6 +5,7 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import forge.gui.GuiBase;
import java.io.BufferedReader;
@@ -20,9 +21,13 @@ public class Launcher extends Activity {
startActivity(main);
Intent intent = getIntent();
- String action = intent.getAction();
- String type = intent.getType();
+ sendIntent(intent, intent.getAction(), intent.getType());
+ finish();
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
+ }
+
+ private void sendIntent(Intent intent, String action, String type) {
if (Intent.ACTION_SEND.equals(action) && type != null) {
final Handler handler = new Handler();
handler.postDelayed(() -> {
@@ -50,9 +55,7 @@ public class Launcher extends Activity {
}
}, 1500);
}
- finish();
}
-
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
@@ -61,8 +64,7 @@ public class Launcher extends Activity {
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
- final Handler handler = new Handler();
- handler.postDelayed(() -> {
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
if ("text/plain".equals(type)) {
Uri textUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (textUri != null) {
diff --git a/forge-gui-android/src/forge/app/Main.java b/forge-gui-android/src/forge/app/Main.java
index 166c282da3c..1562937d252 100644
--- a/forge-gui-android/src/forge/app/Main.java
+++ b/forge-gui-android/src/forge/app/Main.java
@@ -1,32 +1,26 @@
package forge.app;
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.Normalizer;
-import java.util.ArrayList;
-
-import android.graphics.Point;
-import android.view.InputDevice;
-import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.Version;
-import com.badlogic.gdx.backends.android.AndroidApplication;
-
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.AlarmManager;
import android.app.AlertDialog;
-import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipboardManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
+import android.graphics.Point;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
@@ -36,35 +30,57 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
-import android.os.PowerManager;
import android.provider.Settings;
import android.text.SpannableString;
+import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
+import android.view.InputDevice;
+import android.view.View;
import android.view.WindowManager;
import android.webkit.MimeTypeMap;
import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Version;
+import com.badlogic.gdx.backends.android.AndroidApplication;
+import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
+import com.badlogic.gdx.backends.android.AndroidAudio;
+import com.getkeepsafe.relinker.ReLinker;
+import de.cketti.fileprovider.PublicFileProvider;
import forge.Forge;
import forge.interfaces.IDeviceAdapter;
-import forge.localinstance.properties.ForgePreferences;
-import forge.model.FModel;
import forge.util.FileUtil;
import forge.util.ThreadUtil;
-import io.sentry.Breadcrumb;
-import io.sentry.Sentry;
import org.apache.commons.lang3.tuple.Pair;
-//import io.sentry.android.core.SentryAndroid;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.text.Normalizer;
+import java.util.ArrayList;
public class Main extends AndroidApplication {
- AndroidAdapter Gadapter;
- ArrayList gamepads;
- AndroidClipboard androidClipboard;
- boolean hasLaunched;
+ private AndroidAdapter Gadapter;
+ private ArrayList gamepads;
+ private AndroidClipboard androidClipboard;
+ private boolean isMIUI;
+ private String ASSETS_DIR = "";
+ private SharedPreferences sharedPreferences;
+ private int mShortAnimationDuration;
+ private View forgeLogo = null, forgeView = null, activeView = null;
+ private ProgressBar progressBar;
+ private TextView progressText;
private AndroidClipboard getAndroidClipboard() {
if (androidClipboard == null)
@@ -72,16 +88,62 @@ public class Main extends AndroidApplication {
return androidClipboard;
}
+ public static boolean isMiUi() {
+ return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
+ }
+
+ public static String getSystemProperty(String propName) {
+ String line;
+ BufferedReader input = null;
+ try {
+ java.lang.Process p = Runtime.getRuntime().exec("getprop " + propName);
+ input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
+ line = input.readLine();
+ input.close();
+ } catch (IOException ex) {
+ return null;
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return line;
+ }
+
+ @Override
+ protected void onResume() {
+ try {
+ super.onResume();
+ } catch (Exception e) {
+ }
+ }
+
+ @Override
+ public AndroidAudio createAudio(Context context, AndroidApplicationConfiguration config) {
+ return super.createAudio(context, config);
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- gamepads = getGameControllers();
+ setContentView(getResources().getIdentifier("main", "layout", getPackageName()));
+ mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
+ sharedPreferences = getPreferences(Context.MODE_PRIVATE);
+ progressBar = findViewById(getResources().getIdentifier("pBar", "id", getPackageName()));
+ progressBar.setIndeterminate(true);
+ progressBar.setVisibility(View.GONE);
+ progressText = findViewById(getResources().getIdentifier("pText", "id", getPackageName()));
+ progressText.setVisibility(View.GONE);
- if (hasLaunched)
- return;
- hasLaunched = true;
- //init Sentry
- //SentryAndroid.init(this);
+ isMIUI = isMiUi();
+ if (isMIUI)
+ preventSleep(true);
+
+ gamepads = getGameControllers();
//get total device RAM in mb
ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
@@ -89,51 +151,84 @@ public class Main extends AndroidApplication {
actManager.getMemoryInfo(memInfo);
int totalMemory = Math.round(memInfo.totalMem / 1024f / 1024f);
- boolean permissiongranted = checkPermission();
- Gadapter = new AndroidAdapter(this.getContext());
- initForge(Gadapter, permissiongranted, totalMemory, isTabletDevice(this.getContext()), Build.VERSION.SDK_INT, Build.VERSION.RELEASE);
+ boolean permissiongranted = checkPermission();
+ Gadapter = new AndroidAdapter(getContext());
+ initForge(Gadapter, permissiongranted, totalMemory, isTabletDevice(getContext()));
}
+
+ private void crossfade(View contentView, View previousView) {
+ activeView = contentView;
+ // Set the content view to 0% opacity but visible, so that it is visible
+ // (but fully transparent) during the animation.
+ contentView.setAlpha(0f);
+ contentView.setVisibility(View.VISIBLE);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
+ addContentView(contentView, params);
+
+ // Animate the content view to 100% opacity, and clear any animation
+ // listener set on the view.
+ contentView.animate()
+ .alpha(1f)
+ .setDuration(mShortAnimationDuration)
+ .setListener(null);
+
+ // Animate the loading view to 0% opacity. After the animation ends,
+ // set its visibility to GONE as an optimization step (it won't
+ // participate in layout passes, etc.)
+ previousView.animate()
+ .alpha(0f)
+ .setDuration(mShortAnimationDuration)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ previousView.setVisibility(View.GONE);
+ }
+ });
+ }
+
private static boolean isTabletDevice(Context activityContext) {
- Display display = ((Activity) activityContext).getWindowManager().getDefaultDisplay();
+ Display display = ((Activity) activityContext).getWindowManager().getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
float widthInches = metrics.widthPixels / metrics.xdpi;
float heightInches = metrics.heightPixels / metrics.ydpi;
double diagonalInches = Math.sqrt(Math.pow(widthInches, 2) + Math.pow(heightInches, 2));
- if (diagonalInches >= 7.0) {
- return true;
- }
- return false;
+ return diagonalInches >= 7.0;
}
- private void displayMessage(AndroidAdapter adapter, boolean ex, String msg){
+
+ private void displayMessage(View previousView, AndroidAdapter adapter, boolean ex, String msg, boolean manageApp) {
TableLayout TL = new TableLayout(this);
+ TL.setBackgroundResource(android.R.color.black);
TableRow row = new TableRow(this);
TableRow row2 = new TableRow(this);
TextView text = new TextView(this);
text.setGravity(Gravity.LEFT);
text.setTypeface(Typeface.SERIF);
+ String SP = Build.VERSION.SDK_INT > 29 ? "Files & Media" : "Storage Permission";
- String title="Forge needs Storage Permission to run properly...\n" +
+ String title = "Forge needs " + SP + " to run properly...\n" +
"Follow these simple steps:\n\n";
- String steps = " 1) Tap \"Open App Details\" Button.\n" +
- " 2) Tap Permissions\n"+
- " 3) Turn on the Storage Permission.\n\n"+
+ String steps = " 1) Tap \"App Settings\" Button.\n" +
+ " 2) Tap Permissions\n" +
+ " 3) Enable the " + SP + ".\n\n" +
"(You can tap anywhere to exit and restart the app)\n\n";
if (ex) {
- title = "Forge didn't initialize!\n";
- steps = msg + "\n\n";
+ title = manageApp ? "Forge AutoUpdater Permission...\n" : "Forge didn't initialize!\n";
+ steps = manageApp ? " 1) Tap \"App Settings\" Button.\n" +
+ " 2) Enable \"Allow apps from this source\"\n" +
+ "(You can tap anywhere to exit and restart the app)\n\n" : msg + "\n\n";
}
- SpannableString ss1= new SpannableString(title);
+ SpannableString ss1 = new SpannableString(title);
ss1.setSpan(new StyleSpan(Typeface.BOLD), 0, ss1.length(), 0);
text.append(ss1);
text.append(steps);
row.addView(text);
row.setGravity(Gravity.CENTER);
- int[] colors = {Color.TRANSPARENT,Color.TRANSPARENT};
- int[] pressed = {Color.GREEN,Color.GREEN};
+ int[] colors = {Color.TRANSPARENT, Color.TRANSPARENT};
+ int[] pressed = {Color.GREEN, Color.GREEN};
GradientDrawable gd = new GradientDrawable(
GradientDrawable.Orientation.TOP_BOTTOM, colors);
gd.setStroke(3, Color.DKGRAY);
@@ -145,21 +240,29 @@ public class Main extends AndroidApplication {
gd2.setCornerRadius(100);
Button button = new Button(this);
- button.setText("Open App Details");
+ button.setText("App Settings");
+ button.setTypeface(Typeface.DEFAULT_BOLD);
StateListDrawable states = new StateListDrawable();
- states.addState(new int[] {android.R.attr.state_pressed}, gd2);
- states.addState(new int[] { }, gd);
+ states.addState(new int[]{android.R.attr.state_pressed}, gd2);
+ states.addState(new int[]{}, gd);
button.setBackground(states);
+ button.setTextColor(Color.RED);
button.setOnClickListener(v -> {
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- Uri uri = Uri.fromParts("package", getPackageName(), null);
- intent.setData(uri);
- startActivity(intent);
+ if (manageApp) {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
+ .setData(Uri.parse(String.format("package:%s", getPackageName())))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ } else {
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+ .setData(Uri.parse(String.format("package:%s", getPackageName())))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
});
row2.addView(button);
@@ -168,121 +271,189 @@ public class Main extends AndroidApplication {
TL.addView(row, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
TL.addView(row2, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
TL.setGravity(Gravity.CENTER);
- TL.setOnClickListener(v -> adapter.exit());
- setContentView(TL);
+ TL.setOnClickListener(v -> adapter.restart());
+ crossfade(TL, previousView);
}
+
+ private void loadGame(final String title, final String steps, boolean isLandscape, AndroidAdapter adapter, boolean permissiongranted, int totalRAM, boolean isTabletDevice, AndroidApplicationConfiguration config, boolean exception, String msg) {
+ try {
+ forgeLogo = findViewById(getResources().getIdentifier("logo_id", "id", getPackageName()));
+ forgeView = initializeForView(Forge.getApp(getAndroidClipboard(), adapter, ASSETS_DIR, false, !isLandscape, totalRAM, isTabletDevice, Build.VERSION.SDK_INT, Build.VERSION.RELEASE, getDeviceName()), config);
+ getAnimator(ObjectAnimator.ofFloat(forgeLogo, "alpha", 0f, 1f).setDuration(1800), null, new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ if (!permissiongranted || exception) {
+ displayMessage(forgeLogo, adapter, exception, msg, false);
+ } else if (title.isEmpty() && steps.isEmpty()) {
+ if (isLandscape) {
+ Main.this.setRequestedOrientation(Build.VERSION.SDK_INT >= 26 ?
+ ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : //Oreo and above has virtual back/menu buttons
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ } else {
+ Main.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
+ }
+ crossfade(forgeView, forgeLogo);
+ } else {
+ if (sharedPreferences.getBoolean("run_anyway", false)) {
+ crossfade(forgeView, forgeLogo);
+ return;
+ }
+ TableLayout TL = new TableLayout(getContext());
+ TL.setBackgroundResource(android.R.color.black);
+ TableRow messageRow = new TableRow(getContext());
+ TableRow checkboxRow = new TableRow(getContext());
+ TableRow buttonRow = new TableRow(getContext());
+ TextView text = new TextView(getContext());
+ text.setGravity(Gravity.LEFT);
+ text.setTypeface(Typeface.SERIF);
+
+ SpannableString ss1 = new SpannableString(title);
+ ss1.setSpan(new StyleSpan(Typeface.BOLD), 0, ss1.length(), 0);
+ text.append(ss1);
+ text.append(steps + "\n");
+ messageRow.addView(text);
+ messageRow.setGravity(Gravity.CENTER);
+
+ CheckBox checkBox = new CheckBox(getContext());
+ checkBox.setTypeface(Typeface.SERIF);
+ checkBox.setGravity(Gravity.TOP);
+ checkBox.setChecked(false);
+ checkBox.setPadding(30, 30, 30, 30);
+ checkBox.setTypeface(Typeface.SERIF);
+ checkBox.setText(" Don't remind me next time. ");
+ checkBox.setScaleX(0.9f);
+ checkBox.setScaleY(0.9f);
+ checkBox.setOnCheckedChangeListener((buttonView, isChecked) ->
+ sharedPreferences.edit().putBoolean("run_anyway", isChecked).apply());
+ checkboxRow.addView(checkBox);
+ checkboxRow.setGravity(Gravity.CENTER);
+
+ int[] colors = {Color.TRANSPARENT, Color.TRANSPARENT};
+ int[] pressed = {Color.GREEN, Color.GREEN};
+ GradientDrawable gd = new GradientDrawable(
+ GradientDrawable.Orientation.TOP_BOTTOM, colors);
+ gd.setStroke(3, Color.DKGRAY);
+ gd.setCornerRadius(100);
+
+ GradientDrawable gd2 = new GradientDrawable(
+ GradientDrawable.Orientation.TOP_BOTTOM, pressed);
+ gd2.setStroke(3, Color.DKGRAY);
+ gd2.setCornerRadius(100);
+
+ Button button = new Button(getContext());
+ button.setText("Run Forge..");
+ button.setTypeface(Typeface.DEFAULT_BOLD);
+
+ StateListDrawable states = new StateListDrawable();
+
+ states.addState(new int[]{android.R.attr.state_pressed}, gd2);
+ states.addState(new int[]{}, gd);
+
+ button.setBackground(states);
+
+ button.setTextColor(Color.RED);
+ button.setOnClickListener(v -> {
+ button.setClickable(false);
+ crossfade(forgeView, TL);
+ });
+
+ buttonRow.addView(button);
+ buttonRow.setGravity(Gravity.CENTER);
+
+ TL.addView(messageRow, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
+ TL.addView(checkboxRow, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
+ TL.addView(buttonRow, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
+ TL.setGravity(Gravity.CENTER);
+ crossfade(TL, forgeLogo);
+ }
+ }
+ }).start();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private AnimatorSet getAnimator(Animator play, Animator with, AnimatorListenerAdapter adapter) {
+ AnimatorSet animatorSet = new AnimatorSet();
+ if (with != null)
+ animatorSet.play(play).with(with);
+ else
+ animatorSet.play(play);
+ animatorSet.addListener(adapter);
+ return animatorSet;
+ }
+
@Override
public void onBackPressed() {
- if (Gadapter!=null)
+ if (Gadapter != null)
Gadapter.exit();
super.onBackPressed();
}
+
private boolean checkPermission() {
int pid = android.os.Process.myPid();
int uid = android.os.Process.myUid();
try {
- int result = this.getBaseContext().checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, pid, uid);
- if (result == PackageManager.PERMISSION_GRANTED) {
- return true;
- } else {
- return false;
- }
+ int result = getBaseContext().checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, pid, uid);
+ return result == PackageManager.PERMISSION_GRANTED;
} catch (NullPointerException e) {
return false;
}
}
- private void requestPermission() {
- //Show Information about why you need the permission
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle("Storage Permission Denied...");
- builder.setMessage("This app needs storage permission to run properly.\n\n\n\n");
- builder.setPositiveButton("Open App Details", (dialog, which) -> {
- dialog.cancel();
- //ActivityCompat crashes... maybe it needs the appcompat v7???
- //ActivityCompat.requestPermissions(Main.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
- });
- /*builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
- builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- }
- });*/
- builder.show();
- }
+ private void initForge(AndroidAdapter adapter, boolean permissiongranted, int totalRAM, boolean isTabletDevice) {
+ AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
+ config.useAccelerometer = false;
+ config.useCompass = false;
+ config.useGyroscope = false;
+ config.useRotationVectorSensor = false;
+ config.useImmersiveMode = false;
+ config.nativeLoader = () -> ReLinker.loadLibrary(getContext(), "gdx");
- private void initForge(AndroidAdapter adapter, boolean permissiongranted, int totalRAM, boolean isTabletDevice, int AndroidAPI, String AndroidRelease){
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
- //fake init for error message
- //set current orientation
- String message = getDeviceName()+"\n"+"Android "+AndroidRelease+"\n"+"RAM "+ totalRAM+"MB" +"\n"+"LibGDX "+ Version.VERSION+"\n"+"Can't access external storage";
- Sentry.addBreadcrumb(new Breadcrumb(message));
+ String message = getDeviceName() + "\n" + "Android " + Build.VERSION.RELEASE + "\n" + "RAM " + totalRAM + "MB" + "\n" + "LibGDX " + Version.VERSION + "\n" + "Can't access external storage";
Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation);
- initialize(Forge.getApp(getAndroidClipboard(), adapter, "", false, true, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName()));
- displayMessage(adapter, true, message);
+ loadGame("", "", false, adapter, permissiongranted, totalRAM, isTabletDevice, config, true, message);
return;
}
- String obbforge = Environment.getExternalStorageDirectory() + "/obbforge";
- //if obbforge file exists in Phone Storage, Forge uses app-specific Obb directory as path, Android 11+ is mandatory even without obbforge
- String assetsDir = (FileUtil.doesFileExist(obbforge) || Build.VERSION.SDK_INT > 29) ? getContext().getObbDir()+"/Forge/" : Environment.getExternalStorageDirectory()+"/Forge/";
- if (!FileUtil.ensureDirectoryExists(assetsDir)) {
- //fake init for error message
- //set current orientation
- String message = getDeviceName()+"\n"+"Android "+AndroidRelease+"\n"+"RAM "+ totalRAM+"MB" +"\n"+"LibGDX "+ Version.VERSION+"\n"+"Can't access external storage\nPath: " + assetsDir;
- Sentry.addBreadcrumb(new Breadcrumb(message));
+ ASSETS_DIR = Build.VERSION.SDK_INT > 29 ? getContext().getObbDir() + "/Forge/" : Environment.getExternalStorageDirectory() + "/Forge/";
+ if (!FileUtil.ensureDirectoryExists(ASSETS_DIR)) {
+ String message = getDeviceName() + "\n" + "Android " + Build.VERSION.RELEASE + "\n" + "RAM " + totalRAM + "MB" + "\n" + "LibGDX " + Version.VERSION + "\n" + "Can't access external storage\nPath: " + ASSETS_DIR;
Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation);
- initialize(Forge.getApp(getAndroidClipboard(), adapter, "", false, true, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName()));
- displayMessage(adapter, true, message);
+ loadGame("", "", false, adapter, permissiongranted, totalRAM, isTabletDevice, config, true, message);
return;
}
- boolean isPortrait;
- if (permissiongranted) {
- //ensure .nomedia file exists in Forge directory so its images
- //and other media files don't appear in Gallery or other apps
- String noMediaFile = assetsDir + ".nomedia";
- if (!FileUtil.doesFileExist(noMediaFile)) {
+ //ensure .nomedia file exists in Forge directory so its images
+ //and other media files don't appear in Gallery or other apps
+ String noMediaFile = ASSETS_DIR + ".nomedia";
+ if (!FileUtil.doesFileExist(noMediaFile)) {
+ try {
FileUtil.writeFile(noMediaFile, "");
+ } catch (Exception e) {
+ String message = getDeviceName() + "\n" + "Android " + Build.VERSION.RELEASE + "\n" + "RAM " + totalRAM + "MB" + "\n" + "LibGDX " + Version.VERSION + "\n" + "Can't read/write to storage";
+ Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation);
+ loadGame("", "", false, adapter, permissiongranted, totalRAM, isTabletDevice, config, true, message);
+ return;
}
- //enforce orientation based on whether device is a tablet and user preference
- adapter.switchOrientationFile = assetsDir + "switch_orientation.ini";
- boolean landscapeMode = adapter.isTablet == !FileUtil.doesFileExist(adapter.switchOrientationFile);
- ForgePreferences prefs = FModel.getPreferences();
- boolean propertyConfig = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_NETPLAY_COMPAT);
- if (landscapeMode) {
- isPortrait = false;
- Main.this.setRequestedOrientation(Build.VERSION.SDK_INT >= 26 ?
- ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : //Oreo and above has virtual back/menu buttons
- ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
- } else {
- isPortrait = true;
- Main.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- }
- initialize(Forge.getApp(getAndroidClipboard(), adapter, assetsDir, propertyConfig, isPortrait, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName()));
- } else {
- isPortrait = true;
- //fake init for permission instruction
- Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation);
- initialize(Forge.getApp(getAndroidClipboard(), adapter, "", false, isPortrait, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName()));
- displayMessage(adapter, false, "");
}
+ //enforce orientation based on whether device is a tablet and user preference
+ adapter.switchOrientationFile = ASSETS_DIR + "switch_orientation.ini";
+ boolean landscapeMode = adapter.isTablet == !FileUtil.doesFileExist(adapter.switchOrientationFile);
+
+ String info = totalRAM < 3500 || Build.VERSION.SDK_INT < 29 ? "Device Specification Check\n" + getDeviceName()
+ + "\n" + "Android " + Build.VERSION.RELEASE + "\n" + "RAM " + totalRAM + "MB\n\nMinimum Requirements:" : "";
+ String lowV = Build.VERSION.SDK_INT < 29 ? "\nAPI: Android 10 or higher" : "";
+ String lowM = totalRAM < 3500 ? "\nRAM: 4GB RAM or higher" : "";
+ if (landscapeMode && Build.VERSION.SDK_INT > 32) {
+ Main.this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
+ }
+ loadGame(info, lowV + lowM, landscapeMode, adapter, permissiongranted, totalRAM, isTabletDevice, config, false, "");
}
@Override
protected void onDestroy() {
- hasLaunched = false;
- try {
- final Forge forge = (Forge) Gdx.app.getApplicationListener();
- if (forge != null)
- forge.dispose();
- } catch (Exception e) {
- e.printStackTrace();
- }
super.onDestroy();
//ensure app doesn't stick around
//ActivityManager am = (ActivityManager)getSystemService(Activity.ACTIVITY_SERVICE);
@@ -290,8 +461,7 @@ public class Main extends AndroidApplication {
}
@Override
- protected void onPause()
- {
+ protected void onPause() {
super.onPause();
ForgePreferences prefs = FModel.getPreferences();
@@ -317,8 +487,7 @@ public class Main extends AndroidApplication {
if (cm.getPrimaryClip().getItemCount() > 0) {
try {
return cm.getPrimaryClip().getItemAt(0).coerceToText(getContext()).length() > 0;
- }
- catch (Exception ex) {
+ } catch (Exception ex) {
return false;
}
}
@@ -331,8 +500,7 @@ public class Main extends AndroidApplication {
try {
String text = cm.getPrimaryClip().getItemAt(0).coerceToText(getContext()).toString();
return Normalizer.normalize(text, Normalizer.Form.NFD);
- }
- catch (Exception ex) {
+ } catch (Exception ex) {
ex.printStackTrace();
}
}
@@ -341,7 +509,11 @@ public class Main extends AndroidApplication {
@Override
public void setContents(String contents0) {
- cm.setPrimaryClip(ClipData.newPlainText("Forge", contents0));
+ try {
+ cm.setPrimaryClip(ClipData.newPlainText("Forge", contents0));
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
}
}
@@ -380,16 +552,23 @@ public class Main extends AndroidApplication {
@Override
public boolean openFile(String filename) {
try {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //ensure this task isn't linked to this application
- Uri uri = Uri.fromFile(new File(filename));
- String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
- MimeTypeMap.getFileExtensionFromUrl(uri.toString()));
- intent.setDataAndType(uri, type);
- startActivity(intent);
- return true;
- }
- catch (Exception e) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //ensure this task isn't linked to this application
+ Uri uri = Uri.fromFile(new File(filename));
+ String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
+ MimeTypeMap.getFileExtensionFromUrl(uri.toString()));
+ intent.setDataAndType(uri, type);
+ startActivity(intent);
+ return true;
+ } else {
+ Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
+ intent.setData(PublicFileProvider.getUriForFile(getContext(), "com.mydomain.publicfileprovider", new File(filename)));
+ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ startActivity(intent);
+ return true;
+ }
+ } catch (Exception e) {
e.printStackTrace();
}
return false;
@@ -397,28 +576,7 @@ public class Main extends AndroidApplication {
@Override
public void restart() {
- try { //solution from http://stackoverflow.com/questions/6609414/howto-programatically-restart-android-app
- Context c = getApplicationContext();
- PackageManager pm = c.getPackageManager();
- if (pm != null) {
- //create the intent with the default start activity for your application
- Intent mStartActivity = pm.getLaunchIntentForPackage(c.getPackageName());
- if (mStartActivity != null) {
- mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- //create a pending intent so the application is restarted after System.exit(0) was called.
- // We use an AlarmManager to call this intent in 100ms
- int mPendingIntentId = 223344;
- PendingIntent mPendingIntent = PendingIntent.getActivity(c, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
- AlarmManager mgr = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
- mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
- //kill the application
- System.exit(0);
- }
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
+ triggerRebirth();
}
@Override
@@ -439,8 +597,7 @@ public class Main extends AndroidApplication {
//create file to indicate that portrait mode should be used for tablet or landscape should be used for phone
if (landscapeMode != isTablet) {
FileUtil.writeFile(switchOrientationFile, "1");
- }
- else {
+ } else {
FileUtil.deleteFile(switchOrientationFile);
}
}
@@ -450,14 +607,7 @@ public class Main extends AndroidApplication {
// Setting getWindow() Flags needs to run on UI thread.
// Should fix android.view.ViewRoot$CalledFromWrongThreadException:
// Only the original thread that created a view hierarchy can touch its views.
- runOnUiThread(() -> {
- if (preventSleep) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
- else {
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
- });
+ preventSleep(preventSleep);
}
@Override
@@ -465,6 +615,7 @@ public class Main extends AndroidApplication {
Bitmap bmp = BitmapFactory.decodeStream(input);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, output);
}
+
@Override
public Pair getRealScreenSize(boolean real) {
//app size
@@ -473,12 +624,12 @@ public class Main extends AndroidApplication {
Point size = new Point();
if (Build.VERSION.SDK_INT >= 17) {
// Seems it doesn't compile if using 4.1.1.4 since it's missing this method
- /*if (real)
+ if (real)
display.getRealSize(size);
else
- display.getSize(size);*/
+ display.getSize(size);
//remove this line below and use the method above if using Android libs higher than 4.1.1.4
- return Pair.of(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); // this method don't take account the soft navigation bars taken in rendered screen
+ //return Pair.of(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); // this method don't take account the soft navigation bars taken in rendered screen
} else if (Build.VERSION.SDK_INT >= 14) {
try {
size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
@@ -499,13 +650,42 @@ public class Main extends AndroidApplication {
return gamepads;
}
}
+
+ private void preventSleep(boolean preventSleep) {
+ runOnUiThread(() -> {
+ if (preventSleep) {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ } else {
+ if (!isMIUI)
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+ });
+ }
+
+ private void triggerRebirth() {
+ try {
+ Context context = getApplicationContext();
+ PackageManager packageManager = context.getPackageManager();
+ Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
+ ComponentName componentName = intent.getComponent();
+ Intent mainIntent = Intent.makeRestartActivityTask(componentName);
+ // Required for API 34 and later
+ // Ref: https://developer.android.com/about/versions/14/behavior-changes-14#safer-intents
+ mainIntent.setPackage(context.getPackageName());
+ context.startActivity(mainIntent);
+ Runtime.getRuntime().exit(0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
private ArrayList getGameControllers() {
- ArrayList gameControllerDeviceIds = new ArrayList();
+ ArrayList gameControllerDeviceIds = new ArrayList<>();
int[] deviceIds = InputDevice.getDeviceIds();
for (int deviceId : deviceIds) {
InputDevice dev = InputDevice.getDevice(deviceId);
int sources = dev.getSources();
- String devNameId = dev.getName()+"["+deviceId+"]";
+ String devNameId = dev.getName() + "[" + deviceId + "]";
// Verify that the device has gamepad buttons, control sticks, or both.
if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
@@ -522,7 +702,7 @@ public class Main extends AndroidApplication {
public String getDeviceName() {
String manufacturer = Build.MANUFACTURER;
- String model = Build.MODEL;
+ String model = Build.BRAND + " - " + Build.MODEL;
if (model.toLowerCase().startsWith(manufacturer.toLowerCase())) {
return capitalize(model);
} else {
diff --git a/forge-gui-ios/pom.xml b/forge-gui-ios/pom.xml
index 8753cfeb158..ec789a767fc 100644
--- a/forge-gui-ios/pom.xml
+++ b/forge-gui-ios/pom.xml
@@ -68,7 +68,7 @@
com.badlogicgames.gdx
gdx-backend-robovm
- 1.11.0
+ 1.12.1
diff --git a/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar b/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar
index 8fbd0cb3813..0485da75bac 100644
Binary files a/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar and b/forge-gui-mobile-dev/libs/gdx-backend-lwjgl-sources.jar differ
diff --git a/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar b/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar
index d2f8f105679..b8c835fd2c2 100644
Binary files a/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar and b/forge-gui-mobile-dev/libs/gdx-box2d-platform-natives.jar differ
diff --git a/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar b/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar
index 87ceb2eb26e..564d2f5139e 100644
Binary files a/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar and b/forge-gui-mobile-dev/libs/gdx-freetype-natives.jar differ
diff --git a/forge-gui-mobile-dev/libs/gdx-natives.jar b/forge-gui-mobile-dev/libs/gdx-natives.jar
index 10d0a113c8a..fb8b5e13ec2 100644
Binary files a/forge-gui-mobile-dev/libs/gdx-natives.jar and b/forge-gui-mobile-dev/libs/gdx-natives.jar differ
diff --git a/forge-gui-mobile-dev/pom.xml b/forge-gui-mobile-dev/pom.xml
index 7694be00a9b..26e8304d334 100644
--- a/forge-gui-mobile-dev/pom.xml
+++ b/forge-gui-mobile-dev/pom.xml
@@ -20,6 +20,7 @@
**/*.vert
**/*.frag
**/title_bg_lq.png
+ **/title_bg_lq_portrait.png
**/transition.png
**/adv_bg_texture.jpg
**/adv_bg_splash.png
@@ -216,12 +217,6 @@
-
-
- gdx-nightlies
- https://oss.sonatype.org/content/repositories/snapshots/
-
-
forge
@@ -231,18 +226,18 @@
com.badlogicgames.gdx
gdx-backend-lwjgl3
- 1.11.0
+ 1.12.1
com.badlogicgames.gdx
gdx-platform
- 1.11.0
+ 1.12.1
natives-desktop
com.badlogicgames.gdx
gdx-freetype-platform
- 1.11.0
+ 1.12.1
natives-desktop
@@ -254,12 +249,18 @@
com.badlogicgames.gdx-controllers
gdx-controllers-desktop
- 2.2.3-SNAPSHOT
+ 2.2.3
+
+
+ com.badlogicgames.gdx
+ gdx
+
+
com.badlogicgames.gdx
gdx-box2d-platform
- 1.11.0
+ 1.12.1
natives-desktop
diff --git a/forge-gui-mobile/libs/gdx-freetype.jar b/forge-gui-mobile/libs/gdx-freetype.jar
index b0c5060437f..7882e998dda 100644
Binary files a/forge-gui-mobile/libs/gdx-freetype.jar and b/forge-gui-mobile/libs/gdx-freetype.jar differ
diff --git a/forge-gui-mobile/libs/gdx-sources.jar b/forge-gui-mobile/libs/gdx-sources.jar
index 22d94b50342..85793e30966 100644
Binary files a/forge-gui-mobile/libs/gdx-sources.jar and b/forge-gui-mobile/libs/gdx-sources.jar differ
diff --git a/forge-gui-mobile/libs/gdx.jar b/forge-gui-mobile/libs/gdx.jar
index 1a0381b8566..cca18342888 100644
Binary files a/forge-gui-mobile/libs/gdx.jar and b/forge-gui-mobile/libs/gdx.jar differ
diff --git a/forge-gui-mobile/pom.xml b/forge-gui-mobile/pom.xml
index ecb25e59aa0..91cc8d9f6a5 100644
--- a/forge-gui-mobile/pom.xml
+++ b/forge-gui-mobile/pom.xml
@@ -24,10 +24,6 @@
-
- gdx-nightlies
- https://oss.sonatype.org/content/repositories/snapshots/
-
jitpack.io
https://jitpack.io
@@ -58,37 +54,61 @@
com.github.tommyettinger
textratypist
0.8.2
+
+
+ com.badlogicgames.gdx
+ gdx
+
+
com.badlogicgames.gdx-controllers
gdx-controllers-core
- 2.2.3-SNAPSHOT
+ 2.2.3
+
+
+ com.badlogicgames.gdx
+ gdx
+
+
com.badlogicgames.gdx
gdx
- 1.11.0
+ 1.12.1
com.badlogicgames.gdx
gdx-freetype
- 1.11.0
+ 1.12.1
com.github.raeleus.TenPatch
tenpatch
5.2.3
compile
+
+
+ com.badlogicgames.gdx
+ gdx
+
+
com.badlogicgames.gdx
gdx-box2d
- 1.11.0
+ 1.12.1
com.badlogicgames.gdx
gdx-ai
1.8.2
+
+
+ com.badlogicgames.gdx
+ gdx
+
+
diff --git a/forge-gui-mobile/src/forge/adventure/scene/HudScene.java b/forge-gui-mobile/src/forge/adventure/scene/HudScene.java
index 639e1a0242b..79312c2fc66 100644
--- a/forge-gui-mobile/src/forge/adventure/scene/HudScene.java
+++ b/forge-gui-mobile/src/forge/adventure/scene/HudScene.java
@@ -23,6 +23,11 @@ public abstract class HudScene extends Scene implements InputProcessor, IAfterMa
hud = GameHUD.getInstance();
}
+ @Override
+ public boolean touchCancelled (int x, int y, int pointer, int button) {
+ return touchUp(x, y, pointer, button);
+ }
+
@Override
public void connected(final Controller controller) {
hud.ui.controllerConnected();
diff --git a/forge-gui-mobile/src/forge/assets/AssetsDownloader.java b/forge-gui-mobile/src/forge/assets/AssetsDownloader.java
index 09acca91f4c..6663ae926ff 100644
--- a/forge-gui-mobile/src/forge/assets/AssetsDownloader.java
+++ b/forge-gui-mobile/src/forge/assets/AssetsDownloader.java
@@ -52,26 +52,15 @@ public class AssetsDownloader {
"You are currently on an older version (" + Forge.CURRENT_VERSION + ").\n\n" +
"Would you like to update to the new version now?";
if (!Forge.getDeviceAdapter().isConnectedToWifi()) {
- message += " If so, you may want to connect to wifi first. The download is around 6.5MB.";
+ message += " If so, you may want to connect to wifi first. The download is around 12MB.";
}
if (SOptionPane.showConfirmDialog(message, "New Version Available", "Update Now", "Update Later", true, true)) {
String apkFile = new GuiDownloadZipService("", "update", apkURL,
Forge.getDeviceAdapter().getDownloadsDir(), null, splashScreen.getProgressBar()).download(filename);
if (apkFile != null) {
- /* FileUriExposedException was added on API 24, Forge now targets API 26 so Android 10 and above runs,
- most user thinks Forge crashes but in reality, the method below just can't open the apk when Forge
- exits silently to run the downloaded apk. Some devices allow the apk to run but most users are annoyed when
- Forge didn't open the apk so I downgrade the check so it will run only on target devices without FileUriExposedException */
- if (Forge.androidVersion < 24) {
- Forge.getDeviceAdapter().openFile(apkFile);
- Forge.exitAnimation(false);
- return;
- }
- // API 24 and above needs manual apk installation unless we provide a FileProvider for FileUriExposedException
- switch (SOptionPane.showOptionDialog("Download Successful. Go to your downloads folder and install " + filename +" to update Forge. Forge will now exit.", "", null, ImmutableList.of("Ok"))) {
- default:
- Forge.exitAnimation(false);
- }
+ Forge.getDeviceAdapter().openFile(apkFile);
+ Forge.isMobileAdventureMode = Forge.advStartup;
+ Forge.exitAnimation(false);
return;
}
SOptionPane.showOptionDialog("Could not download update. " +