Android jni本地編程入門

來源:互聯網
上載者:User

在某些情況下,java編程已經不能滿足我們的需要,比如一個複雜的演算法處理,這時候就需要用到jni技術;

  • jni : java native interface
  • jni 其實就是java和c/cpp之間進行通訊的一個介面規範,java可以調用c/cpp裡面的函數,同樣,c/cpp也可以調用java類的方法;

jni開發工具ndk的安裝:
在最新的ndk版本中,安裝ndk很簡單,只需要裝ndk的路徑配置到系統內容變數中即可;
在編譯的時候,進入工程根目錄;執行命令  ndk-build  即可完成編譯;

一、cpp與java

>>1.java檔案:TextOutput.java

package com.jnitest;import android.util.Log;public class TextOutput {    private native String init();    static {        System.loadLibrary("text");    }    public String getString() {        return init();    }    public void sayHello() {        Log.e("tag", "void sayHello");    }    public String sayHello_() {        Log.e("tag", "string sayHello_");        return "return string sayHello_";    }    public static void sayHello__() {        Log.e("tag", "static sayHello__");    }}

在該類中定義了一個本地方法init[native init],方法實現由接下來的cpp函數來實現;以及定義了其它幾個方法,由cpp檔案來調用;

>>2.cpp檔案:test.cpp

#include <jni.h>#include <android/log.h>#include <string.h>#ifndef _Included_com_jnitest_TextOutput#define _Included_com_jnitest_TextOutput#ifdef __cplusplusextern "C" {#endifJNIEXPORT jstring JNICALL Java_com_jnitest_TextOutput_init(JNIEnv *, jobject);#ifdef __cplusplus}JNIEXPORT jstring JNICALL Java_com_jnitest_TextOutput_init(JNIEnv * env,        jobject obj) {    jmethodID mid; // 方法標識id    jclass cls = env->GetObjectClass(obj); // 類的對象執行個體    mid = env->GetMethodID(cls, "sayHello", "()V");     env->CallVoidMethod(obj, mid);    jmethodID mid1;    mid1 = env->GetMethodID(cls, "sayHello_", "()Ljava/lang/String;");// @1    jstring s1 = (jstring) env->CallObjectMethod(obj, mid1); // @2    jmethodID mid2;    mid2 = env->GetStaticMethodID(cls, "sayHello__", "()V");    env->CallStaticVoidMethod(cls, mid2);    return s1;}#endif#endif

先來看在cpp中定義的函數名:Java_com_jnitest_TextOutput_init
其實不難看出,java檔案與cpp檔案中函數名的配對定義方式為Java + 包名 + java類名 + 方法/函數名,中間用_分隔;其中兩個參數分別是:

  • env:當前該線程的內容,包含線程裡面全部內容;
  • obj:當前類的執行個體,指.java檔案的內容(在該例子中即是TextOutput類);

@1:擷取MethodId,該方法需要三個參數,分別jclass類的對象執行個體,函數名,函數簽名;其中函數簽名由兩部分構成(參數+函數傳回值); 
查看簽名可以通過先進入到java檔案產生的class檔案目錄,執行命令:javap -s -p ClassName

產生如所示的函數簽名;

@2:執行該方法,在上面的例子中,將執行sayHello_方法

運行程式:

TextOutput to = new TextOutput();Log.e("tag", "" + to.getString());

二.c與java
在Activity中有一個int欄位,通過callback賦值

package com.example.hellojni;import android.app.Activity;import android.util.Log;import android.widget.TextView;import android.os.Bundle;public class HelloJni extends Activity {    private static int si;    private static void callback() {        si = 123;    }    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        TextView tv = new TextView(this);        tv.setText(stringFromJNI());        setContentView(tv);        Log.e("tag", "si=" + si);    }    public native String stringFromJNI();    static {        System.loadLibrary("hello-jni");    }}

hello-jni.c

#include <string.h>#include <jni.h>/*  * */jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env,        jobject thiz) //env:當前該線程的內容,包含線程全部的東西;thiz:當前類的執行個體,指.java檔案的內容{    jint si;    jfieldID fid; // 一個欄位,實際上對應java類裡面的一個欄位或屬性;    jclass cls = (*env)->GetObjectClass(env, thiz); // 類的對象執行個體    jmethodID mid = (*env)->GetStaticMethodID(env, cls, "callback", "()V"); // 一個方法的id    //(I)V  (I)I    if (mid == NULL) {        return (*env)->NewStringUTF(env, "mid=null");    }    (*env)->CallStaticVoidMethod(env, cls, mid); //調用callback方法    fid = (*env)->GetStaticFieldID(env, cls, "si", "I"); //取出si欄位    if (fid == NULL) {        return (*env)->NewStringUTF(env, "fid=null");    }    si = (*env)->GetStaticIntField(env, cls, fid); //取出欄位對應的值(fid欄位對應的值)    return (*env)->NewStringUTF(env, "init success");}

運行上面的Activity,即可實現對si的賦值

3.加入連結庫

在程式開發過程中,會頻繁的用到調試,方式有很多種,下面要講的這一種是通過log列印資訊來列印程式運行時的一些狀態數值;

修改Android.mk檔案,添加一句代碼

include $(CLEAR_VARS)LOCAL_LDLIBS += -llog //LDLIBS:串連libs,後面跟的參數為需要連結的libs,-llog表示Android中的Log庫;include $(BUILD_SHARED_LIBRARY)

加入了log庫之後

即可以在c檔案中調用log列印輸出資訊:

__android_log_print(ANDROID_LOG_ERROR, "hello", "livingstone");    __android_log_print(ANDROID_LOG_DEBUG, "hello", "livingstone %d" ,23);

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.