Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Native Android backend + example #3446

Merged
merged 1 commit into from
Mar 4, 2021
Merged

Conversation

duddel
Copy link
Contributor

@duddel duddel commented Aug 31, 2020

I am working on a native Android backend with the goals of using the available OpenGL 3 renderer, and not having other dependencies (such as SDL).

The PR branch contains the native Android backend, an example app and CI integration (GitHub Actions). The Android app project itself is (I believe) as tiny as possible. It is a "modern" Android project, based on CMake and Gradle with small wrapper code written in Kotlin.

Progress: see backends/imgui_impl_android.cpp

Maybe this is useful to others.

device-2021-02-26-135247

@ocornut
Copy link
Owner

ocornut commented Sep 9, 2020

Hello @duddel, by the way sorry I haven't answered to this yet. I'm not familiar with Android but the whole PR looks nicely done and sane and up to dear imgui style/standards so I hope you get to keep working on that. I'll see if I can get some Android users to test this.

Do you know if there's a way we could avoid some of the gradle-related cruft (e.g. grapple-wrapper.jar) binary?

@duddel
Copy link
Contributor Author

duddel commented Sep 9, 2020

Hi @ocornut, thanks alot and no problem! I figured already, by reading related issues, that you are not an Android user. No need to hurry.

Concerning Gradle: I also find this a little bit disturbing, but providing the Gradle wrapper binary (gradle-wrapper.jar) and the gradlew scripts (gradlew, gradlew.bat) is the recommended way of executing Gradle builds: https://docs.gradle.org/current/userguide/gradle_wrapper.html

At least these files are auto-generated, and our build_android.sh ensures integrity of the wrapper by downloading and comparing a sha256 (also recommended by Gradle: https://docs.gradle.org/current/userguide/gradle_wrapper.html#wrapper_checksum_verification)

If things change in the future, and there is a simpler way of executing Gradle, I am happy to delete these files.

return 0;
}

// Unfortunately, the native KeyEvent implementation has no getUnicodeChar() function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can have if you try hard enough:

uint32_t Android_AInputEvent_GetUnicodeChar(JNIEnv* env, struct AInputEvent* event)
{
    if (event == NULL || (AInputEvent_getType(event) != AINPUT_EVENT_TYPE_KEY))
        return 0;

    //KeyEvent(long downTime, long eventTime, int action, int code, int repeat, int metaState, int deviceId, int scancode, int flags, int source)
    int64_t downTime  = AKeyEvent_getDownTime(event);
    int64_t eventTime = AKeyEvent_getEventTime(event);
    int32_t action    = AKeyEvent_getAction(event);
    int32_t code      = AKeyEvent_getKeyCode(event);
    int32_t repeat    = AKeyEvent_getRepeatCount(event);
    int32_t metaState = AKeyEvent_getMetaState(event);
    int32_t deviceId  = AInputEvent_getDeviceId(event);
    int32_t scancode  = AKeyEvent_getScanCode(event);
    int32_t flags     = AKeyEvent_getFlags(event);
    int32_t source    = AInputEvent_getSource(event);

    // Create an instance of android.view.KeyEvent.
    jclass      keyEventClass             = env->FindClass("android/view/KeyEvent");
    jmethodID   keyEventClassConstructor  = env->GetMethodID(keyEventClass, "<init>", "(JJIIIIIIII)V");
    jobject     keyEventObject            = env->NewObject(keyEventClass, keyEventClassConstructor,
        downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags, source);

    // Get unicode char.
    jmethodID   keyEventGetUnicodeChar    = env->GetMethodID(keyEventClass, "getUnicodeChar", "()I");
    int32_t unicodeChar = env->CallIntMethod(keyEventObject, keyEventGetUnicodeChar);

    // Release object
    env->DeleteLocalRef(keyEventObject);
    env->DeleteLocalRef(keyEventClass);

    return unicodeChar;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out. But still, this is not a native implementation for the KeyEvent.
I used this method before, but changed it in f8a0f03 to capturing KeyEvents in non-native code and let the characters be polled from the native side. This is less error prone, imo.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes native functions in NDK are plainly broken. Showing soft keyboard for example was not working. Maybe now it is, but on android-9 it was not. Often they're often not on par with Android SDK. Like choreographer was missing from NDK for a few releases. Using SDK API to translate key event into Unicode codepoint is safe operation. One may not like dealing with JNI, but this is the nature of the beast.

Out of curiosity, can you elaborate more on why do you think pooling key events from Java is less error prone? It is bypassing native input queue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My approach of reconstructing the KeyEvent via JNI and calling getUnicodeChar() was only able to capture ASCII characters. I was doubtful about the reconstructed KeyEvent holding enough information to safely get Unicode characters. I figured that calling it on the non-native KeyEvent (Java/Kotlin side) is the best shot.

Concerning the input queue: You are right, it is based on the assumption, that all KeyEvents reach our Activity via dispatchKeyEvent(). I did not find any information if this is guaranteed. Your Android_AInputEvent_GetUnicodeChar() solution looks more promising than mine (I constructed the KeyEvent with event_type and key_code only). I will have a look.

About showing the soft keyboard: Yes, no reliable way to do it in native code. That was the reason to extend the NativeActivity in the first place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this isn't that big of a deal here. Key events would be useful when physical keyboard is connected to device. Text input will probably need to be implemented using IME.

@frink
Copy link
Contributor

frink commented Sep 27, 2020

What does Android do if your keyboard is set to a foreign language?

@duddel
Copy link
Contributor Author

duddel commented Sep 27, 2020

What does Android do if your keyboard is set to a foreign language?

I used a physical keyboard and switched the keyboard layout in Android around. getUnicodeChar() returns characters based on the selected layout. So I strongly believe this is handled by Android... Or what do you mean by "keyboard is set to a foreign language"?

@frink
Copy link
Contributor

frink commented Sep 30, 2020

You mentioned it only handed ASCII so I was trying to understand how internationalization might work... You answered me I think...

@magenbluten
Copy link

magenbluten commented Sep 30, 2020 via email

@ocornut
Copy link
Owner

ocornut commented Feb 22, 2021

Hello @duddel,

Sorry for late answer. Going to try merging this soon.

Some feedback:

At least these files are auto-generated, and our build_android.sh ensures integrity of the wrapper by downloading and comparing a sha256 (also recommended by Gradle: https://docs.gradle.org/current/userguide/gradle_wrapper.html#wrapper_checksum_verification)

  • Since there's a script downloading the gradle binary and doing a checksum, can we consider removing some of those files from the repo and having the build script just download a specific version of the .jar file itself?

Small stuff

  • Rebasing this on master, squash + force-push
  • Add references/links in docs/EXAMPLES.md, docs/BACKENDS.ends, docs/README.md (for that last one, it's only adding an "Android" at the end of the list around line 120, after OSX).
  • Tweaking imgui_impl_android.h so HandleInputEvent is capitalized consistently with other functions (and move the * next to type for good measure).

Thank you!

@duddel duddel force-pushed the android_native branch 2 times, most recently from b652a5d to 3a3d642 Compare February 22, 2021 22:58
@duddel
Copy link
Contributor Author

duddel commented Feb 22, 2021

Hi @ocornut,

I fixed up a squashed rebase to master, hopefully correct.

Everything works fine (concerning Android). The Windows build seems to fail for the same reason as on master.

I incorporated your remarks. Just let me know if anything is still unfortunate.

Since there's a script downloading the gradle binary and doing a checksum, can we consider removing some of those files from the repo and having the build script just download a specific version of the .jar file itself?

Concerning Gradle: the committed gradle-wrapper.jar is responsible for downloading the actual Gradle binaries. Your idea of not providing the wrapper, but downloading it manually, is good. I checked it again. Unfortunately, they let you download the sha256 but not he wrapper itself.

The wrapper must be generated with an actual Gradle installation, and then should be committed (this is what I initially did). As I said, I am also not pleased with this procedure, but it is still the recommended way.

If you like, we can try to find another solution before merge. Maybe it is possible to use a provided Gradle installation on the GitHub Actions worker (but then losing the benefit of a fixed Gradle version via the wrapper, and complicating things for users).

Thanks again!

Copy link
Contributor

@thedmd thedmd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a few comments, which I think will improve this PR and help it blend with other ImGui examples.

Overall native application is very basic. Yet is is enough to show ImGui running on Android.

Thanks for making the effort! : )

backends/imgui_impl_android.cpp Outdated Show resolved Hide resolved
backends/imgui_impl_android.cpp Outdated Show resolved Hide resolved
backends/imgui_impl_android.cpp Outdated Show resolved Hide resolved
backends/imgui_impl_android.cpp Outdated Show resolved Hide resolved
backends/imgui_impl_android.cpp Outdated Show resolved Hide resolved
examples/example_android_opengl3/android/build.gradle Outdated Show resolved Hide resolved
// Therefore, we call showSoftInput() of the main activity implemented in MainActivity.kt via JNI.
static int showSoftInput()
{
JavaVM *jVM = g_App->activity->vm;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JNIEnv* for native thread can be fetched, attached and detached in android_main() function.
This will speed up JNI calls. Local references will need to be explicitly released in this case.

It is helpful if functions making JNI calls accept JNIEnv* as a first argument. This will make them reentrant and possible to call from Java callbacks.

Functions in current example will work, but need to be reworked every time someone decide to take this example as a starting point.

No change is necessary. I wanted everyone to be aware of this potential pitfall.

ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
io.IniFilename = NULL;
ImGui::StyleColorsDark();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you consider importing fonts to be on pair with other examples?

assets could be utilized for that purpose. This can greatly improve readability of the UI. Default one is tiny and very hard to see on modern phone.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fonts can now be loaded from assets/. I prepared a function add_font_from_assets_ttf() for that and copied/adjusted the default comment block from other examples.

case APP_CMD_SAVE_STATE:
break;
case APP_CMD_INIT_WINDOW:
init(app);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider adding ANativeWindow_acquire and ANativeWindow_release to avoid situations where Java thread release app->window object but native app sill use it a valid object, because APP_CMD_TERM_WINDOW was not yet processed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ANativeWindow_acquire() in init() and ANativeWindow_release() in shutdown().
I am not entirely sure if it has an effect here, but it shouldn't harm either. This is rarely used in any NDK examples I have seen, but I keep my eyes open.

@duddel
Copy link
Contributor Author

duddel commented Feb 24, 2021

Thanks alot, I will have a look at your remarks!

After all, I also plan to remove the Gradle wrapper to unclutter the repo.

@duddel
Copy link
Contributor Author

duddel commented Feb 26, 2021

Incorporated most of the remarks. Tested on multiple devices including font loading.
Let me know if there is anything else.
Thanks!

@ocornut
Copy link
Owner

ocornut commented Mar 2, 2021

Thank you very much for the update.

Some extra feedback, sorry there were missing from previous batch of feedbacks:

(1) In the header of the imgui_impl_android.cpp and imgui_impl_android.h I would suggest listing the missing features( (by looking at e.g. win32, glfw backend). It's fine if they are not all implemented in native Android backend today but we'd want that list as explicit documentation.

I would add:

//  [ ] Platform: Clipboard support.
//  [ ] Platform: Gamepad support.

I would suggest NOT adding:

//  [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.

But only add it if/when mouse support gets added later.

(2) Headers <ctime> -> <time.h>

(3) Headers using <map> and <queue> seems a like overkill there but I understand the reasoning for now.
I would suggest to add a comment at the end of the g_KeyEventQueues declaration, e.g. // FIXME: Remove dependency on map and queue once we use upcoming input queue. Also similar FIXMEcomment under the// Process queued key events` line.

Skimming at it, it seems like your queuing mechanism has an issue, A-down, A-up, B-down will be seen by core dear imgui as A-down, B-down ... A-up which depending on the context and key sequence might be problematic or not. But different backends have similar issues with mouse button. I'm fine with either leaving this as is with a comment waiting for Input Queue, OR, if you can think of a larger issue it might make sense to use a dumber ImVector and process that in sequence (but then you'd quickly fall into the hole of reimplementing the queue... so maybe best to ignore for now).

(4) // todo: any reasonable io.BackendFlags?
I checked and don't think there are here so you can remove that line now.
(Generally speaking prefer using a FIXME marker to standardize grepping those)

(5) // intended fallthrough...
Even though it is perfectly legal I've seen compilers zealously warn about this and in my experience it was just simpler to avoid it and duplicate the line, as we aim to have this code compile in a maximum of scenarios.

(6) Example: wouldn't the add_font_from_assets_ttf() helper be best expressed as a GetAssetData() helper that only returned data + size, and let the user code call both lines? So we're providing a thinner/more flexible helper.

(7) Could the showSoftInput() machinery in the example, or part of it, be handled by the backend?
Otherwise, could/should the backend provide helpers to call, or have additional comments?

(8) Same question for the unicode char machinery. Could part of it be handled by the backend?

Both 7 and 8 may be naive and I presume tricky, but this is also what the backend value should be (in theory).

Thank you again!

@duddel
Copy link
Contributor Author

duddel commented Mar 2, 2021

Hi, thanks for the comments.

I made some changes

(1) In the header of the imgui_impl_android.cpp and imgui_impl_android.h I would suggest listing the missing features [...]

Synchronized (missing) features with other examples. I left "Mouse cursor shape and visibility" in place because mouse input is now added too, and maybe it is possible to even change the cursor shape on Android in the future.

(2) Headers <ctime> -> <time.h>

ok.

(3) Headers using <map> and <queue> seems a like overkill there but I understand the reasoning for now. [...]

I added a few comment and look forward of using the ImGui input queue. You are right about the maybe-changed order of key presses ImGui recieves. But I didn't come across a case where it interfered the input. Overall, this thing is cumbersome and I will delete it with joy, once the input queue is ready :)

(4) // todo: any reasonable io.BackendFlags?

ok. changed todos to FIXME

(5) // intended fallthrough...

ok. I left the "trivial" fallthroughs (merging multiple cases, identical code) in place.

(6) Example: wouldn't the add_font_from_assets_ttf() helper be best expressed as a GetAssetData() helper that only returned data + size, and let the user code call both lines? So we're providing a thinner/more flexible helper.

Yes, I changed the helper function. It is cleaner this way, although a few more lines for the user.

(7) Could the showSoftInput() machinery in the example, or part of it, be handled by the backend?
Otherwise, could/should the backend provide helpers to call, or have additional comments?

(8) Same question for the unicode char machinery. Could part of it be handled by the backend?

Both 7 and 8 may be naive and I presume tricky, but this is also what the backend value should be (in theory).

Initially, I had it that way, but put these functions into the user code (main.cpp) to make a cleaner separation.
Now, the backend only depends on the Android native window class (ANativeWindow). This is actually enough for an app without the need of text input. If we move the code into the backend, it also depends on a couple of things (from the native app, or native Activity) to call the Kotlin methods. Also, the Kotlin wrapper code itself would be a dependency.
Furthermore, it is now easier for a user to implement a custom soft-keyboard solution for text input, rather then using the default keyboard.

Overall, I prefer to leave it like that, for now.

Thanks again!

@ocornut
Copy link
Owner

ocornut commented Mar 4, 2021

Thanks for the update.
This is now merged + made minor amends (8dd692c)

Initially, I had it that way, but put these functions into the user code (main.cpp) to make a cleaner separation.
Now, the backend only depends on the Android native window class (ANativeWindow). This is actually enough for an app without the need of text input. If we move the code into the backend, it also depends on a couple of things (from the native app, or native Activity) to call the Kotlin methods. Also, the Kotlin wrapper code itself would be a dependency.

OK for now, I guess we can always revisit if needed.

@duddel
Copy link
Contributor Author

duddel commented Mar 4, 2021

Thanks for the update.
This is now merged + made minor amends (8dd692c)

Great! Thank you very much.
I will continue to look into this backend. Especially the unfortunate need of the JNI code for Unicode input/Soft keyboard.

One small thing: The Changelog says

But the example is actually set up for GL ES3. If one desires ES2 compatibility, this should be possible with a couple of small tweaks.

duddel added a commit to duddel/imgui that referenced this pull request Mar 4, 2021
commit ee643b2
Author: ocornut <[email protected]>
Date:   Thu Mar 4 19:59:59 2021 +0100

    IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using either... (ocornut#3851, ocornut#1370)

    ...when the hovered location is located within a child window, e.g. InputTextMultiline().
    This is intended to have no side effects, but brace yourself for the possible comeback..
    This essentially makes IsItemHovered() not accept hover from child windows, but EndChild/EndGroup are forwarded.
    More or less should fix/revert c76f014 which was a revert of 344d48b

commit b53b8f5
Author: Rokas Kupstys <[email protected]>
Date:   Thu Mar 4 16:27:43 2021 +0200

    Demo: Use correct string formats on non-windows platforms.

    (amended)

commit 3e6dfd3
Author: ocornut <[email protected]>
Date:   Thu Mar 4 13:37:14 2021 +0100

    ImDrawList: AddImageRounded() compare texid from cmdheader as with other functions. + Made the ImGuiMemAllocFunc / ImGuiMemFreeFunc consistent with our other typedefs (ocornut#3836)

commit 8dd692c
Author: ocornut <[email protected]>
Date:   Thu Mar 4 11:03:40 2021 +0100

    Android: Amend backend and examples with minor consistency tweaks. (ocornut#3446)

commit fb85c03
Author: duddel <[email protected]>
Date:   Thu Mar 4 10:35:44 2021 +0100

    Add Android backend and example (ocornut#3446)

commit d8c88bd
Author: ocornut <[email protected]>
Date:   Thu Mar 4 09:52:00 2021 +0100

    Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (ocornut#3872)

    ImSpanAllocator: Support for alignment.

commit 1ddaff8
Author: ocornut <[email protected]>
Date:   Wed Mar 3 18:45:52 2021 +0100

    Demo: Tweak inputs display.
@ocornut
Copy link
Owner

ocornut commented Apr 14, 2021

Android build started failing today, seemingly because of a Gradle update?
https://github.com/ocornut/imgui/runs/2343351753?check_suite_focus=true

May be:

> Configure project :app
WARNING: Support for ANDROID_NDK_HOME is deprecated and will be removed in the future. Use android.ndkVersion in build.gradle instead.
Support for ANDROID_NDK_HOME is deprecated and will be removed in the future. Use android.ndkVersion in build.gradle instead.
Observed package id 'ndk;21.4.7075529' in inconsistent location '/usr/local/lib/android/sdk/ndk-bundle' (Expected '/usr/local/lib/android/sdk/ndk/21.4.7075529')
[...]
 FAILURE: Build failed with an exception.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
[...]
 > Failed to query the value of task ':app:compileDebugJavaWithJavac' property 'options.generatedSourceOutputDirectory'.
   > Querying the mapped value of map(java.io.File property(org.gradle.api.file.Directory, fixed(class org.gradle.api.internal.file.DefaultFilePropertyFactory$FixedDirectory, /home/runner/work/imgui/imgui/examples/example_android_opengl3/android/app/build/generated/ap_generated_sources/debug/out)) org.gradle.api.internal.file.DefaultFilePropertyFactory$ToFileTransformer@8973893) before task ':app:compileDebugJavaWithJavac' has completed is not supported

@duddel
Copy link
Contributor Author

duddel commented Apr 14, 2021

Yes, for some reason, the GitHub Actions worker on master runs with Gradle 7.0 (although they say it is Gradle 6.8.3 on ubuntu-18.04).

Yes, they updated to GitHub Actions worker ubuntu-18.04 to Gradle 7.0 (was Gradle 6.8.3).

I made the Android build compatible with Gradle 7.0 in a branch: duddel@dc74b00

I updated the Android Gradle Plugin (AGP) to version 4.1.0 (current stable), which is compatible with Gradle 7.0. The AGP version must stay in sync with Gradle, so future changes on the Actions workers might require changes in the Gradle config in our project.

see:

@ocornut
Copy link
Owner

ocornut commented Apr 26, 2021

Thank you @duddel, I confirm that merging the commit you linked fixed CI for us.

@hhchun
Copy link

hhchun commented Jun 21, 2021

When I clone it and run it after compilation, the following error will be reported
2021-06-21 12:52:06.230 5801-5816/imgui.example.android E/EGL_emulation: eglCreateContext: EGL_BAD_CONFIG: no ES 3 support
2021-06-21 12:52:06.230 5801-5816/imgui.example.android E/EGL_emulation: tid 5816: eglCreateContext(1404): error 0x3005 (EGL_BAD_CONFIG)
2021-06-21 12:52:06.230 5801-5816/imgui.example.android E/ImGuiExample: eglCreateContext() returned EGL_NO_CONTEXT
2021-06-21 12:52:06.245 5801-5816/imgui.example.android E/libEGL: eglMakeCurrent:758 error 3009 (EGL_BAD_MATCH)
2021-06-21 12:52:06.245 5801-5816/imgui.example.android E/libEGL: call to OpenGL ES API with no current context (logged once per thread)

--------- beginning of crash

2021-06-21 12:52:06.245 5801-5816/imgui.example.android A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 5816 (example.android)

@duddel
Copy link
Contributor Author

duddel commented Jun 21, 2021

When I clone it and run it after compilation, the following error will be reported
2021-06-21 12:52:06.230 5801-5816/imgui.example.android E/EGL_emulation: eglCreateContext: EGL_BAD_CONFIG: no ES 3 support
2021-06-21 12:52:06.230 5801-5816/imgui.example.android E/EGL_emulation: tid 5816: eglCreateContext(1404): error 0x3005 (EGL_BAD_CONFIG)
2021-06-21 12:52:06.230 5801-5816/imgui.example.android E/ImGuiExample: eglCreateContext() returned EGL_NO_CONTEXT
2021-06-21 12:52:06.245 5801-5816/imgui.example.android E/libEGL: eglMakeCurrent:758 error 3009 (EGL_BAD_MATCH)
2021-06-21 12:52:06.245 5801-5816/imgui.example.android E/libEGL: call to OpenGL ES API with no current context (logged once per thread)

--------- beginning of crash

2021-06-21 12:52:06.245 5801-5816/imgui.example.android A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 5816 (example.android)

Basically, it is what it says: "no ES 3 support". The example app requires GL ES 3 (not 2), which your device (or emulator) does not support.

@skdevil602
Copy link

Hlo bro can u give me imgui android studio project
Working on android using opengl3
Because when I build the project imgui doesn't renders
Plzz if can help than help me

@ocornut
Copy link
Owner

ocornut commented Feb 21, 2023

FYI CI for this started failing a few days ago since Gradle 8.0:
https://github.com/ocornut/imgui/actions/runs/4230958001/jobs/7348899624
Anyone fancy fixing the example for Gradle ?

@duddel
Copy link
Contributor Author

duddel commented Feb 24, 2023

FYI CI for this started failing a few days ago since Gradle 8.0: https://github.com/ocornut/imgui/actions/runs/4230958001/jobs/7348899624 Anyone fancy fixing the example for Gradle ?

I will have a look asap, will fix it by next tuesday.

@duddel duddel mentioned this pull request Mar 7, 2023
@BrunoLevy
Copy link

BrunoLevy commented Jul 20, 2023

Hello,
About translating key input into unicode and displaying the on-screen keyboard when needed, I have developed C++ functions that call the Java API through JNI android_utils.h android_utils.cpp, it sufficiently small and self-contained to be integrated in imgui_impl_android.cpp.
With it you can have fully functional ImGui under Android (without writing a single line of Java !)
If you are interested, I can file a pull request.
I have also a couple of shell scripts to help creating an android app here (specialized for my Geogram lib, but could be made more generic if need be)

@ocornut
Copy link
Owner

ocornut commented Jul 20, 2023

Looks great, it could be useful (with some minor stylistic tweaks), but license is not MIT and you may not be owner, so I don't know how that would work?

@BrunoLevy
Copy link

I am owner and OK to add MIT license to this file.

@ocornut
Copy link
Owner

ocornut commented Jul 20, 2023

Then I think it would work and could be helpful to improve the Android backend. Thanks!
Assuming your code is "stable" (in the sense that you've used it enough to know it generally work), would you mind if the version in imgui_impl_android was a little more compact? (calls on a single line), with perhaps reference to the original source if desired.

This Android backend in general has been a little bit neglected :(
One reason being that I personally never used it (would be useful if I knew how to setup a dev env and an emulator).

@BrunoLevy
Copy link

  • yes, I have been using this code for a while, and tested it on different phones, so I am reasonably confident.
  • about code formatting, no problem ! (my own code is formatted with 80 characters max lines, but it is not a religion, I will adapt it to Imgui style)

@duddel
Copy link
Contributor Author

duddel commented Jul 20, 2023

Hi @BrunoLevy, this sounds interesting! I love to see a pure-native implementation for the key input and unicode mess. The current detour to the Kotlin code, and back, is unfortunate.

@BrunoLevy
Copy link

BrunoLevy commented Jul 22, 2023

Hi, I'm working on that, and will submit a PR, before then I'm adapting everything to the new event-queue-based system,
my current backend here directly changes io.MousePos (not good).

I tried with your backend. Everything mostly works, except a little problem: when a menu is open and you click somewhere else then everything gets stuck, probably because fingers do not send hovering events, I'm investigating.

I'm testing with my own app here, and will also test with the android example bundled with Dear ImGui. How do you build it ? (it has no gradlew, tried to write my own without success).

@duddel
Copy link
Contributor Author

duddel commented Jul 22, 2023

We decided to go without the Gradle wrapper und use the stock Gradle, that comes with the GitHub Actions runner, instead (recently changed to Gradle 8.x, see #6229). You can do the same thing locally (just call gradle assembleDebug instead of gradlew), or let Android Studio create a Wrapper for you.

Curious how your adaptions will work out.

@BrunoLevy
Copy link

I'm mostly there: I could replace my old backend with the new one, and insert calls the the JNI functions to show/hide the soft keyboard and translate the keys. I tested it with the soft keyboard and a BT keyboard, with different layouts, and it works well.

Now there are two options:

  • insert all my android_utils functions into imgui_impl_android.cpp
    • pro: I think it is a good thing to have only one .h/.cpp pair per backend
    • con: it is 500 lines of code or so
  • keep android_utils in a separate file (MIT license, imgui formatting style)
    • pro: easier to maintain, to update
    • con: probably not a good thing if each backend starts to spawn multiple files

What do you think ?

Two other questions:

  • should we expose the functions of android_utils in imgui_impl_android.h ?
  • there is also in android_utils a function to find the directory for temporary files, not used by the backend, but that may be useful for folks who write apps. Should I include it also ?

@nukadelic
Copy link

nukadelic commented Jan 24, 2024

I'm not too familiar with cpp or android , not sure if its the right place to ask but can anyone share a .so file ? Trying to include this framework into unity android build target , already tried a few different approaches but none seems to work so far , for reference : psydack/uimgui#50 (comment)

Really keen to get imgui working in native vr build , already created world space render and interaction bindings , works fine in the editor right now : https://imgur.com/fAW7WFc

@BrunoLevy
Copy link

In case it helps, explanations to compile geogram (that uses ImGui) with Android are here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants