Android JNI 手把手教你編寫.so並調用接口

最近在看了很多JNI資料,用了各種方法,但個人卻喜歡這種方式,廢話不多說。


一、在android源碼package目錄下創建一個文件夾TestJni,並創建兩個目錄,分別爲test_jni.cpp和Android.mk


二、編寫test_jni.cpp:

#include <stdio.h>    
#include <errno.h>    
#include <fcntl.h>    
#include <unistd.h>    
#include <stdint.h>    
#include <assert.h>    
//#include <cutils/log.h>    
#include <string.h>    
#include <jni.h>    
#include "android_runtime/AndroidRuntime.h"
     
static const char *kClassName = "com/example/test_jni/testjni";  //需要註冊的類,注意我的是testjni.java

jint openportNative(JNIEnv *env,jobject obj,int state)
{
//printf("+++++++OpenPort++++++++\n");
state = 111;
return state;
}
jint closeportNative(JNIEnv *env,jobject obj,int state)
{
//printf("+++++++ClosePort++++++++\n");
state = 222;
return state;
}

static JNINativeMethod gMethods[] = {    
    /* name, signature, funcPtr */    
    {"openport",    "(I)I",                   (void*)openportNative}, //綁定 ,openport爲java應用層的接口,對應JNI openportNative接口;
    {"closeport",    "(I)I",                (void*)closeportNative}    
};    

jint JNI_OnLoad(JavaVM *vm, void *reserved)    //這個很重要,詳細說明不解散;
{    
    JNIEnv *env = NULL;    
    jclass cls;
    jint result = -1;    
     
    if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {    
       
        return -1;    
    }    
    cls = env->FindClass((const char*)kClassName);    
    if (cls == NULL) {          
        return -1;    
    }    
    if (env->RegisterNatives( cls, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0) {    
      
        return -1;    
    }    
result=JNI_VERSION_1_4;
    return result;    
}    

三、編寫Android.mk文件:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_SRC_FILES:= test_jni.cpp  
LOCAL_C_INCLUDES += \
    $(JNI_H_INCLUDE) 
LOCAL_SHARED_LIBRARIES := \
    libandroid_runtime     
LOCAL_MODULE := libtest_jni
LOCAL_MODULE_TAGS := eng
include $(BUILD_SHARED_LIBRARY)

四、執行source build/envsetup.sh---->lunch xxx -----> make test_jni -j4

編譯完成後.so文件將直接保存到out/target/product/xxxxx/system/lib/目錄下,將他拷貝到eclipse的libs目錄下即可,接下來我們調用下接口;


五、MainActivity.java  代碼很簡單,新建兩個按鈕,然後訪問庫文件的接口,並接受返回值,數值確認是正確的。

package com.example.test_jni;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.example.testjni.R;
import com.example.test_jni.testjni;

public class MainActivity extends Activity {
    private Button btn1,btn2;
    int red;
    static {                   
        System.loadLibrary("test_jni");                    //靜態加載庫
        }                                           
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
      
        final testjni j = new testjni();            //創建一個對象,這個對象看下面的代碼,裏面有包含native方法
        btn1 = (Button)findViewById(R.id.bt1);
        btn2 = (Button)findViewById(R.id.bt2);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               red = j.openport(111);   //執行native openport方法
               System.out.println("red========="+red);              
            }                   
        });
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                red =j.closeport(222); //同上
                System.out.println("red========="+red);              
            }
        });
              
    }
}

六、testjni.java類

package com.example.test_jni;

public class testjni {
    static {                   
        System.loadLibrary("test_jni");                    
        }                                         
    public native int openport(int a);  //本地方法  
    public native int closeport(int b);
}

七、在eclipse編譯成APK文件,安裝APK。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章