Esempio: hello-jni

Questo esempio illustra hello-jni, un'applicazione C/C++ minima creata con NDK. Questo esempio si trova nella directory hello-jni del repository ndk-samples, all'interno del ramo android-mk.

Android.mk

Le due righe seguenti indicano il nome del file di origine nativo, insieme al nome della libreria condivisa da creare. Il nome completo della libreria creata è libhello-jni.so, dopo che il sistema di build ha aggiunto il prefisso lib e l'estensione .so.

LOCAL_SRC_FILES := hello-jni.c
LOCAL_MODULE    := hello-jni

Per ulteriori informazioni sulla funzione del file Android.mk e su come utilizzarlo, visita il sito Android.mk.

Application.mk

Questa riga indica al sistema di compilazione la CPU e l'architettura su cui creare. In questo esempio, il sistema di compilazione si crea per tutte le architetture supportate.

APP_ABI := all

Per ulteriori informazioni sul file Application.mk e su come utilizzarlo, consulta Application.mk.

Implementazione lato Java

Il file helloJNI.java si trova in hellojni/src/com/example/hellojni/. Richiama una funzione per recuperare una stringa dal lato nativo, quindi la visualizza sullo schermo.

Il codice sorgente contiene tre righe di particolare interesse per l'utente NDK. Sono presentati qui nell'ordine di utilizzo, non in base alla riga.

Questa chiamata di funzione carica il file .so all'avvio dell'applicazione.

Kotlin

System.loadLibrary("hello-jni")

Java

System.loadLibrary("hello-jni");

La parola chiave native in questa dichiarazione del metodo indica alla macchina virtuale che la funzione si trova nella libreria condivisa, ovvero implementata sul lato nativo.

Kotlin

external fun stringFromJNI(): String

Java

public native String stringFromJNI();

Il framework Android chiama la funzione caricata e dichiarata nei passaggi precedenti, visualizzando la stringa sullo schermo.

Kotlin

tv.text = stringFromJNI()

Java

tv.setText( stringFromJNI() );

Implementazione lato C

Il file hello-jni.c si trova in hello-jni/jni/. Contiene una funzione che restituisce una stringa richiesta dal lato Java. La dichiarazione della funzione è la seguente:

JNIEXPORT jstring JNICALL
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )

Questa dichiarazione corrisponde alla funzione nativa dichiarata nel codice sorgente Java. Il tipo restituito, jstring, è un tipo di dati definito nella specifica dell'interfaccia nativa Java. In realtà non è una stringa, ma un puntatore a una stringa Java.

Dopo jstring viene il nome della funzione, che si basa sul nome della funzione Java e sul percorso del file che la contiene. Costruiscilo in base alle seguenti regole:

  • Aggiungi Java_ all'inizio.
  • Descrivi il percorso file in relazione alla directory di origine di primo livello.
  • Utilizza i trattini bassi al posto delle barre.
  • Ometti l'estensione del file .java.
  • Dopo l'ultimo trattino basso, aggiungi il nome della funzione.

Seguendo queste regole, questo esempio utilizza il nome della funzione Java_com_example_hellojni_HelloJni_stringFromJNI. Questo nome si riferisce a una funzione Java chiamata stringFromJNI(), che risiede in hellojni/src/com/example/hellojni/HelloJni.java.

JNIEnv* è il puntatore alla VM, mentre jobject è un puntatore all'oggetto this implicito passato dal lato Java.

La seguente riga chiama l'API VM (*env) e le passa un valore restituito: vale a dire la stringa richiesta dalla funzione sul lato Java.

return (*env)->NewStringUTF(env, "Hello from JNI !
Compiled with ABI " ABI ".");