diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index e7e5a2ac7..ff8ed76f6 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -52,6 +52,7 @@ 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; @@ -1630,6 +1631,52 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh } return 0; } + + /** + * This method is called by SDL using JNI. + */ + public static int showToast(String message, int duration, int gravity, int xOffset, int yOffset) + { + if(null == mSingleton) { + return - 1; + } + + try + { + class OneShotTask implements Runnable { + String mMessage; + int mDuration; + int mGravity; + int mXOffset; + int mYOffset; + + OneShotTask(String message, int duration, int gravity, int xOffset, int yOffset) { + mMessage = message; + mDuration = duration; + mGravity = gravity; + mXOffset = xOffset; + mYOffset = yOffset; + } + + public void run() { + try + { + Toast toast = Toast.makeText(mSingleton, mMessage, mDuration); + if (mGravity >= 0) { + toast.setGravity(mGravity, mXOffset, mYOffset); + } + toast.show(); + } catch(Exception ex) { + Log.e(TAG, ex.getMessage()); + } + } + } + mSingleton.runOnUiThread(new OneShotTask(message, duration, gravity, xOffset, yOffset)); + } catch(Exception ex) { + return -1; + } + return 0; + } } /** diff --git a/include/SDL_system.h b/include/SDL_system.h index 06ac41cd3..f0134417d 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -215,6 +215,22 @@ extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void); */ extern DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission); +/** + \brief Show android toast notification + + Show toast in UI thread [https://developer.android.com/guide/topics/ui/notifiers/toasts] + Params description + message : text message to be shown + duration : 0 - short [https://developer.android.com/reference/android/widget/Toast#LENGTH_SHORT], + 1 - long [https://developer.android.com/reference/android/widget/Toast#LENGTH_LONG] + gravity : the location at which the notification should appear on the screen. + It's an optional parameter. Set -1 if you don't want specify any gravity or + choose some value from https://developer.android.com/reference/android/view/Gravity + xOffset : set this parameter only when gravity >=0 + yOffset : set this parameter only when gravity >=0 +*/ +extern DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xOffset, int yOffset); + #endif /* __ANDROID__ */ /* Platform specific functions for WinRT */ diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 5831ea99b..a01787ea3 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -312,6 +312,7 @@ static jmethodID midManualBackButton; static jmethodID midMinimizeWindow; static jmethodID midOpenURL; static jmethodID midRequestPermission; +static jmethodID midShowToast; static jmethodID midSendMessage; static jmethodID midSetActivityTitle; static jmethodID midSetCustomCursor; @@ -591,6 +592,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl midMinimizeWindow = (*env)->GetStaticMethodID(env, mActivityClass, "minimizeWindow","()V"); midOpenURL = (*env)->GetStaticMethodID(env, mActivityClass, "openURL", "(Ljava/lang/String;)I"); midRequestPermission = (*env)->GetStaticMethodID(env, mActivityClass, "requestPermission", "(Ljava/lang/String;I)V"); + midShowToast = (*env)->GetStaticMethodID(env, mActivityClass, "showToast", "(Ljava/lang/String;IIII)I"); midSendMessage = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z"); midSetActivityTitle = (*env)->GetStaticMethodID(env, mActivityClass, "setActivityTitle","(Ljava/lang/String;)Z"); midSetCustomCursor = (*env)->GetStaticMethodID(env, mActivityClass, "setCustomCursor", "(I)Z"); @@ -621,6 +623,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl !midMinimizeWindow || !midOpenURL || !midRequestPermission || + !midShowToast || !midSendMessage || !midSetActivityTitle || !midSetCustomCursor || @@ -2468,6 +2471,11 @@ SDL_bool SDL_AndroidRequestPermission(const char *permission) return Android_JNI_RequestPermission(permission); } +int SDL_AndroidShowToast(const char* message, int duration, int gravity, int xOffset, int yOffset) +{ + return Android_JNI_ShowToast(message, duration, gravity, xOffset, yOffset); +} + void Android_JNI_GetManifestEnvironmentVariables(void) { if (!mActivityClass || !midGetManifestEnvironmentVariables) { @@ -2547,6 +2555,17 @@ SDL_bool Android_JNI_RequestPermission(const char *permission) return bPermissionRequestResult; } +/* Show toast notification */ +int Android_JNI_ShowToast(const char* message, int duration, int gravity, int xOffset, int yOffset) +{ + int result = 0; + JNIEnv *env = Android_JNI_GetEnv(); + jstring jmessage = (*env)->NewStringUTF(env, message); + result = (*env)->CallStaticIntMethod(env, mActivityClass, midShowToast, jmessage, duration, gravity, xOffset, yOffset); + (*env)->DeleteLocalRef(env, jmessage); + return result; +} + int Android_JNI_GetLocale(char *buf, size_t buflen) { AConfiguration *cfg; diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index 0fb07d615..7c4e3dbad 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -129,6 +129,9 @@ SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled); /* Request permission */ SDL_bool Android_JNI_RequestPermission(const char *permission); +/* Show toast notification */ +int Android_JNI_ShowToast(const char* message, int duration, int gravity, int xOffset, int yOffset); + int Android_JNI_OpenURL(const char *url); int SDL_GetAndroidSDKVersion(void); diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 4d698c60b..e32cd1fe6 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -766,6 +766,7 @@ #define SDL_GetPreferredLocales SDL_GetPreferredLocales_REAL #define SDL_SIMDRealloc SDL_SIMDRealloc_REAL #define SDL_AndroidRequestPermission SDL_AndroidRequestPermission_REAL +#define SDL_AndroidShowToast SDL_AndroidShowToast_REAL #define SDL_OpenURL SDL_OpenURL_REAL #define SDL_HasSurfaceRLE SDL_HasSurfaceRLE_REAL #define SDL_GameControllerHasLED SDL_GameControllerHasLED_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 8e67893a2..61437c8d0 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -826,6 +826,7 @@ SDL_DYNAPI_PROC(SDL_Locale *,SDL_GetPreferredLocales,(void),(),return) SDL_DYNAPI_PROC(void*,SDL_SIMDRealloc,(void *a, const size_t b),(a, b),return) #ifdef __ANDROID__ SDL_DYNAPI_PROC(SDL_bool,SDL_AndroidRequestPermission,(const char *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_AndroidShowToast,(const char* message, int duration, int gravity, int xOffset, int yOffset),(message,duration,gravity,xOffset,yOffset),return) #endif SDL_DYNAPI_PROC(int,SDL_OpenURL,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_HasSurfaceRLE,(SDL_Surface *a),(a),return)