Android JNI 使用

来源:互联网 发布:安全设置阻止java运行 编辑:程序博客网 时间:2024/05/02 02:55

在Android里边提供了一个跨语言通信的方式jni,今天工作不忙,以前没做过这方面的工作,今天没事了学习了一下,做个小结,以防以后工作使用,比较方便,呵呵,开始流程分析吧


1.  NDK环境搭建(Ubuntu)

     因为我今天只是看了基于sdk开发使用的jni,所以我们必须要下载并且安装NDK

     1)   下载地址: http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip

     2)   下载完成以后,解压到你的workspace /android-ndk-r4b

            (以前的版本都需要运行 build/host-setup.sh 来进行初始化,这个 android-ndk-r4b 版本把它去除了,只是像如下配置一下环境变量即可 )

     3)    配置环境

            修改你的.bashrc 文件

            $ vi ~/.bashrc

            在最后添加

            export NDK_HOME=/workspace/android-ndk-r4b
            export PATH=$PATH:$NDK_HOME

            保存退出。

            $ source ~/.bashrc

            $ ndk-build

             ndk-build
             Android NDK: Could not find application project directory !   
             Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.   
             /workspace/ndk/ndkr4/build/core/build-local.mk:85: *** Android NDK: Aborting    .  Stop.

             出现这个证明,你的环境配置没问题了,只是build脚本没找到你jni目录,继续我们工作,呵呵

     4)    测试环境

            在NDK_HOME的根目录下有个samples/hello-jni/例子

             cd   workspace/samples/hello-jni/

             ndk-build

             make: Entering directory `/workspace/ndk/ndkr4/samples/hello-jni'
             Install        : libhello-jni.so => /workspace/ndk/ndkr4/samples/hello-jni/libs/armeabi
             make: Leaving directory `/workspace/ndk/ndkr4/samples/hello-jni'

             只要出现了libhello-jni.so,证明你编译通过了,没问题了


2.    第一个jni程序

        这个程序的功能是 ,通过jni调用本地方法,然后返回一个结构体,最后在java层显示

 

        1)  打开你的eclipse,当然你的eclipse已经具有开发sdk的环境了,新建一个android project  ,名字NewJni

              在工程根目录下新建一个folder   “jni”

              然后在jni目录里新建应该新建两个文件    Android.mk    newjni.c

             Android.mk  内容如下:

           LOCAL_PATH := $(call my-dir)
           include $(CLEAR_VARS)
           LOCAL_MODULE    := newjni
           LOCAL_SRC_FILES := newjni.c
           LOCAL_LDLIBS    := -llog   [后边会说道,这个是用来在jni的c程序中打印log,需要的lib]
           include $(BUILD_SHARED_LIBRARY)


           newjni.c    内容如下:

      #include <string.h>
#include <jni.h>
#include <stdlib.h>
#include <stdio.h>
#include <android/log.h>
#define LOG_TAG "NewJni"
/*
 * Java_packagename_classname_methodname
 */

#define  LOGD(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

struct StudentInfo
{
    char username[256];
    int password;
};     


/*--------------------测试结构体返回方法-----------------------------------------------------*/
jobject
Java_com_dlt_newjni_MainActivity_getStruct( JNIEnv* env, jclass cls)
{    
   LOGD(">>>>>>>>>jni->getStruct");
   //获取Java中的实例类  
   jclass objectClass = (*env)->FindClass(env,"com/dlt/newjni/StudentInfo");
   LOGD(">>>>>>>>>jni->getStruct-1");
   jmethodID mid = (*env)->GetMethodID(env,objectClass,"<init>","()V");  
   LOGD(">>>>>>>>>jni->getStruct-2");
   jobject obj = (*env)->NewObject(env,objectClass,mid);
   LOGD(">>>>>>>>>jni->getStruct-3");
   //获取类中每一个变量的定义  
   //名字  
   jfieldID uname = (*env)->GetFieldID(env,objectClass,"username","Ljava/lang/String;");  
   LOGD(">>>>>>>>>jni->getStruct-4");
   //密码  
   jfieldID pwd = (*env)->GetFieldID(env,objectClass,"password","I");  
   LOGD(">>>>>>>>>jni->getStruct-5");
    
   //给每一个实例的变量付值  
   (*env)->SetObjectField(env,obj,uname,(*env)->NewStringUTF(env,"xulc"));  
   LOGD(">>>>>>>>>jni->getStruct-6");
   
   (*env)->SetIntField(env,obj,pwd,123);  
   LOGD(">>>>>>>>>jni->getStruct-7");
   return obj;        

   写好以上的c代码,下面我们到终端cd到NewJni工程根目录下,执行 ndk-build

   生成:

  SharedLibrary  : libnewjni.so
  Install        : libnewjni.so => /home/xulc/work/dev-tools/android-ndk-r4b/samples/NewJni/libs/armeabi



                 java层的测试代码  ,内容如下:

StudentInfo.java

        package com.dlt.newjni;

public class StudentInfo {
    public String username;
    public int password;
}


package com.dlt.newjni;

import android.app.Activity;
import android.util.Log;
import android.widget.TextView;
/*
 * JNI Demo
 * feature list:
 * 1. 完成基本类型java层传到C层,并且返回
 * 2. 完成复杂结构体返回
 */
public class MainActivity extends Activity {
    
    public String username;
    public int password;
    
    
    protected void onCreate(android.os.Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        TextView tv = new TextView(this);
        tv.setText("superman");
        setContentView(tv);
        disUser();
    }
    
    private void disUser()
    {
        StudentInfo sInfo = getStruct();
        Log.d("Main", ">>>>>>>>>>>>>>>>disUser:[uname],[pwd]= " + sInfo.username
                + ", " + sInfo.password);
        
    }
   
    static {
        System.loadLibrary("newjni");
    }
    
    public native StudentInfo getStruct();
}

最后在eclipse下执行一下这个apk,看看效果




3.  记录一下在jni的c代码里如何使用log,然后显示在logcat上面

      红色的为需要加入的地方

     在jni/Android.mk

  LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := newjni
LOCAL_SRC_FILES := newjni.c

LOCAL_LDLIBS    := -llog  

include $(BUILD_SHARED_LIBRARY)

    

      在jni/newjni.c

#include <android/log.h>
#define LOG_TAG "NewJni"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)


以上两个文件需要加的地方,这样你就可以在newjni.c 里边使用LOGD("XXXXXXX");了