eclipse的JNI学习




Android上层的Application和ApplicationFramework都是使用Java编写,底层包括系统和使用众多的LIiraries都是C/C++编写的。所以上层Java要调用底层的C/C++函数库必须通过Java的JNI来实现。


普通.os文件使用方法:

1、在你的项目根目录下建立libs/armeabi目录;

2、将libxxx.so文件copy到 libs/armeabi/下;

3、此时ADT插件自动编译输出的.apk文件中已经包括.so文件了;

4、安装APK文件,即可直接使用JNI中的方法;

我想还需要简单说明一下libxxx.so的命名规则,沿袭Linux传统,lib<something>.so是类库文件名称的格式,但在Java的System.loadLibrary(“ something ”)方法中指定库名称时,不能包括 前缀—— lib,以及后缀——.so。

完成自己的jni编程并生成.os文件

JNI是Java平台定义的用于和宿主平台上的本地代码进行交互的“Java标准”,它通常有两个使用场景:1.使用(之前使用c/c++、delphi开发的)遗留代码;2.为了更好、更直接地与硬件交互并 获得更高性能 。

1、首先配置NDK开发环境,下载android-ndk-r10b工具并解压(这个网上很好找记录解压后的位置,打开eclipse软件,在工具栏选择windows-->preferences,打开如下窗口,选择android-->NDK-->NDK Location,选择browse,选择刚刚解压android-ndk-r10b的文件根目录位置。


2、新建一个android工程,起名为JniTest,MainActivity所在包名为:com.example.jnitest;在src文件夹下添加一个新的package,命名为com.example.jni,在该package下添加一个java文件,该文件用于存储我们新建的jni方法。文件格式如下:

TestJni.java的的代码,这里共定义了四个方法:

package com.example.jni;

public class TestJni {

public native boolean init();
public native int add(int x , int y);
public native void destory();
public native String getString();

}

3、通过javah命令生成所需的.h文件;保存上面的工程,并文件夹打开工程项目根目录,此时可以查看是否存在class文件,位置在bin-->classes-->com-->example-->jni-->TestJni,如果不存在,请重新build project并继续下面步骤:返回根目录-->bin-->classes文件夹下,此时该文件夹下只有一个com文件。shift+右击,选择在此处打开命令窗口,如果没有该项,通过com命令,定位到该位置也可以。打开命令提示符窗口,输入:javah com.example.jni.TestJni


则会在根目录-->bin-->classes文件下生成一个com_example_jni_TestJni.h的文件。该文件即是我们需要的头文件。内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jni_TestJni */


#ifndef _Included_com_example_jni_TestJni
#define _Included_com_example_jni_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_jni_TestJni
 * Method:    init
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_com_example_jni_TestJni_init
  (JNIEnv *, jobject);


/*
 * Class:     com_example_jni_TestJni
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_jni_TestJni_add
  (JNIEnv *, jobject, jint, jint);


/*
 * Class:     com_example_jni_TestJni
 * Method:    destory
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_jni_TestJni_destory
  (JNIEnv *, jobject);


/*
 * Class:     com_example_jni_TestJni
 * Method:    getString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jni_TestJni_getString
  (JNIEnv *, jobject);


#ifdef __cplusplus
}
#endif
#endif

4、右击工程“JniTest”,选择android Tools-->add native support,给添加的lib命名为JniTest,注意,此时命名默认带有前缀lib和后缀.so,点击finish结束。


此时,原工程根目录下会增加了一个jni文件夹,将3步骤生成的com_example_jni_TestJni.h头文件复制到该jni文件夹下,并添加以下文件
com_example_jni_TestJni.cpp,源码:
#include <stdio.h>
#include <stdlib.h>
#include "com_example_jni_TestJni.h"
#include "Add.h"
CAdd *pCAdd = NULL;
JNIEXPORT jboolean JNICALL Java_com_example_jni_TestJni_init(JNIEnv *env,jobject obj) {
   if (pCAdd == NULL) {
        pCAdd = new CAdd;
    }
   return pCAdd != NULL;
}
JNIEXPORT jint JNICALL Java_com_example_jni_TestJni_add(JNIEnv *env, jobject obj,
        jint x, jint y) {
        int res = -1;
       if (pCAdd != NULL) {
          res = pCAdd->Add(x, y);
        }
       return res;
}
JNIEXPORT void JNICALL Java_com_example_jni_TestJni_destory(JNIEnv *env, jobject obj)
{    if (pCAdd != NULL)
    {
        pCAdd = NULL;
    }
}
JNIEXPORT jstring JNICALL Java_com_example_jni_TestJni_getString(JNIEnv *env, jobject obj){


return env->NewStringUTF("HELLO JNI!!");
}
Add.cpp文件源码:
 #include "Add.h"
 CAdd::CAdd() {
 }
 CAdd::~CAdd() {
 }
 int CAdd::Add(int x, int y) {    
 return x + y;
}
Add.h文件源码:
#ifndef _TEST_JNI_ADD_H_
 #define _TEST_JNI_ADD_H_
    class CAdd {public:
         CAdd();    
        ~CAdd();    
        int Add(int x, int y);
    };
#endif
修改Android.mk文件内容为:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := JniTest
LOCAL_SRC_FILES := com_example_jni_TestJni.cpp
LOCAL_SRC_FILES += Add.cpp
include $(BUILD_SHARED_LIBRARY)


此时应该会报错,解决办法:右击工程名,选择Properties,打开Properties for JniTest,选择C/C++ General-->Paths and Symbols-->includes-->add-->File system,选择android-ndk-r10b的文件解压路径,然后依次选择android-ndk-r10b-->platforms-->android-?(选择对应的android target版本)-->arch-arm-->usr-->include,点击确定添加。此时clean并rebuild project,错误消失。此时会在libs文件夹下生成一个armeabi文件夹,打开armeabi,里面就有我们需要的libTestJni.os文件。


5、在我们新建的TestJni.java文件中添加以下代码:

static{
System.loadLibrary("JniTest");
}

在MainActivity.java中修改以下代码:


public class MainActivity extends Activity {

TextView tvX = null;
TextView tvY = null;
TextView tvSum = null; 
Button   btnAdd = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);
tvX = (TextView)findViewById(R.id.et_x);
tvY = (TextView)findViewById(R.id.et_y);
tvSum = (TextView)findViewById(R.id.et_sum);
btnAdd = (Button)findViewById(R.id.btn_add);
btnAdd.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) { 
int x = Integer.valueOf( tvX.getText().toString());
int y = Integer.valueOf( tvY.getText().toString());
int sum = 0;
TestJni jni = new TestJni();
boolean flag = jni.init();
if(flag){
sum = jni.add(x, y);
}
btnAdd.setText(String.valueOf(sum));

jni.destory();
tvSum.setText(String.valueOf(jni.getString()));
}
});

}

}


此时就是通过调用TestJni中的方法使用C和C++进行计算。试一下结果:


点击button后:


我们的jni初步学习到此为止!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.) 在项目根目录下创建jni目录,下面是要放进去的第一个文件Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := main_jni #LOCAL_CFLAGS := LOCAL_SRC_FILES := main.cpp #LOCAL_LDLIBS := include $(BUILD_SHARED_LIBRARY) 2.) 在jni目录创建main.cpp #include using namespace std; #ifdef __cplusplus extern "C" { #endif class Test { public: Test(){}; ~Test(){}; int SomeFunc() { return 20140522; } }; jint Java_com_yxiaolv_testjni_MainActivity_SomeFunc(JNIEnv *env, jobject thiz) //红色部分必须和你java类包名一致 { Test *test = new Test(); return test->SomeFunc(); } #ifdef __cplusplus } #endif //将下面第3.)至第5.)步的代码片段放到eclipse创建android项目时自动产生的MainAcitivity.java中就可以了 3.) 在Java Activity代码中添加对这个jni的调用 (本例中是MainActivity.java ): static { System.loadLibrary("main_jni"); } 4.) 在调用者Activity中定义函数 native int SomeFunc(); 5.) 在activity中调用 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = new TextView(this); int i = SomeFunc(); tv.setText( String.valueOf(i) ); setContentView(tv); } //下面的第6.)和第7.)步可以被集成的.cproject 和在.project中添加plugin之后一键编译,不用单独起dos窗口了。由于没有找到生成.cproject的工具,只能手写,所以本文不使用该方法,以后找到了好的方法再补充。委屈 6.) 在dos窗口中,cd到项目路径下,运行ndk-build 命令,该命令会自动搜索该路径子目录下的native项目,进行编译。 (Note: 编译完成后不要忘记了刷新项目)。 7.) 重新编译和部署项目,就可以看到已经包含了.so的apk运行在目标机上了。 摘自 http://stackoverflow.com/questions/13654678/how-compile-c-project-via-android-ndk 1). 如果不知道怎样安装和使用windows版的NDK,可以参考 http://blog.csdn.net/do_script/article/details/26478583

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值