Initial commit

This commit is contained in:
jjayers99
2023-06-30 22:30:54 -04:00
commit d9c0a08662
38719 changed files with 1599809 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="forge.app"
android:versionCode="1"
android:versionName="1.6.53" > <!-- versionName should be updated and it's used for Sentry releases tag -->
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="26" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- This one needs Android Runtime Permission for Android 6+ -->
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-feature android:name="android.hardware.gamepad" android:required="false"/>
<application
android:allowBackup="true"
android:isGame="true"
android:appCategory="game"
android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:largeHeap="true">
<activity
android:name=".Main"
android:label="@string/app_name"
android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:exported="false">
</activity>
<activity
android:name=".Launcher"
android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
android:theme="@android:style/Theme.Black.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<meta-data android:name="io.sentry.dsn" android:value="https://a0b8dbad9b8a49cfa51bf65d462e8dae:b3f27d7461224cb8836eb5c6050c666c@sentry.cardforge.org/2?buffer.enabled=false" />
<!-- manually added -->
<provider
android:name="io.sentry.android.core.SentryInitProvider"
android:authorities=".SentryInitProvider"
android:exported="false"/>
<provider
android:name="io.sentry.android.core.SentryPerformanceProvider"
android:authorities=".SentryPerformanceProvider"
android:initOrder="200"
android:exported="false"/>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,16 @@
#ifdef GL_ES
precision mediump float;
#endif
varying vec4 v_color;
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_grayness;
uniform float u_bias;
void main() {
vec4 c = v_color * texture2D(u_texture, v_texCoords);
float grey = dot( c.rgb, vec3(0.22, 0.707, 0.071) );
vec3 blendedColor = mix(c.rgb, vec3(grey), u_grayness);
gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), vec4(blendedColor.rgb, c.a), u_bias);
}

View File

@@ -0,0 +1,14 @@
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoords;
void main() {
v_color = a_color;
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}

View File

@@ -0,0 +1,40 @@
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
uniform sampler2D u_texture;
uniform vec2 u_viewportInverse;
uniform vec3 u_color;
uniform float u_offset;
uniform float u_step;
varying vec4 v_color;
varying vec2 v_texCoord;
#define ALPHA_VALUE_BORDER 0.5
void main() {
vec2 T = v_texCoord.xy;
float alpha = 0.0;
bool allin = true;
for( float ix = -u_offset; ix < u_offset; ix += u_step )
{
for( float iy = -u_offset; iy < u_offset; iy += u_step )
{
float newAlpha = texture2D(u_texture, T + vec2(ix, iy) * u_viewportInverse).a;
allin = allin && newAlpha > ALPHA_VALUE_BORDER;
if (newAlpha > ALPHA_VALUE_BORDER && newAlpha >= alpha)
{
alpha = newAlpha;
}
}
}
if (allin)
{
alpha = 0.0;
}
gl_FragColor = vec4(u_color,alpha);
}

View File

@@ -0,0 +1,16 @@
uniform mat4 u_projTrans;
attribute vec4 a_position;
attribute vec2 a_texCoord0;
attribute vec4 a_color;
varying vec4 v_color;
varying vec2 v_texCoord;
uniform vec2 u_viewportInverse;
void main() {
gl_Position = u_projTrans * a_position;
v_texCoord = a_texCoord0;
v_color = a_color;
}

View File

@@ -0,0 +1,26 @@
#ifdef GL_ES
#define PRECISION mediump
precision PRECISION float;
precision PRECISION int;
#else
#define PRECISION
#endif
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_amount;
uniform float u_speed;
uniform float u_time;
uniform float u_bias;
void main () {
vec2 uv = v_texCoords;
uv.y += (cos((uv.y + (u_time * 0.04 * u_speed)) * 45.0) * 0.0019 * u_amount) + (cos((uv.y + (u_time * 0.1 * u_speed)) * 10.0) * 0.002 * u_amount);
uv.x += (sin((uv.y + (u_time * 0.07 * u_speed)) * 15.0) * 0.0029 * u_amount) + (sin((uv.y + (u_time * 0.1 * u_speed)) * 15.0) * 0.002 * u_amount);
vec4 texColor = texture2D(u_texture, uv);
gl_FragColor = mix(vec4(0.0, 0.0, 0.0, 1.0), texColor, u_bias);
}

View File

@@ -0,0 +1,57 @@
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 v_texCoords;
uniform sampler2D u_texture;
uniform float u_time;
uniform float u_speed;
uniform float u_amount;
uniform vec2 u_viewport;
uniform vec2 u_position;
float random2d(vec2 n) {
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}
float randomRange (in vec2 seed, in float min, in float max) {
return min + random2d(seed) * (max - min);
}
float insideRange(float v, float bottom, float top) {
return step(bottom, v) - step(top, v);
}
void main()
{
float time = floor(u_time * u_speed * 60.0);
vec3 outCol = texture2D(u_texture, v_texCoords).rgb;
float maxOffset = u_amount/2.0;
for (float i = 0.0; i < 2.0; i += 1.0) {
float sliceY = random2d(vec2(time, 2345.0 + float(i)));
float sliceH = random2d(vec2(time, 9035.0 + float(i))) * 0.25;
float hOffset = randomRange(vec2(time, 9625.0 + float(i)), -maxOffset, maxOffset);
vec2 uvOff = v_texCoords;
uvOff.x += hOffset;
if (insideRange(v_texCoords.y, sliceY, fract(sliceY+sliceH)) == 1.0){
outCol = texture2D(u_texture, uvOff).rgb;
}
}
float maxColOffset = u_amount / 6.0;
float rnd = random2d(vec2(time , 9545.0));
vec2 colOffset = vec2(randomRange(vec2(time , 9545.0), -maxColOffset, maxColOffset),
randomRange(vec2(time , 7205.0), -maxColOffset, maxColOffset));
if (rnd < 0.33) {
outCol.r = texture2D(u_texture, v_texCoords + colOffset).r;
} else if (rnd < 0.66) {
outCol.g = texture2D(u_texture, v_texCoords + colOffset).g;
} else {
outCol.b = texture2D(u_texture, v_texCoords + colOffset).b;
}
gl_FragColor = vec4(outCol, 1.0);
}

View File

@@ -0,0 +1 @@
${alpha-version}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

497
forge-gui-android/pom.xml Normal file
View File

@@ -0,0 +1,497 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
<packaging.type>jar</packaging.type>
<build.min.memory>-Xms1024m</build.min.memory>
<build.max.memory>-Xmx1536m</build.max.memory>
<alpha-version>1.6.56.001</alpha-version>
<sign.keystore>keystore</sign.keystore>
<sign.alias>alias</sign.alias>
<sign.storepass>storepass</sign.storepass>
<sign.keypass>keypass</sign.keypass>
<cardforge.user>user</cardforge.user>
<cardforge.pass>pass</cardforge.pass>
<cardforge.server>ftp.cardforge.org</cardforge.server>
</properties>
<parent>
<artifactId>forge</artifactId>
<groupId>forge</groupId>
<version>1.6.57-SNAPSHOT</version>
</parent>
<artifactId>forge-gui-android</artifactId>
<packaging>${packaging.type}</packaging>
<name>Forge Android</name>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>filters</directory>
<filtering>true</filtering>
</resource>
</resources>
<finalName>forge-android-${alpha-version}</finalName>
</build>
<repositories>
<repository>
<id>gdx-nightlies</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>4.1.1.4</version>
<scope>provided</scope>
</dependency>
<!-- declare a specific dependency to override com.google.android's transitive dependency -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<!-- declare a specific dependency to override org.apache.httpcomponents's transitive dependency -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-game</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-ai</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-gui</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>forge</groupId>
<artifactId>forge-gui-mobile</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>xmlpull</groupId>
<artifactId>xmlpull</artifactId>
<version>1.1.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>
<artifactId>gdx-backend-android</artifactId>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-android</artifactId>
<version>5.7.0</version>
<type>aar</type>
<exclusions>
<exclusion>
<groupId>io.sentry</groupId>
<artifactId>sentry-android-core</artifactId>
</exclusion>
<exclusion>
<groupId>io.sentry</groupId>
<artifactId>sentry-android-ndk</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- manual sentry-android dependencies because of Gradle Bug -->
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-android-core</artifactId>
<version>5.7.0</version>
<type>aar</type>
<exclusions>
<exclusion>
<groupId>androidx.lifecycle</groupId>
<artifactId>lifecycle-process</artifactId>
</exclusion>
<exclusion>
<groupId>androidx.lifecycle</groupId>
<artifactId>lifecycle-common-java8</artifactId>
</exclusion>
<exclusion>
<groupId>androidx.core</groupId>
<artifactId>core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-android-ndk</artifactId>
<version>5.7.0</version>
<type>aar</type>
<exclusions>
<exclusion>
<groupId>io.sentry</groupId>
<artifactId>sentry-android-core</artifactId>
</exclusion>
<exclusion>
<groupId>androidx.lifecycle</groupId>
<artifactId>lifecycle-process</artifactId>
</exclusion>
<exclusion>
<groupId>androidx.lifecycle</groupId>
<artifactId>lifecycle-common-java8</artifactId>
</exclusion>
<exclusion>
<groupId>androidx.core</groupId>
<artifactId>core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- runtime dependency of sentry -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx-controllers</groupId>
<artifactId>gdx-controllers-android</artifactId>
<version>2.2.3-SNAPSHOT</version>
<type>aar</type>
</dependency>
</dependencies>
<profiles>
<profile>
<id>android-debug</id>
<properties>
<packaging.type>apk</packaging.type>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.simpligility.maven.plugins</groupId>
<artifactId>android-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.2.2</version>
</dependency>
</dependencies>
<version>4.6.0</version>
<extensions>true</extensions>
<configuration>
<sign>
<debug>true</debug>
</sign>
<sdk>
<platform>26</platform>
</sdk>
<dexForceJumbo>true</dexForceJumbo>
<androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
<assetsDirectory>${project.basedir}/assets</assetsDirectory>
<resourceDirectory>${project.basedir}/res</resourceDirectory>
<nativeLibrariesDirectory>${project.basedir}/libs</nativeLibrariesDirectory>
<extractDuplicates>true</extractDuplicates>
<proguard>
<skip>false</skip>
<config>${project.basedir}/proguard.cfg</config>
</proguard>
<release>true</release>
<dexCompiler>d8</dexCompiler>
<d8>
<minApi>26</minApi>
<jvmArguments>
<argument>${build.min.memory}</argument>
<argument>${build.max.memory}</argument>
</jvmArguments>
</d8>
<dex>
<multi-dex>true</multi-dex>
<jvmArguments>
<argument>${build.min.memory}</argument>
<argument>${build.max.memory}</argument>
</jvmArguments>
<dexArguments>--min-sdk-version=26</dexArguments>
</dex>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>android-release-build</id>
<properties>
<packaging.type>apk</packaging.type>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.simpligility.maven.plugins</groupId>
<artifactId>android-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.2.2</version>
</dependency>
</dependencies>
<version>4.6.0</version>
<extensions>true</extensions>
<configuration>
<sign>
<debug>false</debug>
</sign>
<sdk>
<platform>26</platform>
</sdk>
<zipalign>
<verbose>false</verbose>
</zipalign>
<dexForceJumbo>true</dexForceJumbo>
<androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
<assetsDirectory>${project.basedir}/assets</assetsDirectory>
<resourceDirectory>${project.basedir}/res</resourceDirectory>
<nativeLibrariesDirectory>${project.basedir}/libs</nativeLibrariesDirectory>
<extractDuplicates>true</extractDuplicates>
<proguard>
<skip>false</skip>
<config>${project.basedir}/proguard.cfg</config>
</proguard>
<release>true</release>
<dexCompiler>d8</dexCompiler>
<d8>
<minApi>26</minApi>
<jvmArguments>
<argument>${build.min.memory}</argument>
<argument>${build.max.memory}</argument>
</jvmArguments>
</d8>
<dex>
<multi-dex>true</multi-dex>
<jvmArguments>
<argument>${build.min.memory}</argument>
<argument>${build.max.memory}</argument>
</jvmArguments>
<dexArguments>--min-sdk-version=26</dexArguments>
</dex>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>android-release-sign</id>
<properties>
<packaging.type>apk</packaging.type>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<id>signing</id>
<goals>
<goal>sign</goal>
<goal>verify</goal>
</goals>
<phase>package</phase>
<inherited>true</inherited>
<configuration>
<removeExistingSignatures>true</removeExistingSignatures>
<archiveDirectory />
<includes>
<include>${project.build.directory}/${project.build.finalName}.apk</include>
</includes>
<keystore>${sign.keystore}</keystore>
<alias>${sign.alias}</alias>
<storepass>${sign.storepass}</storepass>
<keypass>${sign.keypass}</keypass>
<verbose>true</verbose>
<arguments>
<argument>-sigalg</argument>
<argument>MD5withRSA</argument>
<argument>-digestalg</argument>
<argument>SHA1</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.simpligility.maven.plugins</groupId>
<artifactId>android-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard-base</artifactId>
<version>6.2.2</version>
</dependency>
</dependencies>
<version>4.6.0</version>
<inherited>true</inherited>
<configuration>
<sign>
<debug>false</debug>
</sign>
<zipalign>
<skip>false</skip>
<verbose>true</verbose>
<inputApk>${project.build.directory}/${project.build.finalName}.apk</inputApk>
<outputApk>${project.build.directory}/${project.build.finalName}-signed-aligned.apk</outputApk>
</zipalign>
</configuration>
<executions>
<execution>
<id>android-align</id>
<phase>package</phase>
<goals>
<goal>zipalign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>android-release-packaging</id>
<phase>package</phase>
<configuration>
<target>
<copy todir="${project.build.directory}/res">
<fileset dir="${basedir}/../forge-gui/" includes="LICENSE.txt" />
<fileset dir="${basedir}/../forge-gui/release-files/" includes="CONTRIBUTORS.txt" />
<fileset dir="${basedir}/../forge-gui/release-files/" includes="INSTALLATION.txt" />
<fileset dir="${basedir}/../forge-gui/release-files/" includes="ISSUES.txt" />
<fileset dir="${basedir}/../forge-gui/release-files/" includes="CHANGES.txt" />
<fileset dir="${basedir}/../forge-gui/release-files/" includes="GAMEPAD_README.txt" />
<fileset dir="${basedir}/../forge-gui/" includes="MANUAL.txt" />
<fileset dir="${basedir}/../forge-gui-mobile-dev/" includes="sentry.properties" />
<fileset dir="${basedir}/../forge-gui/">
<include name="res/**" />
<exclude name="res/cardsfolder/**" />
</fileset>
</copy>
<mkdir dir="${project.build.directory}/res/res/cardsfolder" />
<zip destfile="${project.build.directory}/res/res/cardsfolder/cardsfolder.zip" basedir="${basedir}/../forge-gui/res/cardsfolder" level="1" />
<zip destfile="${project.build.directory}/assets.zip" basedir="${project.build.directory}/res" level="1" />
<delete dir="${project.build.directory}/res" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>android-release-upload</id>
<properties>
<packaging.type>apk</packaging.type>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>1.8.1</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-commons-net</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>android-ftp</id>
<phase>package</phase>
<configuration>
<target>
<ftp action="mkdir" password="${cardforge.pass}" server="${cardforge.server}" userid="${cardforge.user}" passive="true" remotedir="maven/releases/forge/forge-gui-android/${alpha-version}/" />
<ftp password="${cardforge.pass}" server="${cardforge.server}" userid="${cardforge.user}" passive="true" remotedir="maven/releases/forge/forge-gui-android/${alpha-version}/">
<fileset dir="${project.build.directory}">
<include name="${project.build.finalName}-signed-aligned.apk" />
<include name="assets.zip" />
</fileset>
</ftp>
<ftp password="${cardforge.pass}" server="${cardforge.server}" userid="${cardforge.user}" passive="true" remotedir="maven/releases/forge/forge-gui-android/">
<fileset dir="${project.build.directory}/classes">
<include name="version.txt" />
</fileset>
</ftp>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -0,0 +1,128 @@
-dontobfuscate
-optimizationpasses 3
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable
## 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 <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)
##-libraryjars <java.home>/jmods/jdk.xml.dom.jmod(!**.jar;!module-info.class)
-dontwarn afu.org.checkerframework.**
-dontwarn io.netty.**
-dontwarn org.eclipse.jetty.**
-dontwarn com.thoughtworks.xstream.**
-dontwarn com.badlogic.gdx.**
-dontwarn org.apache.commons.**
-dontwarn org.apache.http.**
-dontwarn com.google.guava.**
-dontwarn com.google.common.**
-dontwarn com.google.gson.**
-dontwarn org.checkerframework.**
-dontwarn org.xmlpull.**
-dontwarn org.apache.log4j.**
-dontwarn org.fourthline.cling.**
-dontwarn org.seamless.http.**
-dontwarn org.seamless.xhtml.**
-dontwarn org.seamless.xml.**
-dontwarn org.seamless.util.**
-dontwarn org.seamless.swing.**
-dontwarn java.lang.management.**
-dontwarn java.awt.**
-dontwarn java.util.**
-dontwarn java.lang.**
-dontwarn java.net.**
-dontwarn java.nio.**
-dontwarn java.io.**
-dontwarn org.slf4j.**
-dontwarn ch.qos.logback.**
-dontwarn javax.**
-dontwarn org.apache.logging.log4j.**
-dontwarn module-info
-dontwarn io.sentry.logback.*
-dontwarn io.sentry.**
-dontwarn net.jpountz.**
## Support library
-dontwarn android.**
-dontwarn androidx.**
-dontwarn forge.**
-keep class forge.** { *; }
-keep class com.thoughtworks.xstream.** { *; }
-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 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.netty.util.internal.logging.** { *; }
-keep class net.jpountz.** { *; }
-keep class com.ray3k.** { *; }
-keepclassmembers class com.badlogic.gdx.backends.android.AndroidInput* {
<init>(com.badlogic.gdx.Application, android.content.Context, java.lang.Object, com.badlogic.gdx.backends.android.AndroidApplicationConfiguration);
}
-keepclassmembers class com.badlogic.gdx.physics.box2d.World {
boolean contactFilter(long, long);
void beginContact(long);
void endContact(long);
void preSolve(long, long);
void postSolve(long, long);
boolean reportFixture(long);
float reportRayFixture(long, float, float, float, float, float);
}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep public class * extends com.badlogic.gdx.Application
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepattributes LineNumberTable,SourceFile
# https://stackoverflow.com/a/32615580
-optimizations !class/unboxing/enum

View File

@@ -0,0 +1,12 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your
# project structure.
# Project target.
project.type=0
target=android-26

View File

@@ -0,0 +1,15 @@
cd ../forge-core
call mvn clean install
cd ../forge-net
call mvn clean install
cd ../forge-ai
call mvn clean install
cd ../forge-game
call mvn clean install
cd ../forge-gui
call mvn clean install
cd ../forge-gui-mobile
call mvn clean install
cd ../forge-gui-android
call mvn -U -B clean -P android-release-build,android-release-sign,android-release-upload install -Dsign.keystore=forge.keystore -Dsign.alias=Forge -Dsign.storepass=forge72 -Dsign.keypass=forge72 -Dcardforge.user=drdev@cardforge.org -Dcardforge.pass=W%GdM]_o7@wEUEJIvs
pause

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
</LinearLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#ffffff</color>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Forge</string>
</resources>

View File

@@ -0,0 +1,91 @@
package forge.app;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import forge.gui.GuiBase;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Launcher extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent main = new Intent(Launcher.this, Main.class);
main.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(main);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
final Handler handler = new Handler();
handler.postDelayed(() -> {
if ("text/plain".equals(type)) {
Uri textUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (textUri != null) {
try {
InputStream in = getContentResolver().openInputStream(textUri);
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder total = new StringBuilder();
for (String line; (line = r.readLine()) != null; ) {
total.append(line).append('\n');
}
GuiBase.getInterface().copyToClipboard(total.toString());
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
GuiBase.getInterface().copyToClipboard(intent.getStringExtra(Intent.EXTRA_TEXT));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, 1500);
}
finish();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
final Handler handler = new Handler();
handler.postDelayed(() -> {
if ("text/plain".equals(type)) {
Uri textUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (textUri != null) {
try {
InputStream in = getContentResolver().openInputStream(textUri);
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder total = new StringBuilder();
for (String line; (line = r.readLine()) != null; ) {
total.append(line).append('\n');
}
GuiBase.getInterface().copyToClipboard(total.toString());
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
GuiBase.getInterface().copyToClipboard(intent.getStringExtra(Intent.EXTRA_TEXT));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}, 1500);
}
}
}

View File

@@ -0,0 +1,544 @@
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.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.Context;
import android.content.Intent;
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.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
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.style.StyleSpan;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.WindowManager;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
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;
public class Main extends AndroidApplication {
AndroidAdapter Gadapter;
ArrayList<String> gamepads;
AndroidClipboard androidClipboard;
boolean hasLaunched;
private AndroidClipboard getAndroidClipboard() {
if (androidClipboard == null)
androidClipboard = new AndroidClipboard();
return androidClipboard;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gamepads = getGameControllers();
if (hasLaunched)
return;
hasLaunched = true;
//init Sentry
//SentryAndroid.init(this);
//get total device RAM in mb
ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
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);
}
private static boolean isTabletDevice(Context activityContext) {
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;
}
private void displayMessage(AndroidAdapter adapter, boolean ex, String msg){
TableLayout TL = new TableLayout(this);
TableRow row = new TableRow(this);
TableRow row2 = new TableRow(this);
TextView text = new TextView(this);
text.setGravity(Gravity.LEFT);
text.setTypeface(Typeface.SERIF);
String title="Forge needs Storage Permission 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"+
"(You can tap anywhere to exit and restart the app)\n\n";
if (ex) {
title = "Forge didn't initialize!\n";
steps = msg + "\n\n";
}
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};
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(this);
button.setText("Open App Details");
StateListDrawable states = new StateListDrawable();
states.addState(new int[] {android.R.attr.state_pressed}, gd2);
states.addState(new int[] { }, gd);
button.setBackground(states);
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);
});
row2.addView(button);
row2.setGravity(Gravity.CENTER);
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);
}
@Override
public void onBackPressed() {
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;
}
} 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, 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));
Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation);
initialize(Forge.getApp(getAndroidClipboard(), adapter, "", false, true, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName()));
displayMessage(adapter, 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));
Main.this.setRequestedOrientation(Main.this.getResources().getConfiguration().orientation);
initialize(Forge.getApp(getAndroidClipboard(), adapter, "", false, true, totalRAM, isTabletDevice, AndroidAPI, AndroidRelease, getDeviceName()));
displayMessage(adapter, 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)) {
FileUtil.writeFile(noMediaFile, "");
}
//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, "");
}
}
@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);
//am.killBackgroundProcesses(getApplicationContext().getPackageName());
}
@Override
protected void onPause()
{
super.onPause();
ForgePreferences prefs = FModel.getPreferences();
boolean minimizeonScreenLock = prefs != null && prefs.getPrefBoolean(ForgePreferences.FPref.UI_ANDROID_MINIMIZE_ON_SCRLOCK);
if (minimizeonScreenLock) {
// If the screen is off then the device has been locked
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
boolean isScreenOn = powerManager.isScreenOn();
if (!isScreenOn) {
this.moveTaskToBack(true);
// Minimize the app to the background...
}
}
}
//special clipboard that words on Android
private class AndroidClipboard implements com.badlogic.gdx.utils.Clipboard {
private final ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
@Override
public boolean hasContents() {
if (cm.getPrimaryClip().getItemCount() > 0) {
try {
return cm.getPrimaryClip().getItemAt(0).coerceToText(getContext()).length() > 0;
}
catch (Exception ex) {
return false;
}
}
return false;
}
@Override
public String getContents() {
if (cm.getPrimaryClip().getItemCount() > 0) {
try {
String text = cm.getPrimaryClip().getItemAt(0).coerceToText(getContext()).toString();
return Normalizer.normalize(text, Normalizer.Form.NFD);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
return "";
}
@Override
public void setContents(String contents0) {
cm.setPrimaryClip(ClipData.newPlainText("Forge", contents0));
}
}
private class AndroidAdapter implements IDeviceAdapter {
private final boolean isTablet;
private final ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
private String switchOrientationFile;
private AndroidAdapter(Context context) {
isTablet = (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
@Override
public boolean isConnectedToInternet() {
return Boolean.TRUE.equals(ThreadUtil.executeWithTimeout(() -> {
NetworkInfo activeNetworkInfo = connManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}, 2000)); //if can't determine Internet connection within two seconds, assume not connected
}
@Override
public boolean isConnectedToWifi() {
return Boolean.TRUE.equals(ThreadUtil.executeWithTimeout(() -> {
NetworkInfo wifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return wifi.isConnected();
}, 2000)); //if can't determine Internet connection within two seconds, assume not connected
}
@Override
public String getDownloadsDir() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/";
}
@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) {
e.printStackTrace();
}
return false;
}
@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();
}
}
@Override
public void exit() {
finish();
//ensure process fully killed
System.exit(0);
}
@Override
public boolean isTablet() {
return isTablet;
}
@Override
public void setLandscapeMode(boolean landscapeMode) {
//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 {
FileUtil.deleteFile(switchOrientationFile);
}
}
@Override
public void preventSystemSleep(final boolean preventSleep) {
// 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);
}
});
}
@Override
public void convertToJPEG(InputStream input, OutputStream output) {
Bitmap bmp = BitmapFactory.decodeStream(input);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, output);
}
@Override
public Pair<Integer, Integer> getRealScreenSize(boolean real) {
//app size
WindowManager windowManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
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)
display.getRealSize(size);
else
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
} else if (Build.VERSION.SDK_INT >= 14) {
try {
size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
} catch (Exception e) {
size.x = Gdx.graphics.getWidth();
size.y = Gdx.graphics.getHeight();
}
} else {
size.x = Gdx.graphics.getWidth();
size.y = Gdx.graphics.getHeight();
}
return Pair.of(size.x, size.y);
}
@Override
public ArrayList<String> getGamepads() {
return gamepads;
}
}
private ArrayList<String> getGameControllers() {
ArrayList<String> gameControllerDeviceIds = new ArrayList<String>();
int[] deviceIds = InputDevice.getDeviceIds();
for (int deviceId : deviceIds) {
InputDevice dev = InputDevice.getDevice(deviceId);
int sources = dev.getSources();
String devNameId = dev.getName()+"["+deviceId+"]";
// Verify that the device has gamepad buttons, control sticks, or both.
if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
|| ((sources & InputDevice.SOURCE_JOYSTICK)
== InputDevice.SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
if (!gameControllerDeviceIds.contains(devNameId)) {
gameControllerDeviceIds.add(devNameId);
}
}
}
return gameControllerDeviceIds;
}
public String getDeviceName() {
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
if (model.toLowerCase().startsWith(manufacturer.toLowerCase())) {
return capitalize(model);
} else {
return capitalize(manufacturer) + " " + model;
}
}
private String capitalize(String s) {
if (s == null || s.length() == 0) {
return "";
}
char first = s.charAt(0);
if (Character.isUpperCase(first)) {
return s;
} else {
return Character.toUpperCase(first) + s.substring(1);
}
}
}