golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.94k stars 17.53k forks source link

x/mobile/cmd/gomobile: No implementation found | Android #17359

Open vrabeux opened 7 years ago

vrabeux commented 7 years ago

Hi,

My environment :

I made a .aar file with gomobile bind -target android, and imported it in my project. When I run the app in a simulator or device I get the following error :

 No implementation found for void go.avcl_client_usage.Avcl_client_usage._init() (tried Java_go_avcl_1client_1usage_Avcl_1client_1usage__1init and Java_go_avcl_1client_1usage_Avcl_1client_1usage__1init__)

I tried to update go and gomobile but I am stuck.

Thanks for your help.

dballard commented 7 years ago

+1 gomobile 6ea0bb537040ee2926a37608791a60803db71171 (sept 13 2016) go 1.6.3 android 6 & 7 Fedora 23 Linux

import "fmt"

func Greetings(name string) string {
    return fmt.Sprintf("Hello, %s!", name)
}
ublic class contacts extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contacts);

        String greetings = Android_test.greetings("Android and Gopher");
        ((TextView)findViewById(R.id.testText)).setText(greetings);
        //((TextView)findViewById(R.id.testText)).setText("foo"); // works

    }
}

$ adb shell am start -n "im.ricochet.ricochet/im.ricochet.ricochet.contacts" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER Client not ready yet..Waiting for process to come online Waiting for process to come online Connected to process 5278 on device lge-nexus_5x-00a20cec25be1659 I/art: Late-enabling -Xcheck:jni I/art: Debugger is no longer active I/art: Starting a blocking GC Instrumentation W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable E/art: No implementation found for void go.android_test.Android_test._init() (tried Java_go_android_1test_Android_1test1init and Java_go_android_1test_Android_1test1init) D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: im.ricochet.ricochet, PID: 5278 java.lang.UnsatisfiedLinkError: No implementation found for void go.android_test.Android_test._init() (tried Java_go_android_1test_Android_1test__1init and Java_go_android_1test_Android_1test1init__) at go.android_test.Android_test._init(Native Method) at go.android_test.Android_test.(Android_test.java:12) at go.android_test.Android_test.greetings(Native Method) at im.ricochet.ricochet.contacts.onCreate(contacts.java:18) at android.app.Activity.performCreate(Activity.java:6664) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6077) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) Application terminated.

crawshaw commented 7 years ago

It certainly looks like bind/genjava.go:GenC always generates that symbol, so the fact it's not being found suggests some other reason it is not being loaded. What kind of android device are you running on? What architecture?

(To double check the basics: if you run gomobile with the -work flag it will leave the intermediate files around. Take a look and see if bind generated code for the symbol Java_go_avcl_1client_1usage_Avcl_1client_1usage__1init. Or @dballard, in your case, Java_go_android_1test_Android_1test__1init.)

sinlov commented 7 years ago

just finding error of this bug If your golang package name contains '_', it will let bind jni error like Java_go_xxx_1xxx_1_xxx

So move your golang package name _, or gobind fix this

dballard commented 7 years ago

Thank you @sinlov!

first, @crawshaw , I found

/gomobile_bind/java_android_test.c:Java_go_android_test_Android_test__1init(JNIEnv *env, jclass _unused) {

So it got that far...

But renaming the project camel case style to androidTest worked! It imports properly. So this does seem like a bug in gomobile, that it can't handle go projects with '_' in their name.

Do you want to track that here or start a new fresh ticket?

I am unblocked and moving forward so thanks to everyone!

dballard commented 7 years ago

More notes:

package two_words
FATAL EXCEPTION: main
                                                                      Process: im.ricochet.ricochet, PID: 15439
                                                                      java.lang.UnsatisfiedLinkError: No implementation found for void go.two_words.Two_words._init() (tried Java_go_two_1words_Two_1words__1init and Java_go_two_1words_Two_1words__1init__)
                                                                          at go.two_words.Two_words._init(Native Method)
/tmp/gomobile-work-569296966 $ grep 1init ./* -r
./gomobile_bind/java_two_words.c:Java_go_two_words_Two_words__1init(JNIEnv *env, jclass _unused) {

It looks like what ever is doing the generation of package names based on splitting multi word go packages isn't following quite the same standard as the Java side is expecting

Java tried: Java_go_two_1words_Two_1words__1init Java_go_two_1words_Two_1words1init

C generated code had: Java_go_two_words_Two_words__1init

dballard commented 7 years ago

So according to JNI documentation

https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names

It says JNI expects '_' in resources like functions to be replaced with '_1'

this is backed by the above problem I'm having, and in your own code in genjava.go in GenC() you manuually do it for the _init function on line 1298

    g.Printf("Java_%s_%s__1init(JNIEnv *env, jclass _unused) {\n", g.jniPkgName(), g.className())

So It looks like you need a small update to your name handling/translating code that swaps '_' for '_1'

dballard commented 7 years ago

@quentinmit I'm hoping I've provided enough data to move this from "Needs more investigation" to the next step. If you have more questions please reach out. I'm still trying to wrap my head around the not small code base of mobile/bind but I feel someone who's already up on it is going to be dramatically faster than me on this :)

willauld commented 6 years ago

I just ran into what looks to me to be this same problem or very close. I was getting the same error message (that's how I found this thread). However, rather than having an '' in the package name I had an '' in the function name. After reading @sinlov's comment I removed the '_' rebuilt the lib with gomobile and then the program in android studio. This did the trick.

So it appears that this issue has not been fixed or at least missed my variant of the problem. Thanks,

rwrz commented 3 years ago

Hello everyone, I know this thread is here for a while by now, but I run into this issue yesterday and I think it worth mentioning since it can be a future issue for others.

What happened, I'm running gomobile exported libraries on a Flutter application and after my first successful integration, I wanted more. So I did a second library using the same method and then my problems started to happen. Initially, the problem was duplicity on some dependencies on the Android project.

So, I found a way to "fix" it:

    // WARNING - THIS IS NOT A REAL FIX
    packagingOptions {
        pickFirst 'lib/x86/libgojni.so'
        pickFirst 'lib/armeabi-v7a/libgojni.so'
        pickFirst 'lib/x86_64/libgojni.so'
        pickFirst 'lib/arm64-v8a/libgojni.so'
        // pickFirst '**/*.so'  // did it first, it solved, but other issues showed, so, I moved to "per-item" approach above
    }

With that code, it compiled and I thought I had fixed it. But, later on, all my plugins stopped working. This was caused because of that same error on this thread No implementation found ... _init... whatever. But was obfuscated by this nothing is working at all. After a few tries later, I found this other thread: #15956.

So, it is not possible to have 2 independent bindings in the same app. Knowing that I fixed it by merging both libraries on the same "gomobile" command.

Hope it helps anyone that came up here with similar issues (it took me almost 4 hours on the weekend from the problem to the real fix).