forked from MoonsideGames/FAudioGMS
617 lines
18 KiB
Java
617 lines
18 KiB
Java
package org.libsdl.app;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.app.Dialog;
|
|
import android.app.UiModeManager;
|
|
import android.content.ClipboardManager;
|
|
import android.content.ClipData;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.pm.ActivityInfo;
|
|
import android.content.pm.ApplicationInfo;
|
|
import android.content.pm.PackageManager;
|
|
import android.content.res.Configuration;
|
|
import android.graphics.Bitmap;
|
|
import android.graphics.Color;
|
|
import android.graphics.PixelFormat;
|
|
import android.graphics.PorterDuff;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.hardware.Sensor;
|
|
import android.hardware.SensorEvent;
|
|
import android.hardware.SensorEventListener;
|
|
import android.hardware.SensorManager;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.os.Message;
|
|
import android.text.InputType;
|
|
import android.util.DisplayMetrics;
|
|
import android.util.Log;
|
|
import android.util.SparseArray;
|
|
import android.view.Display;
|
|
import android.view.Gravity;
|
|
import android.view.InputDevice;
|
|
import android.view.KeyEvent;
|
|
import android.view.MotionEvent;
|
|
import android.view.PointerIcon;
|
|
import android.view.Surface;
|
|
import android.view.SurfaceHolder;
|
|
import android.view.SurfaceView;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.Window;
|
|
import android.view.WindowManager;
|
|
import android.view.inputmethod.BaseInputConnection;
|
|
import android.view.inputmethod.EditorInfo;
|
|
import android.view.inputmethod.InputConnection;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
import android.widget.Button;
|
|
import android.widget.LinearLayout;
|
|
import android.widget.RelativeLayout;
|
|
import android.widget.TextView;
|
|
import android.widget.Toast;
|
|
|
|
import java.util.Hashtable;
|
|
import java.util.Locale;
|
|
|
|
/**
|
|
SDL Activity
|
|
*/
|
|
public class SDLActivity {
|
|
private static final String TAG = "yoyo";
|
|
|
|
public static boolean mIsResumedCalled, mHasFocus;
|
|
|
|
public static Locale mCurrentLocale;
|
|
|
|
// Handle the state of the native layer
|
|
public enum NativeState {
|
|
INIT, RESUMED, PAUSED
|
|
}
|
|
|
|
public static NativeState mNextNativeState;
|
|
public static NativeState mCurrentNativeState;
|
|
|
|
// Main components
|
|
public static SDLActivity mSingleton;
|
|
|
|
/**
|
|
* This method is called by SDL before loading the native shared libraries.
|
|
* It can be overridden to provide names of shared libraries to be loaded.
|
|
* The default implementation returns the defaults. It never returns null.
|
|
* An array returned by a new implementation must at least contain "SDL2".
|
|
* Also keep in mind that the order the libraries are loaded may matter.
|
|
* @return names of shared libraries to be loaded (e.g. "SDL2", "main").
|
|
*/
|
|
public String[] getLibraries() {
|
|
return new String[] {
|
|
"hidapi",
|
|
"SDL2",
|
|
"FAudioGMS"
|
|
};
|
|
}
|
|
|
|
// Load the .so
|
|
public void loadLibraries() {
|
|
for (String lib : getLibraries()) {
|
|
SDL.loadLibrary(lib);
|
|
}
|
|
}
|
|
|
|
public static void initialize() {
|
|
// The static nature of the singleton and Android quirkyness force us to initialize everything here
|
|
// Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
|
|
mSingleton = null;
|
|
mIsResumedCalled = false;
|
|
mHasFocus = true;
|
|
mNextNativeState = NativeState.INIT;
|
|
mCurrentNativeState = NativeState.INIT;
|
|
}
|
|
|
|
// Setup
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
Log.v(TAG, "Device: " + Build.DEVICE);
|
|
Log.v(TAG, "Model: " + Build.MODEL);
|
|
Log.v(TAG, "onCreate()");
|
|
|
|
try {
|
|
Thread.currentThread().setName("SDLActivity");
|
|
} catch (Exception e) {
|
|
Log.v(TAG, "modify thread properties failed " + e.toString());
|
|
}
|
|
|
|
// Load shared libraries
|
|
loadLibraries();
|
|
|
|
// Set up JNI
|
|
SDL.setupJNI();
|
|
|
|
// Initialize state
|
|
SDL.initialize();
|
|
|
|
// So we can call stuff from static callbacks
|
|
mSingleton = this;
|
|
}
|
|
|
|
public void pauseNativeThread() {
|
|
mNextNativeState = NativeState.PAUSED;
|
|
mIsResumedCalled = false;
|
|
|
|
SDLActivity.handleNativeState();
|
|
}
|
|
|
|
public void resumeNativeThread() {
|
|
mNextNativeState = NativeState.RESUMED;
|
|
mIsResumedCalled = true;
|
|
|
|
SDLActivity.handleNativeState();
|
|
}
|
|
|
|
// Events
|
|
public void onPause() {
|
|
Log.v(TAG, "onPause()");
|
|
pauseNativeThread();
|
|
}
|
|
|
|
public void onResume() {
|
|
Log.v(TAG, "onResume()");
|
|
resumeNativeThread();
|
|
}
|
|
|
|
public void onStop() {
|
|
Log.v(TAG, "onStop()");
|
|
pauseNativeThread();
|
|
}
|
|
|
|
public void onStart() {
|
|
Log.v(TAG, "onStart()");
|
|
resumeNativeThread();
|
|
}
|
|
|
|
public void onWindowFocusChanged(boolean hasFocus) {
|
|
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
|
|
|
|
mHasFocus = hasFocus;
|
|
if (hasFocus) {
|
|
mNextNativeState = NativeState.RESUMED;
|
|
SDLActivity.handleNativeState();
|
|
nativeFocusChanged(true);
|
|
} else {
|
|
nativeFocusChanged(false);
|
|
mNextNativeState = NativeState.PAUSED;
|
|
SDLActivity.handleNativeState();
|
|
}
|
|
}
|
|
|
|
public void onLowMemory() {
|
|
Log.v(TAG, "onLowMemory()");
|
|
SDLActivity.nativeLowMemory();
|
|
}
|
|
|
|
public void onConfigurationChanged(Configuration newConfig) {
|
|
Log.v(TAG, "onConfigurationChanged()");
|
|
|
|
if (mCurrentLocale == null || !mCurrentLocale.equals(newConfig.locale)) {
|
|
mCurrentLocale = newConfig.locale;
|
|
SDLActivity.onNativeLocaleChanged();
|
|
}
|
|
}
|
|
|
|
public void onDestroy() {
|
|
Log.v(TAG, "onDestroy()");
|
|
SDLActivity.nativeSendQuit();
|
|
SDLActivity.nativeQuit();
|
|
}
|
|
|
|
// Called by JNI from SDL.
|
|
public static void manualBackButton() {
|
|
}
|
|
|
|
/* Transition to next state */
|
|
public static void handleNativeState() {
|
|
if (mNextNativeState == mCurrentNativeState) {
|
|
// Already in same state, discard.
|
|
return;
|
|
}
|
|
|
|
// Try a transition to init state
|
|
if (mNextNativeState == NativeState.INIT) {
|
|
mCurrentNativeState = mNextNativeState;
|
|
return;
|
|
}
|
|
|
|
// Try a transition to paused state
|
|
if (mNextNativeState == NativeState.PAUSED) {
|
|
nativePause();
|
|
mCurrentNativeState = mNextNativeState;
|
|
Log.i("yoyo", "SDL - PAUSE!");
|
|
return;
|
|
}
|
|
|
|
// Try a transition to resumed state
|
|
if (mNextNativeState == NativeState.RESUMED) {
|
|
nativeResume();
|
|
mCurrentNativeState = mNextNativeState;
|
|
Log.i("yoyo", "SDL - RESUME!");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL if SDL did not handle a message itself.
|
|
* This happens if a received message contains an unsupported command.
|
|
* Method can be overwritten to handle Messages in a different class.
|
|
* @param command the command of the message.
|
|
* @param param the parameter of the message. May be null.
|
|
* @return if the message was handled in overridden method.
|
|
*/
|
|
public boolean onUnhandledMessage(int command, Object param) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* A Handler class for Messages from native SDL applications.
|
|
* It uses current Activities as target (e.g. for the title).
|
|
* static to prevent implicit references to enclosing object.
|
|
*/
|
|
public static class SDLCommandHandler extends Handler {
|
|
@Override
|
|
public void handleMessage(Message msg) {
|
|
}
|
|
}
|
|
|
|
// Handler for the messages
|
|
Handler commandHandler = new SDLCommandHandler();
|
|
|
|
// Send a message from the SDLMain thread
|
|
boolean sendCommand(int command, Object data) {
|
|
Message msg = commandHandler.obtainMessage();
|
|
msg.arg1 = command;
|
|
msg.obj = data;
|
|
boolean result = commandHandler.sendMessage(msg);
|
|
|
|
return result;
|
|
}
|
|
|
|
// C functions we call
|
|
public static native int nativeSetupJNI();
|
|
public static native int nativeRunMain(String library, String function, Object arguments);
|
|
public static native void nativeLowMemory();
|
|
public static native void nativeSendQuit();
|
|
public static native void nativeQuit();
|
|
public static native void nativePause();
|
|
public static native void nativeResume();
|
|
public static native void nativeFocusChanged(boolean hasFocus);
|
|
public static native void onNativeDropFile(String filename);
|
|
public static native void nativeSetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, float rate);
|
|
public static native void onNativeResize();
|
|
public static native void onNativeKeyDown(int keycode);
|
|
public static native void onNativeKeyUp(int keycode);
|
|
public static native boolean onNativeSoftReturnKey();
|
|
public static native void onNativeKeyboardFocusLost();
|
|
public static native void onNativeMouse(int button, int action, float x, float y, boolean relative);
|
|
public static native void onNativeTouch(int touchDevId, int pointerFingerId,
|
|
int action, float x,
|
|
float y, float p);
|
|
public static native void onNativeAccel(float x, float y, float z);
|
|
public static native void onNativeClipboardChanged();
|
|
public static native void onNativeSurfaceCreated();
|
|
public static native void onNativeSurfaceChanged();
|
|
public static native void onNativeSurfaceDestroyed();
|
|
public static native String nativeGetHint(String name);
|
|
public static native void nativeSetenv(String name, String value);
|
|
public static native void onNativeOrientationChanged(int orientation);
|
|
public static native void nativeAddTouch(int touchId, String name);
|
|
public static native void nativePermissionResult(int requestCode, boolean result);
|
|
public static native void onNativeLocaleChanged();
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean setActivityTitle(String title) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static void setWindowStyle(boolean fullscreen) {
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
* This is a static method for JNI convenience, it calls a non-static method
|
|
* so that is can be overridden
|
|
*/
|
|
public static void setOrientation(int w, int h, boolean resizable, String hint){
|
|
}
|
|
|
|
/**
|
|
* This can be overridden
|
|
*/
|
|
public void setOrientationBis(int w, int h, boolean resizable, String hint){
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static void minimizeWindow() {
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean shouldMinimizeOnFocusLoss() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean isScreenKeyboardShown(){
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean supportsRelativeMouse(){
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean setRelativeMouseEnabled(boolean enabled) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean sendMessage(int command, int param) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static Context getContext() {
|
|
return SDL.getContext();
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean isAndroidTV() {
|
|
return false;
|
|
}
|
|
|
|
public static double getDiagonal() {
|
|
return 0.0;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean isTablet() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean isChromebook() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean isDeXMode() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static DisplayMetrics getDisplayDPI() {
|
|
return getContext().getResources().getDisplayMetrics();
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean getManifestEnvironmentVariables() {
|
|
Log.i("yoyo", "sdl envvars req!");
|
|
nativeSetenv("SDL_ANDROID_BLOCK_ON_PAUSE", "1");
|
|
nativeSetenv("SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO", "1");
|
|
Log.i("yoyo", "sdl envvars ok!");
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean showTextInput(int x, int y, int w, int h) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static Surface getNativeSurface() {
|
|
return null;
|
|
}
|
|
|
|
// Input
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static void initTouch() {
|
|
}
|
|
|
|
// Messagebox
|
|
|
|
/** Result of current messagebox. Also used for blocking the calling thread. */
|
|
public final int[] messageboxSelection = new int[1];
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
* Shows the messagebox from UI thread and block calling thread.
|
|
* buttonFlags, buttonIds and buttonTexts must have same length.
|
|
* @param buttonFlags array containing flags for every button.
|
|
* @param buttonIds array containing id for every button.
|
|
* @param buttonTexts array containing text for every button.
|
|
* @param colors null for default or array of length 5 containing colors.
|
|
* @return button id or -1.
|
|
*/
|
|
public int messageboxShowMessageBox(
|
|
final int flags,
|
|
final String title,
|
|
final String message,
|
|
final int[] buttonFlags,
|
|
final int[] buttonIds,
|
|
final String[] buttonTexts,
|
|
final int[] colors) {
|
|
return -1;
|
|
}
|
|
|
|
public void messageboxCreateAndShow(Bundle args) {
|
|
}
|
|
|
|
private final Runnable rehideSystemUi = new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
}
|
|
};
|
|
|
|
public void onSystemUiVisibilityChange(int visibility) {
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean clipboardHasText() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static String clipboardGetText() {
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static void clipboardSetText(String string) {
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static int createCustomCursor(int[] colors, int width, int height, int hotSpotX, int hotSpotY) {
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean setCustomCursor(int cursorID) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static boolean setSystemCursor(int cursorID) {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static void requestPermission(String permission, int requestCode) {
|
|
if (Build.VERSION.SDK_INT < 23) {
|
|
nativePermissionResult(requestCode, true);
|
|
return;
|
|
}
|
|
|
|
Activity activity = (Activity)getContext();
|
|
if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
|
|
activity.requestPermissions(new String[]{permission}, requestCode);
|
|
} else {
|
|
nativePermissionResult(requestCode, true);
|
|
}
|
|
}
|
|
|
|
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
boolean result = (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED);
|
|
nativePermissionResult(requestCode, result);
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static int openURL(String url) {
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* This method is called by SDL using JNI.
|
|
*/
|
|
public static int showToast(String message, int duration, int gravity, int xOffset, int yOffset) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Simple runnable to start the SDL application
|
|
*/
|
|
class SDLMain implements Runnable {
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DISPLAY);
|
|
} catch (Exception e) {
|
|
Log.v("SDL", "modify thread properties failed " + e.toString());
|
|
}
|
|
}
|
|
}
|
|
|
|
class SDLInputConnection extends BaseInputConnection {
|
|
public SDLInputConnection(View targetView, boolean fullEditor) {
|
|
super(targetView, fullEditor);
|
|
|
|
}
|
|
|
|
public boolean sendKeyEvent(KeyEvent event) {
|
|
return false;
|
|
}
|
|
|
|
public boolean commitText(CharSequence text, int newCursorPosition) {
|
|
return false;
|
|
}
|
|
|
|
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
|
return false;
|
|
}
|
|
|
|
public static native void nativeCommitText(String text, int newCursorPosition);
|
|
|
|
public native void nativeGenerateScancodeForUnichar(char c);
|
|
|
|
public native void nativeSetComposingText(String text, int newCursorPosition);
|
|
|
|
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
|
return false;
|
|
}
|
|
}
|