Separate android initialization from Activity (#11891)

This commit is contained in:
Xander 2025-01-10 23:05:58 +00:00 committed by GitHub
parent c64197be1a
commit d14c93c4b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 2322 additions and 2159 deletions

View file

@ -55,6 +55,11 @@ android {
lint {
abortOnError false
}
compileOptions {
// our minSdk, lollipop (API 21) uses java 7
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {

View file

@ -16,7 +16,7 @@
# public *;
#}
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivity {
-keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivityComponent {
java.lang.String nativeGetHint(java.lang.String); # Java-side doesn't use this, so it gets minified, but C-side still tries to register it
java.lang.String clipboardGetText();
boolean clipboardHasText();

View file

@ -0,0 +1,15 @@
package org.libsdl.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marker annotation for {@link SDLActivityComponent} methods that correspond to
* events in {@link android.app.Activity}.
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface ActivityHook {
}

View file

@ -13,7 +13,7 @@ public class SDL {
// This function should be called first and sets up the native code
// so it can call into the Java classes
public static void setupJNI() {
SDLActivity.nativeSetupJNI();
SDLActivityComponent.nativeSetupJNI();
SDLAudioManager.nativeSetupJNI();
SDLControllerManager.nativeSetupJNI();
}
@ -22,7 +22,7 @@ public class SDL {
public static void initialize() {
setContext(null);
SDLActivity.initialize();
SDLActivityComponent.initialize();
SDLAudioManager.initialize();
SDLControllerManager.initialize();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,5 @@
package org.libsdl.app;
public interface SDLComponentReceiver {
void superOnBackPressed();
}

View file

@ -10,7 +10,6 @@ import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.VibratorManager;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
@ -682,7 +681,7 @@ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, i);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, i);
SDLActivity.onNativeMouse(0, action, x, y, false);
SDLActivityComponent.onNativeMouse(0, action, x, y, false);
consumed = true;
break;
@ -690,7 +689,7 @@ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
x = getEventX(event, i);
y = getEventY(event, i);
SDLActivity.onNativeMouse(0, action, x, y, checkRelativeEvent(event));
SDLActivityComponent.onNativeMouse(0, action, x, y, checkRelativeEvent(event));
consumed = true;
break;
@ -709,7 +708,7 @@ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
// BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4
int buttons = event.getButtonState() >> 4;
SDLActivity.onNativePen(event.getPointerId(i), buttons, action, x, y, p);
SDLActivityComponent.onNativePen(event.getPointerId(i), buttons, action, x, y, p);
consumed = true;
break;
}
@ -795,7 +794,7 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
@Override
public boolean supportsRelativeMouse() {
return (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */);
return (!SDLActivityComponent.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */);
}
@Override
@ -805,11 +804,11 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
@Override
public boolean setRelativeMouseEnabled(boolean enabled) {
if (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */) {
if (!SDLActivityComponent.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */) {
if (enabled) {
SDLActivity.getContentView().requestPointerCapture();
SDLActivityComponent.getContentView().requestPointerCapture();
} else {
SDLActivity.getContentView().releasePointerCapture();
SDLActivityComponent.getContentView().releasePointerCapture();
}
mRelativeModeEnabled = enabled;
return true;
@ -820,8 +819,8 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
@Override
public void reclaimRelativeMouseModeIfNeeded() {
if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) {
SDLActivity.getContentView().requestPointerCapture();
if (mRelativeModeEnabled && !SDLActivityComponent.isDeXMode()) {
SDLActivityComponent.getContentView().requestPointerCapture();
}
}

View file

@ -1,7 +1,6 @@
package org.libsdl.app;
import android.content.*;
import android.text.InputType;
import android.view.*;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@ -32,7 +31,7 @@ public class SDLDummyEdit extends View implements View.OnKeyListener
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return SDLActivity.handleKeyEvent(v, keyCode, event, ic);
return SDLActivityComponent.handleKeyEvent(v, keyCode, event, ic);
}
//
@ -45,8 +44,8 @@ public class SDLDummyEdit extends View implements View.OnKeyListener
// FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
// FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)
if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) {
SDLActivity.onNativeKeyboardFocusLost();
if (SDLActivityComponent.mTextEdit != null && SDLActivityComponent.mTextEdit.getVisibility() == View.VISIBLE) {
SDLActivityComponent.onNativeKeyboardFocusLost();
}
}
return super.onKeyPreIme(keyCode, event);

View file

@ -1,6 +1,5 @@
package org.libsdl.app;
import android.content.*;
import android.os.Build;
import android.text.Editable;
import android.view.*;
@ -37,7 +36,7 @@ public class SDLInputConnection extends BaseInputConnection
*/
if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (SDLActivity.onNativeSoftReturnKey()) {
if (SDLActivityComponent.onNativeSoftReturnKey()) {
return true;
}
}
@ -114,7 +113,7 @@ public class SDLInputConnection extends BaseInputConnection
for (offset = 0; offset < pendingText.length(); ) {
int codePoint = pendingText.codePointAt(offset);
if (codePoint == '\n') {
if (SDLActivity.onNativeSoftReturnKey()) {
if (SDLActivityComponent.onNativeSoftReturnKey()) {
return;
}
}

View file

@ -12,7 +12,6 @@ import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
@ -57,7 +56,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
setOnGenericMotionListener(SDLActivity.getMotionListener());
setOnGenericMotionListener(SDLActivityComponent.getMotionListener());
// Some arbitrary defaults to avoid a potential division by zero
mWidth = 1.0f;
@ -88,7 +87,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL", "surfaceCreated()");
SDLActivity.onNativeSurfaceCreated();
SDLActivityComponent.onNativeSurfaceCreated();
}
// Called when we lose the surface
@ -97,11 +96,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
Log.v("SDL", "surfaceDestroyed()");
// Transition to pause, if needed
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
SDLActivity.handleNativeState();
SDLActivityComponent.mNextNativeState = SDLActivityComponent.NativeState.PAUSED;
SDLActivityComponent.handleNativeState();
mIsSurfaceReady = false;
SDLActivity.onNativeSurfaceDestroyed();
SDLActivityComponent.onNativeSurfaceDestroyed();
}
// Called when the surface is resized
@ -110,7 +109,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
int format, int width, int height) {
Log.v("SDL", "surfaceChanged()");
if (SDLActivity.mSingleton == null) {
if (SDLActivityComponent.mSingleton == null) {
return;
}
@ -132,20 +131,20 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
} catch(Exception ignored) {
}
synchronized(SDLActivity.getContext()) {
synchronized(SDLActivityComponent.getContext()) {
// In case we're waiting on a size change after going fullscreen, send a notification.
SDLActivity.getContext().notifyAll();
SDLActivityComponent.getContext().notifyAll();
}
Log.v("SDL", "Window size: " + width + "x" + height);
Log.v("SDL", "Device size: " + nDeviceWidth + "x" + nDeviceHeight);
SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, density, mDisplay.getRefreshRate());
SDLActivity.onNativeResize();
SDLActivityComponent.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, density, mDisplay.getRefreshRate());
SDLActivityComponent.onNativeResize();
// Prevent a screen distortion glitch,
// for instance when the device is in Landscape and a Portrait App is resumed.
boolean skip = false;
int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
int requestedOrientation = SDLActivityComponent.mSingleton.mActivity.getRequestedOrientation();
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
if (mWidth > mHeight) {
@ -182,13 +181,13 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
}
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
SDLActivity.onNativeSurfaceChanged();
SDLActivityComponent.onNativeSurfaceChanged();
/* Surface is ready */
mIsSurfaceReady = true;
SDLActivity.mNextNativeState = SDLActivity.NativeState.RESUMED;
SDLActivity.handleNativeState();
SDLActivityComponent.mNextNativeState = SDLActivityComponent.NativeState.RESUMED;
SDLActivityComponent.handleNativeState();
}
// Window inset
@ -201,7 +200,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
WindowInsets.Type.tappableElement() |
WindowInsets.Type.displayCutout());
SDLActivity.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
SDLActivityComponent.onNativeInsetsChanged(combined.left, combined.right, combined.top, combined.bottom);
}
// Pass these to any child views in case they need them
@ -211,7 +210,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Key events
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return SDLActivity.handleKeyEvent(v, keyCode, event, null);
return SDLActivityComponent.handleKeyEvent(v, keyCode, event, null);
}
private float getNormalizedX(float x)
@ -255,12 +254,12 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values
// if we are. We'll leverage our existing mouse motion listener
SDLGenericMotionListener_API14 motionListener = SDLActivity.getMotionListener();
SDLGenericMotionListener_API14 motionListener = SDLActivityComponent.getMotionListener();
x = motionListener.getEventX(event, i);
y = motionListener.getEventY(event, i);
relative = motionListener.inRelativeMode();
SDLActivity.onNativeMouse(buttonState, action, x, y, relative);
SDLActivityComponent.onNativeMouse(buttonState, action, x, y, relative);
} else if (toolType == MotionEvent.TOOL_TYPE_STYLUS || toolType == MotionEvent.TOOL_TYPE_ERASER) {
pointerId = event.getPointerId(i);
x = event.getX(i);
@ -275,7 +274,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4, and apply SDL_PEN_INPUT_DOWN/SDL_PEN_INPUT_ERASER_TIP
int buttonState = (event.getButtonState() >> 4) | (1 << (toolType == MotionEvent.TOOL_TYPE_STYLUS ? 0 : 30));
SDLActivity.onNativePen(pointerId, buttonState, action, x, y, p);
SDLActivityComponent.onNativePen(pointerId, buttonState, action, x, y, p);
} else if (toolType == MotionEvent.TOOL_TYPE_FINGER) {
pointerId = event.getPointerId(i);
x = getNormalizedX(event.getX(i));
@ -287,7 +286,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
p = 1.0f;
}
SDLActivity.onNativeTouch(touchDevId, pointerId, action, x, y, p);
SDLActivityComponent.onNativeTouch(touchDevId, pointerId, action, x, y, p);
}
// Non-primary up/down
@ -349,12 +348,12 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
break;
}
if (newRotation != SDLActivity.mCurrentRotation) {
SDLActivity.mCurrentRotation = newRotation;
SDLActivity.onNativeRotationChanged(newRotation);
if (newRotation != SDLActivityComponent.mCurrentRotation) {
SDLActivityComponent.mCurrentRotation = newRotation;
SDLActivityComponent.onNativeRotationChanged(newRotation);
}
SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
SDLActivityComponent.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
y / SensorManager.GRAVITY_EARTH,
event.values[2] / SensorManager.GRAVITY_EARTH);
@ -374,14 +373,14 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, i);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, i);
SDLActivity.onNativeMouse(0, action, x, y, false);
SDLActivityComponent.onNativeMouse(0, action, x, y, false);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
case MotionEvent.ACTION_MOVE:
x = event.getX(i);
y = event.getY(i);
SDLActivity.onNativeMouse(0, action, x, y, true);
SDLActivityComponent.onNativeMouse(0, action, x, y, true);
return true;
case MotionEvent.ACTION_BUTTON_PRESS:
@ -398,7 +397,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
y = event.getY(i);
int button = event.getButtonState();
SDLActivity.onNativeMouse(button, action, x, y, true);
SDLActivityComponent.onNativeMouse(button, action, x, y, true);
return true;
}
}

View file

@ -12,7 +12,7 @@
"src/SDL.c",
"include/SDL3/SDL.h",
"test/testsprite.c",
"android-project/app/src/main/java/org/libsdl/app/SDLActivity.java"
"android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java"
],
"files": {
"include/SDL3": [

View file

@ -41,15 +41,15 @@ else
not_ok "CMakeLists.txt $version disagrees with SDL_version.h $ref_version"
fi
major=$(sed -ne 's/.*SDL_MAJOR_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java)
minor=$(sed -ne 's/.*SDL_MINOR_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java)
micro=$(sed -ne 's/.*SDL_MICRO_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java)
major=$(sed -ne 's/.*SDL_MAJOR_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java)
minor=$(sed -ne 's/.*SDL_MINOR_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java)
micro=$(sed -ne 's/.*SDL_MICRO_VERSION = \([0-9]*\);/\1/p' android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java)
version="${major}.${minor}.${micro}"
if [ "$ref_version" = "$version" ]; then
ok "SDLActivity.java $version"
ok "SDLActivityComponent.java $version"
else
not_ok "android-project/app/src/main/java/org/libsdl/app/SDLActivity.java $version disagrees with SDL_version.h $ref_version"
not_ok "android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java $version disagrees with SDL_version.h $ref_version"
fi
tuple=$(sed -ne 's/^ *FILEVERSION *//p' src/core/windows/version.rc | tr -d '\r')

View file

@ -58,9 +58,9 @@ fi
perl -w -pi -e 's/\A(project\(SDL[0-9]+ LANGUAGES C VERSION ")[0-9.]+/${1}'$NEWVERSION'/;' CMakeLists.txt
perl -w -pi -e 's/\A(.* SDL_MAJOR_VERSION = )\d+/${1}'$MAJOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
perl -w -pi -e 's/\A(.* SDL_MINOR_VERSION = )\d+/${1}'$MINOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
perl -w -pi -e 's/\A(.* SDL_MICRO_VERSION = )\d+/${1}'$MICRO'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
perl -w -pi -e 's/\A(.* SDL_MAJOR_VERSION = )\d+/${1}'$MAJOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java
perl -w -pi -e 's/\A(.* SDL_MINOR_VERSION = )\d+/${1}'$MINOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java
perl -w -pi -e 's/\A(.* SDL_MICRO_VERSION = )\d+/${1}'$MICRO'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivityComponent.java
perl -w -pi -e 's/(\#define SDL_MAJOR_VERSION\s+)\d+/${1}'$MAJOR'/;' include/SDL3/SDL_version.h
perl -w -pi -e 's/(\#define SDL_MINOR_VERSION\s+)\d+/${1}'$MINOR'/;' include/SDL3/SDL_version.h

View file

@ -118,7 +118,8 @@ Here's an explanation of the files in the Android project, so you can customize
src/main/res/ - directory holding resources for your application
src/main/res/mipmap-* - directories holding icons for different phone hardware
src/main/res/values/strings.xml - strings used in your application, including the application name
src/main/java/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. You should instead subclass this for your application.
src/main/java/org/libsdl/app/SDLActivityComponent.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. Most of the time you do not need to interact with this class directly. Instead, make your activity extend SDLActivity.java
src/main/java/org/libsdl/app/SDLActivity.java - an abstract android activity that uses SDLActivityComponent via composition.
Using the SDL3 Android Archive (.aar)

View file

@ -58,7 +58,7 @@
#define ENCODING_PCM_16BIT 2
#define ENCODING_PCM_FLOAT 4
// Java class SDLActivity
// Java class SDLActivityComponent
JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetVersion)(
JNIEnv *env, jclass cls);
@ -196,7 +196,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeFileDialog)(
JNIEnv *env, jclass jcls,
jint requestCode, jobjectArray fileList, jint filter);
static JNINativeMethod SDLActivity_tab[] = {
static JNINativeMethod SDLActivityComponent_tab[] = {
{ "nativeGetVersion", "()Ljava/lang/String;", SDL_JAVA_INTERFACE(nativeGetVersion) },
{ "nativeSetupJNI", "()I", SDL_JAVA_INTERFACE(nativeSetupJNI) },
{ "nativeInitMainThread", "()V", SDL_JAVA_INTERFACE(nativeInitMainThread) },
@ -559,7 +559,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
return JNI_VERSION_1_4;
}
register_methods(env, "org/libsdl/app/SDLActivity", SDLActivity_tab, SDL_arraysize(SDLActivity_tab));
register_methods(env, "org/libsdl/app/SDLActivityComponent", SDLActivityComponent_tab, SDL_arraysize(SDLActivityComponent_tab));
register_methods(env, "org/libsdl/app/SDLInputConnection", SDLInputConnection_tab, SDL_arraysize(SDLInputConnection_tab));
register_methods(env, "org/libsdl/app/SDLAudioManager", SDLAudioManager_tab, SDL_arraysize(SDLAudioManager_tab));
register_methods(env, "org/libsdl/app/SDLControllerManager", SDLControllerManager_tab, SDL_arraysize(SDLControllerManager_tab));
@ -696,7 +696,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl
!midSupportsRelativeMouse ||
!midOpenFileDescriptor ||
!midShowFileDialog) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivityComponent.java?");
}
checkJNIReady();
@ -2041,7 +2041,7 @@ void Android_JNI_HapticStop(int device_id)
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticStop, device_id);
}
// See SDLActivity.java for constants.
// See SDLActivityComponent.java for constants.
#define COMMAND_SET_KEEP_SCREEN_ON 5
bool SDL_SendAndroidMessage(Uint32 command, int param)