Writing Android NDK Code with Elements

(RemObjects) #1

With our latest release of Elements 9.1 last week, we introduced support for native Android NDK apps.

This is a companion discussion topic for the original entry at http://blogs.remobjects.com/2017/06/02/writing-android-ndk-code-with-elements/

(Isral) #2

RemObjects Elements -
Using Silver Android I get:

  • Error (E46) Unknown identifier “__extern”
  • Error (E548) Unknown type “JNIEnv”, did you mean “rtl.JNIEnv”?
  • Error (E62) Type mismatch, cannot assign “String!” to "System.String!"
    Please provide zipped (*.zip) working solution.

(marc hoffman) #3

checking. this worked back when i wrote it, must be some regression in the latest beta

(marc hoffman) #4

It should be __external (fixing the blog), and yo do need to import rtl. I’ve logged an issue for the problem with the string assignment. thanx!

(RemObjects) #5

Thanks, logged as bugs://78107

(RemObjects) #6

bugs://78107 got closed with status fixed.

(Isral) #7

Which project setting that copy libhello-ndk.so into the apk?

(marc hoffman) #8

In the main Android app project, locate the “Android Native Libraries Folder” project setting, and point it to the output folder of the NDK project (it should be the folder that contains the per-archicture subfolders. and will probably be end in “Bin/Debug/Android”

(Isral) #9

Thanks, I choose armeabi before, but I should choose the parent of armeabi.

What is pragma globals?

What is the work around of @JNIExport?
Code below doesn’t work.

pragma globals on

import rtl

//@JNIExport(ClassName = “org.me.androidapp.MainActivity”)
public func Java_org_me_androidapp_MainActivity_HelloFromNDK(env: UnsafePointer!, this: jobject!) -> jstring! {
return (*(*env)).NewStringUTF(env, “Jade give two rides!”)

(marc hoffman) #10

#pragma globals allows you to have global methods

workaround is t use @SymbolName(), and manually mangle the name as described here: https://developer.android.com/ndk/samples/sample_hellojni.html


public func nameDoesntMatter(...

(Isral) #11

Fatal signal 11 (SIGSEGV), code 1, fault addr 0x5 in tid 10358 (g.me.androidapp)
Attached source code and logcat.
Android NDK.zip (33.7 KB)

(RemObjects) #12

Thanks, logged as bugs://78111

(RemObjects) #13

bugs://78111 got closed with status fixed.

(Isral) #14

The debugger won’t start.

Without debugger (tap on icon):
I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=org.me.androidapp cmp=org.me.androidapp/.MainActivity} from uid 1000 on display 0
I ActivityManager: Start proc 1944:org.me.androidapp/u0a205 for activity org.me.androidapp/.MainActivity
I art : Late-enabling -Xcheck:jni
W linker : /data/app/org.me.androidapp-2/lib/arm/libhellondk.so: is missing DT_SONAME will use basename as a replacement: "libhellondk.so"
E linker : “/data/app/org.me.androidapp-2/lib/arm/libhellondk.so”: ignoring DT_PREINIT_ARRAY in shared library!
E art : No implementation found for java.lang.String org.me.androidapp.MainActivity.HelloFromNDK() (tried Java_org_me_androidapp_MainActivity_HelloFromNDK and Java_org_me_androidapp_MainActivity_HelloFromNDK__)
D AndroidRuntime: Shutting down VM
E AndroidRuntime: FATAL EXCEPTION: main
E AndroidRuntime: Process: org.me.androidapp, PID: 1944
E AndroidRuntime: java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String org.me.androidapp.MainActivity.HelloFromNDK() (tried Java_org_me_androidapp_MainActivity_HelloFromNDK and Java_org_me_androidapp_MainActivity_HelloFromNDK__)
E AndroidRuntime: at org.me.androidapp.MainActivity.HelloFromNDK(Native Method)
E AndroidRuntime: at org.me.androidapp.MainActivity.onCreate(D:\Projects\Silver\Android NDK\org.me.androidapp\MainActivity.swift:18)
E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:6684)
E AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2637)
E AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2751)
E AndroidRuntime: at android.app.ActivityThread.-wrap12(ActivityThread.java)
E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1496)
E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
E AndroidRuntime: at android.os.Looper.loop(Looper.java:154)
E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6186)
E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
W ActivityManager: Force finishing activity org.me.androidapp/.MainActivity

(Isral) #15

Can you reproduce it?

(marc hoffman) #16

can’t say yet, given how it’s 8pm on a saturday ;)… we’ll have a look monday. you’re using .2169, right? can you send me your complete solution?


(Isral) #17

I’m sorry, I forget that now is weekend.
Same solution like before.

(Andrew Colburn) #18

Hello everyone.
I’m struggling with getting the .so library to work in my Android Studio project. I created an Android NDK Extension according to the guide above, compiled .so library and put it in my android project’s jniLibs folder. System.loadLibrary(…) seems to work fine, but whenever I call native method, the app crashes with “java.lang.UnsatisfiedLinkError: No implementation found for…” I tried @JNIExport and @SymbolName aspects - everything results in “No implementation found” error.
Maybe I’m missing something?

(marc hoffman) #19

could you post the project as it is now? what are you building this in, Fire, Water or Visual Studio, and with which version of Elements?

(Andrew Colburn) #20

I’m using RemObjects Fire with version of Elements. So basically my source code looks like follows:

import rtl
#pragma globals on
#hint Update the ClassName and function name below, to match your Android app
@JNIExport(ClassName = “com.example.andy.ndklib.MainActivity”)
public func FirstNDKFunction(env: UnsafePointer!, this: jobject!) -> jstring! {
return (*(*env)).NewStringUTF(env, “Hello from NDK!”)

And ofc in my Android Studio project the package where the MainActivity is is com.example.andy.ndklib with the function:

public static native String FirstNDKFunction();

NativeExtension.zip (1.2 MB)