godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.17k stars 98 forks source link

Implement Android Toast in Godot 4 #11189

Closed llama-nl closed 4 days ago

llama-nl commented 6 days ago

Describe the project you are working on

The project involves enhancing Godot 4's support for Android-specific features by integrating Android Toast notifications. Android Toast is a lightweight and visually subtle notification system that displays brief messages to the user without blocking the interface or requiring additional input. This proposal is aimed at developers creating Android games or apps with Godot who need quick, non-intrusive feedback or information delivery mechanisms.

Describe the problem or limitation you are having in your project

Currently, Godot lacks a built-in way to display Android-native Toast messages. Developers either need to implement this functionality manually through custom Java code or forego it entirely, relying on workarounds such as in-game UI labels, which: • Are more obtrusive, • Require additional design work to match Android's native style, • Do not integrate seamlessly with the Android ecosystem. Integrating Toast functionality into Godot allows developers to: • Provide native Android user feedback (e.g., error messages, status updates) without creating custom UI. • Save time by not having to write external Java code. • Maintain a consistent experience with Android standards.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The proposal involves exposing a simple interface for displaying Toast notifications in Godot using Godot's Java Native Interface (JNI) bridge for Android. This functionality will be added as a core feature for Android exports in Godot.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

  1. JNI Bridge Code: The Android Java layer will include a static method to display Toast messages. This code will be part of the Android-specific platform code in Godot's engine source.
    // In Godot's Android Java layer
    public class GodotToast {
    public static void showToast(final String message, final int duration) {
        Activity activity = getActivity(); // Obtain current activity
        if (activity != null) {
            activity.runOnUiThread(() -> {
                Toast.makeText(activity, message, duration).show();
            });
        }
    }
    }
  2. Godot C++ Binding: The Godot C++ platform code will call the above Java method via JNI.
    
    #include <jni.h>

void AndroidToast_show(const String &message, int duration) { JNIEnv *env = get_jni_env(); if (!env) return;

jclass godotToastClass = env->FindClass("org/godotengine/godot/GodotToast");
jmethodID showToastMethod = env->GetStaticMethodID(godotToastClass, "showToast", "(Ljava/lang/String;I)V");

jstring jMessage = env->NewStringUTF(message.utf8().get_data());
env->CallStaticVoidMethod(godotToastClass, showToastMethod, jMessage, duration);
env->DeleteLocalRef(jMessage);
env->DeleteLocalRef(godotToastClass);

}

3. **Script-Level API:** A script API will be exposed for GDScript, allowing developers to trigger Toast messages from within their scripts.
```gdscript
class_name AndroidToast

static func show(message: String, duration: int = 0) -> void:
    if OS.get_name() == "Android":
        JavaClassWrapper.call_static("org/godotengine/godot/GodotToast", "showToast", message, duration)
  1. Usage in Godot: Developers can call AndroidToast.show("Hello, world!", 0) in their GDScript to display a Toast message on Android.

Mock-Up: The implementation would integrate seamlessly with Godot's existing platform-specific scripting capabilities. A developer might create a simple UI button in the Godot editor that triggers the following script:

func _on_button_pressed():
    AndroidToast.show("Button clicked!", 0)

This results in a native Android Toast message saying "Button clicked!" appearing on the device.

If this enhancement will not be used often, can it be worked around with a few lines of script?

This enhancement cannot be achieved directly in GDScript without JNI or external plugins. Developers would need to:

  1. Write custom Java code for each project.
  2. Rebuild the Android export templates to include their code. While possible, this is a time-consuming and error-prone process for something as simple as a Toast notification. A core implementation ensures ease of use and maintainability.

Is there a reason why this should be core and not an add-on in the asset library?

This feature is inherently tied to Android's native platform and relies on JNI calls, which are not easily handled through GDScript or a standalone asset. Including it as a core feature:

• Ensures seamless integration with Godot’s existing Android export pipeline. • Reduces boilerplate for Android developers. • Ensures future updates to Android and JNI are handled at the engine level without requiring external asset updates.

syntaxerror247 commented 6 days ago

I also recently needed toast notifications in my app and considered implementing them as a core feature. However, I decided against it because it would be limited to Android . Besides, toast notifications likely wouldn’t be used frequently enough to justify adding them to the core.

This functionality can be easily replicated using Godot's GUI nodes, such as a panel combined with a timer.

If you really want Android native toast messages, then Plugin would be the best option. There is already a plugin for this in Assets Library.

sockeye-d commented 6 days ago

I think this should be implemented in OS because other platforms have similar functionality

syntaxerror247 commented 6 days ago

@sockeye-d Can you please explain, what functionality other platforms have?

sockeye-d commented 6 days ago

Looking at SO threads it seems it's possible, and on desktop platforms it could be a push notification or simply not be supported at all

syntaxerror247 commented 6 days ago

@sockeye-d Toasts or similar functionality is not native to iOS, yes it can be created but then as I said above you can also replicate this using gui nodes. And push notifications are a completely different thing.

It's not like I am completely against this, as I said above my app also uses toasts. I am just hesitant because it's easy to implement it using plugins.

CC @m4gr3d @alex2782

Alex2782 commented 6 days ago

Looking at SO threads it seems it's possible

A comparable solution would be possible on any system (I think), it simply displays a label for a short time. (On desktop you could perhaps show a window without a title bar)

But in a game I would solve toast notifications directly with Godot so that it fits the design better and looks and behaves identically on every system. Also on Android (Android 5 to 15+ / Samsung OS etc.)

m4gr3d commented 4 days ago

Access to Android specific APIs is already possible in 4.4 via the bundled AndroidRuntimePlugin introduced in https://github.com/godotengine/godot/pull/97500, which leverages the fixes from https://github.com/godotengine/godot/pull/96182.

There were a few remaining bugs, so I've addressed them in https://github.com/godotengine/godot/pull/99492. Once that PR is merged, you should be able to run the following logic in GDScript to display a toast without any additional plugin:

var android_runtime = Engine.get_singleton("AndroidRuntime")
if android_runtime:
    var activity = android_runtime.getActivity()

    var toastCallable = func ():
        var ToastClass = JavaClassWrapper.wrap("android.widget.Toast")
        ToastClass.makeText(activity, "This is a test", 1).show()

    activity.runOnUiThread(android_runtime.createRunnableFromGodotCallable(toastCallable))
else:
    printerr("Unable to access android runtime")

Pointing out the obvious, this functionality is not limited to Toast, and allow access to any and all Android apis when running on an Android device. This should make it easier for devs targeting the Android platform to access and use its capabilities.

So give it a whirl, and let us know if you find additional bugs.

m4gr3d commented 4 days ago

@Alex2782 @syntaxerror247 I'd appreciate if you could take a look and help review https://github.com/godotengine/godot/pull/99492!