Calling Rust generated lib from Android JNI

I posted this at stack overflow as I think it is more related to Android, but though I may get an answer here as well.

I’m trying to replicate the this tutorial for building and using Rust lib in Android app, I build the library successful, and uploaded the generated libs here

The function required to be called by Android using the Java_<Package>_Class_function theme is:

Java_com_mozilla_greetings_RustGreetings_greeting

My android app structure is as below:

enter image description here

I’m getting the below error at my JNI wrapper:

Cannot resolve corresponding JNI function
Java_com_mozilla_greetings_RustGreetings_greeting

The JNI wrapper is:

    package com.mozilla.greetings;
    
    public class RustGreetings {
    
        private static native String greeting(final String pattern);
    
        public String sayHello(String to) {
            return greeting(to);
        }
    }

And the main class is:

    package com.mozilla.greetings;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class GreetingsActivity extends AppCompatActivity {
    
        static {
            System.loadLibrary("greetings");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_greetings);
    
            RustGreetings g = new RustGreetings();
            String r = g.sayHello("world");
            ((TextView) findViewById(R.id.greetingField)).setText(r);
        }
    }

I solved it using JNA whcih I think is slower than JNI, I’ll write my solution below using JNA hoping someone provide the required fix using JNI

My app structure is as below, using kotlin:

  1. I added the libjnidispatch.so to each library build folder, this can be obtained by extracted the requiredandroid architecture from here, download the required jar, then extract it to get the libjnidispatch.so
  2. I created interbface for jna

JNA.kt

package com.mozilla.greetings

import com.sun.jna.Library

interface JNA : Library {
    fun rust_greeting(pattern: String): String
}
  1. I created wrapper for jna, RustGreetings.kt:
package com.mozilla.greetings

import com.sun.jna.Native

class RustGreetings {

    fun sayHello(to: String): String =
            Native.loadLibrary<JNA>("greetings", JNA::class.java).rust_greeting(to)
}
  1. Main activity, GreetingsActivity.kt:
package com.mozilla.greetings

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_greetings.*


class GreetingsActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_greetings)

        val g = RustGreetings()
        val r = g.sayHello("Rust")
        greetingField.text = r
    }

    companion object {
        init {
            System.loadLibrary("greetings")
        }
    }
}

Note:
In order to avoid using findViewById I used kotlin extension, as explained here and addeding the below to the build.gradle (module):

apply plugin: 'kotlin-android-extensions'

61803517FD3B4EF2BEFB138945264310

It looks it is an IDE issue nothing with the code, the app had been executed.
I re-wrote it using Kotlin, and it was executed smoothly as well, below my kotlin code:

GreetingsActivity.kt

package com.mozilla.greetings

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_greetings.*

class GreetingsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_greetings)

        val g = RustGreetings()
        val r = g.sayHello("My Rust")
        greetingField.text = r
    }

    companion object {

        init {
            System.loadLibrary("greetings")
        }
    }
}

RustGreetings.kt

package com.mozilla.greetings

class RustGreetings {

    private external fun greeting(pattern: String): String

    fun sayHello(to: String): String = greeting(to)
}

build.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.mozilla.greetings"
        minSdkVersion 28
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

activity_greetings.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".GreetingsActivity">

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" android:id="@+id/greetingField"/>

</android.support.constraint.ConstraintLayout>

Below structure and execution, the apk is here: