Skip to content

Commit

Permalink
android: Update to SDL 2.30.9, Android 14; fix Android 11+ support
Browse files Browse the repository at this point in the history
  • Loading branch information
asiekierka committed Nov 30, 2024
1 parent 0a30aa8 commit 2a03b90
Show file tree
Hide file tree
Showing 14 changed files with 353 additions and 204 deletions.
2 changes: 1 addition & 1 deletion arch/android/Makefile.deps
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ endif
# the android project from the new SDL release (SDL/android-project/app/src/...).
#

SDL_VERSION ?= 2.28.2
SDL_VERSION ?= 2.30.9
LIBOGG_VERSION ?= 1.3.5
LIBVORBIS_VERSION ?= 1.3.7
WGET ?= wget
Expand Down
9 changes: 5 additions & 4 deletions arch/android/project/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ android {
keyPassword keystoreProperties['keyPassword']
}
}
namespace "net.digitalmzx.megazeux"
ndkVersion "23.2.8568313"
compileSdkVersion 31
buildToolsVersion "30.0.3"
compileSdkVersion 34
buildToolsVersion "34.0.0"
defaultConfig {
if (buildAsApplication) {
applicationId "net.digitalmzx.megazeux"
}
minSdkVersion 16
targetSdkVersion 31
targetSdkVersion 34
versionCode 1
versionName "1.0"
externalNativeBuild {
Expand Down Expand Up @@ -62,7 +63,7 @@ android {
}

}
lintOptions {
lint {
abortOnError false
}

Expand Down
4 changes: 2 additions & 2 deletions arch/android/project/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="net.digitalmzx.megazeux"
android:installLocation="auto">

<!-- OpenGL ES 2.0 -->
Expand Down Expand Up @@ -30,6 +29,7 @@

<!-- Allow writing to external storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->
<!-- <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> -->
<!-- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> -->
Expand All @@ -42,7 +42,7 @@
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:name=".GameActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.os.Environment;
import android.provider.Settings;
import android.view.View;

import java.io.File;
Expand All @@ -37,20 +40,50 @@

public class MainActivity extends Activity
{
private static final int MANAGE_EXTERNAL_STORAGE_INTENT_CODE = 100;

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

if(Build.VERSION.SDK_INT >= 23)
// Ensure all necessary permissions are present
if(Build.VERSION.SDK_INT >= 30 /* Android 11.0 */)
{
if(!Environment.isExternalStorageManager())
{
try {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, MANAGE_EXTERNAL_STORAGE_INTENT_CODE);
} catch (Exception e) {
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivityForResult(intent, MANAGE_EXTERNAL_STORAGE_INTENT_CODE);
}
return;
}
}
else if(Build.VERSION.SDK_INT >= 23 /* Android 6.0 */)
{
if(checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000);
}
else
launchGame();
}

launchGame();
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(Build.VERSION.SDK_INT >= 30 /* Android 11.0 */)
{
if(requestCode == MANAGE_EXTERNAL_STORAGE_INTENT_CODE)
{
if (Environment.isExternalStorageManager())
launchGame();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,11 @@ private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterfa
final int XB1_IFACE_SUBCLASS = 71;
final int XB1_IFACE_PROTOCOL = 208;
final int[] SUPPORTED_VENDORS = {
0x03f0, // HP
0x044f, // Thrustmaster
0x045e, // Microsoft
0x0738, // Mad Catz
0x0b05, // ASUS
0x0e6f, // PDP
0x0f0d, // Hori
0x10f5, // Turtle Beach
Expand All @@ -284,6 +286,7 @@ private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterfa
0x24c6, // PowerA
0x2dc8, // 8BitDo
0x2e24, // Hyperkin
0x3537, // Gamesir
};

if (usbInterface.getId() == 0 &&
Expand Down Expand Up @@ -357,6 +360,12 @@ private void connectHIDDeviceUSB(UsbDevice usbDevice) {
private void initializeBluetooth() {
Log.d(TAG, "Initializing Bluetooth");

if (Build.VERSION.SDK_INT >= 31 /* Android 12 */ &&
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT");
return;
}

if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ &&
mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH");
Expand Down Expand Up @@ -582,7 +591,13 @@ public boolean openDevice(int deviceID) {
} else {
flags = 0;
}
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));
if (Build.VERSION.SDK_INT >= 33 /* Android 14.0 (U) */) {
Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION);
intent.setPackage(mContext.getPackageName());
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags));
} else {
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));
}
} catch (Exception e) {
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
HIDDeviceOpenResult(deviceID, false);
Expand Down
13 changes: 8 additions & 5 deletions arch/android/project/app/src/main/java/org/libsdl/app/SDL.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ public static Context getContext() {
}

public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
loadLibrary(libraryName, mContext);
}

public static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
if (libraryName == null) {
throw new NullPointerException("No library name provided.");
}
Expand All @@ -53,10 +56,10 @@ public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError,
// To use ReLinker, just add it as a dependency. For more information, see
// https://github.com/KeepSafe/ReLinker for ReLinker's repository.
//
Class<?> relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
Class<?> relinkListenerClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
Class<?> contextClass = mContext.getClassLoader().loadClass("android.content.Context");
Class<?> stringClass = mContext.getClassLoader().loadClass("java.lang.String");
Class<?> relinkClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker");
Class<?> relinkListenerClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener");
Class<?> contextClass = context.getClassLoader().loadClass("android.content.Context");
Class<?> stringClass = context.getClassLoader().loadClass("java.lang.String");

// Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if
// they've changed during updates.
Expand All @@ -66,7 +69,7 @@ public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError,

// Actually load the library!
Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass);
loadMethod.invoke(relinkInstance, mContext, libraryName, null, null);
loadMethod.invoke(relinkInstance, context, libraryName, null, null);
}
catch (final Throwable e) {
// Fall back
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 2;
private static final int SDL_MINOR_VERSION = 28;
private static final int SDL_MICRO_VERSION = 2;
private static final int SDL_MINOR_VERSION = 30;
private static final int SDL_MICRO_VERSION = 9;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
Expand Down Expand Up @@ -89,7 +89,7 @@ public static void debugSource(int sources, String prefix) {
| InputDevice.SOURCE_CLASS_POSITION
| InputDevice.SOURCE_CLASS_TRACKBALL);
if (s2 != 0) cls += "Some_Unkown";
if (s2 != 0) cls += "Some_Unknown";
s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class;
Expand Down Expand Up @@ -163,7 +163,7 @@ public static void debugSource(int sources, String prefix) {
if (s == FLAG_TAINTED) src += " FLAG_TAINTED";
s2 &= ~FLAG_TAINTED;
if (s2 != 0) src += " Some_Unkown";
if (s2 != 0) src += " Some_Unknown";
Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src);
}
Expand Down Expand Up @@ -281,7 +281,7 @@ protected String[] getLibraries() {
// Load the .so
public void loadLibraries() {
for (String lib : getLibraries()) {
SDL.loadLibrary(lib);
SDL.loadLibrary(lib, this);
}
}

Expand Down Expand Up @@ -995,8 +995,8 @@ public void setOrientationBis(int w, int h, boolean resizable, String hint)
/* No valid hint, nothing is explicitly allowed */
if (!is_portrait_allowed && !is_landscape_allowed) {
if (resizable) {
/* All orientations are allowed */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
/* All orientations are allowed, respecting user orientation lock setting */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
} else {
/* Fixed window and nothing specified. Get orientation from w/h of created window */
req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
Expand All @@ -1005,8 +1005,8 @@ public void setOrientationBis(int w, int h, boolean resizable, String hint)
/* At least one orientation is allowed */
if (resizable) {
if (is_portrait_allowed && is_landscape_allowed) {
/* hint allows both landscape and portrait, promote to full sensor */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
/* hint allows both landscape and portrait, promote to full user */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER;
} else {
/* Use the only one allowed "orientation" */
req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);
Expand Down Expand Up @@ -1345,23 +1345,6 @@ public static boolean handleKeyEvent(View v, int keyCode, KeyEvent event, InputC
}
}

if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (isTextInputEvent(event)) {
if (ic != null) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
} else {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
}
onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
onNativeKeyUp(keyCode);
return true;
}
}

if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
// they are ignored here because sending them as mouse input to SDL is messy
Expand All @@ -1376,6 +1359,21 @@ public static boolean handleKeyEvent(View v, int keyCode, KeyEvent event, InputC
}
}

if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (isTextInputEvent(event)) {
if (ic != null) {
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
} else {
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
}
}
onNativeKeyDown(keyCode);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
onNativeKeyUp(keyCode);
return true;
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,13 +546,15 @@ public void pollHapticDevices() {
if (haptic == null) {
InputDevice device = InputDevice.getDevice(deviceIds[i]);
Vibrator vib = device.getVibrator();
if (vib.hasVibrator()) {
haptic = new SDLHaptic();
haptic.device_id = deviceIds[i];
haptic.name = device.getName();
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
if (vib != null) {
if (vib.hasVibrator()) {
haptic = new SDLHaptic();
haptic.device_id = deviceIds[i];
haptic.name = device.getName();
haptic.vib = vib;
mHaptics.add(haptic);
SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion arch/android/project/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<style name="AppTheme" parent="android:Theme.NoTitleBar.Fullscreen">
<!-- Customize your theme here. -->
</style>

Expand Down
2 changes: 1 addition & 1 deletion arch/android/project/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.4'
classpath 'com.android.tools.build:gradle:8.7.2'

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Expand Down
Binary file modified arch/android/project/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 3 additions & 2 deletions arch/android/project/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#Sun May 02 07:03:49 EDT 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
Loading

0 comments on commit 2a03b90

Please sign in to comment.