Šta je novo?

Android - pozivanje Java metoda iz native koda

voodoo_

Čuven
Učlanjen(a)
31.08.2003
Poruke
9,728
Poena
930
Treba da realizujem nativnu C funkciju u okviru Android aplikacije, ali tako da ta funkcija ima mogućnost pozivanja određene Java metode iz klase u kojoj je deklarisana i ta nativna metoda. Ovo treba da radi kao callback, jer će nativna funkcija raditi duže vremena u petlji, a tokom rada bi trebalo da šalje povratne signale roditeljskoj Java klasi, bez izlaska iz same funkcije.

Imam Activity koji sadrži jedan EditText i jedan Button. Klikom na Button se poziva nativna funkcija (nativeMethod), koja onda iz sebe pozove Java metodu (callback), a koja onda ubaci neki tekst u EditText (trivijalna situacija, treba mi samo da isprobam da li to radi).

HTML:
public class JNICallbackTestActivity extends Activity {
	
	static {
		System.loadLibrary("native");
	}
	
	public EditText editText;
	public Button btnDodaj;
	
	private native void nativeMethod();
	
	private void callback() {
		editText.setText("Calling from C.");
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        editText = (EditText) findViewById(R.id.editText);
        btnDodaj = (Button) findViewById(R.id.btnDodaj);
        
        btnDodaj.setOnClickListener(new OnClickListener() {
		public void onClick(View v) {
			nativeMethod();
		}
	});
    }
}

Nativna funkcija izgleda ovako:

HTML:
#include <jni.h>

JNIEXPORT void JNICALL Java_rs_pupin_Callbacks_nativeMethod(JNIEnv *env, jobject obj)
{
	jclass cls = (*env)->GetObjectClass(env, obj);
	//jclass cls = (*env)->FindClass(env, "rs/pupin/JNICallbackTestActivity");

	jmethodID msgid = (*env)->GetMethodID(env, cls, "callback", "()V");
	if (msgid == 0) return;

	(*env)->CallVoidMethod(env, obj, msgid);
}

Međutim, čim kroči u nativnu funkciju, program krešuje (kako god da pokušam da pročitam jclass, i preko prve i preko ove druge iskomentarisane varijante). Guglam ceo dan i nalazim svašta ali ništa konkretno, da li je neko imao slična iskustva? Hvala unapred.
 
Pogrešno sam imenovao funkciju u C fajlu, umesto

Java_rs_pupin_Callbacks_nativeMethod

treba

Java_rs_pupin_JNICallbackTestActivity_nativeMethod

pošto je šablon Java_paket_klasa_metod, a kad sam gledao neki tutorial zaboravio sam da promenim u ime svoje klase. Kakva glupa greška...
 
Kada se vec bavis sa NDK.. da li moze jedno pitanje... Kako da podesim eclipse da mi kompajlira i Java i C code kada nesto menjam. Ja svaki put kada menjam C/C++ code moram da rucno pozivam ndk_build da bi dobio novi .so. Ima li neki elegantniji nacin. npr da se ubaci clean/build opcije u context menu za JNI deo projekta?
 
Jesi siguran da ispravno koristiš JNIEnv? Koliko vidim iz primera po netu (reicmo: https://forums.oracle.com/forums/thread.jspa?messageID=6465762)
ne bi trebalo da pristupaš JNINativeInterface-u preko (*env) nego:

Kod:
JNIEXPORT void JNICALL Java_rs_pupin_Callbacks_nativeMethod(JNIEnv *env, jobject obj)
{
	jclass cls = env->GetObjectClass(obj);
	//jclass cls = env->FindClass(env, "rs/pupin/JNICallbackTestActivity");

	jmethodID msgid = env->GetMethodID(cls, "callback", "()V");
	if (msgid == 0) return;

	env->CallVoidMethod(obj, msgid);
}
 
Poslednja izmena:
@yooyo: verovatno može, mada mi ni ručno nije problem, strelica gore pa enter u terminalu, minimum posla 🙂

@zeleni zub: env-> je C++ varijanta, za čist C mora (*env)-> pošto je env pokazivač na pokazivač
 
Glupo pitanje - proverio si da ti neki od pointera nije slučajno null (env ili *env)?
 
Ma nije u tome problem, eno rešenja u drugom postu 😀 Samo mora strogo da se ispoštuje "dekoracija" imena funkcija u nativnom kodu, i to je to.
 
DOH. Nisam uopšte pročitao post do kraja - mislio sam samo da ispravljaš kod koji si okačio ovde. 🙂
 
Greske sa dekoracijom su najcesce kada se radi sa shared libs (ili dll-ovima u windowsima). Ja sam pre za to da se uradi jednom stabilan JNI interface, i da se to lepo zavije u neku c++ klasu i odatle nastavis dalje. To bi imalo primene za igre i apps koje su port sa drugih platformi.
 
Mali bump teme... da se ne bi maltretirali oko ispravnog imena native metode napravite prvo java klasu sa native metodama pa onda otvorite shell i idite u folder PROJECT/bin/classes i tu ukucajte:
Kod:
javah -jni com.your.package.ImeJavaNativeKlase

Rezultat je header file koji kopirate (ili pomocu javah -d switcha smestite) u jni folder, i ukljucite u native.c/cpp.

javah mora biti u pathu... Kod windowsa to je obicno c:\Program Files\Java\jdk1.6.0_26\bin\javah.exe
 
Poslednja izmena:
Nazad
Vrh Dno