简单实现Android NDK编译jni调用动态库开发


首先我们知道再次熟悉一下NDK的基本知识,Android平台从诞生起,就已经支持C、C++开发。众所周知,Android的SDK基于Java实现,这意味着基于Android SDK进行发的第三方应用都必须使用Java语言。但这并不等同于“第三方应用只能使用Java”,谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,Google在发布之初就提出过,开发支持jni编程方式,也就意味着我们在开发的过程中可以调用自己的第三方动态库了,不管是用c写的还是c++写的都行,那就有人要问的,为什么要多此一举,原因很简单,越接近底层的代码,其耦合性机越强,运行效率也就更高,方便我们处理一下相对比较繁琐的逻辑功能,
本博客将的是NDK版本是人r10e,目前最新的NDK版本貌似是r11了,至于r7之前的版本需要安装Cvgwin才能使用,既然有更高级的,那就何必讲情怀呢不是,因为高版本的NDK提供了一个ndk-build.cmd的脚本,可以直接利用这个脚本编译,而不需要使用Cygwin了。只需要为Eclipse Android工程添加一个Builders,而为Eclipse配置的builder,

其实就是在执行Cygwin,然后传递ndk-build作为参数,这样就能让Eclipse自动编译NDK了,废话不多说开始吧!

工欲善其事必先利其器,首先得配置好NDK开发环境:

1.我自己下载安装NDK-r10e版本,现在可以下载更高级的r11了,下面提供下载地址:http://developer.android.com/sdk/ndk/index.html

2打开我们的Eclipse(本人对Studio开发不是很熟悉,目前还在坚持着),新建一个Android工程,在工程目录testNdk下新建jni文件夹,该文件夹就用来保存NDK需要编译的文件代码比如.mk文件

1.1 点击新建项目右键Properties->Builders->New或者Project->Properties->Builders->New,新建一个Builder。

1.2 弹出窗口如下,在弹出的【Choose configuration type】对话框,选择【Program】,点击【OK】:

1.3 在弹出的【Edit Configuration】对话框中,配置选项卡【Main】。 在“Name“中输入新builders的名称,名字可以随意取,任性点就好。接下来就是在“Location”中输入nkd-build.cmd的路径,是不是对这个文件很陌生,这个文件的来源是之前下载的NDKr10解压后的中的文件可以自己设置路径也可以点击Browser File System 找到解压后的文件路径,这个建议放在根目录下面,路径不能有空格和中文,否则会编译不通过,同样的选在Working Diretcoty时可以选择Worksapce 的项目位置,也可以点击Browse Workspace来选择项目TestNDK的绝对路径,如下图:

1.4继续在这个【Edit Configuration】对话框中,配置选项卡【Refresh】。

     如下图勾选“Refresh resources upon completion”, 

    勾选“The entire workspace”, 

    勾选“Recuresively include sub-folders”。

1.5 继续在【Edit Configuration】对话框中,配置选项卡【Build options】。 
勾选“After a “Clean””,(勾选这个操作后,如果你想编译ndk的时候,只需要clean一下项目 就开始交叉编译) 
勾选“During manual builds”, 
勾选“During auto builds”, 
勾选“Specify working set of relevant resources”。如图下图

注意这个时候上面会提示有错误,那是因为你没有选择要关联的工程,此时点击点击“Specify Resources…”勾选testNdk工程中新建的“jni“目录,点击”finish“。 点击“OK“,完成配置。 如图

到此点击finish、回去点击OK就算是配置完成了,接下来就开始试试行还是不行咯。

1.第一步就是testNdk工程中新建一个JniTest.java的class类(为了调用C/C++代码),其内容如下:
package com.ndk.test;
public class JniTest{
    static public native String AddStr(String strA, String strB);
    static public native int AddInt(int a, int b);
}
2.生成 .h 的c++头文件
(1)用cmd命令定位到Jni
Test.java所在目录,输入“javac JniTest.java“后回车,生成JniTest.class文件
(如果是用的Eclipse建的工程,在
testNdk\bin\classes\com\ndk\test目录下就已经有JniTest.class文件了)。


(2)将Jni
Test.class拷贝到testNdk\bin\classes\com\ndk\test目录,将cmd命令定位到testNdk\bin\classes目录,
输入”javah com.ndk.test.Jni
Test.class“后回车,在testNdk\bin\classes目录下就生成了C++头文件com_ndk_test_JniTest.h
com_ndk_test_Jni
Test.h的文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_ndk_test_Jni
Test */
#ifndef _Included_com_ndk_test_JniTest
#define _Included_com_ndk_test_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_ndk_test_JniTest
 * Method:    AddStr
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_ndk_test_JniTest_AddStr
  (JNIEnv *, jclass, jstring, jstring);
/*
 * Class:     com_ndk_test_JniTest
 * Method:    AddInt
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_ndk_test_JniTest_AddInt
  (JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
3.在jni目录下新建一个Android.mk文件,其内容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=
TestNdk
LOCAL_SRC_FILES := com_
ndk_test_JniTest.c
include $(BUILD_SHARED_LIBRARY)
4. 将刚刚手动生成的com_ndk_test_JniTest.h拷贝到TestNdk工程的jni目录下,
然后新建一个com_ndk_test_JniTest.c文件完成头文件中函数的实现,其内容如下
(本来想写两个方法的,现在只讲解第一个方法,返回一个字符串“HelloWorld from JNI ”,
另一个方法是一个a+b的运算,方法写到这里,感兴趣的可以自己去研究):
com_ndk_test_JniClient.c
#include "com_ndk_test_JniTest.h"
#include <stdlib.h>
#include <stdio.h>


#ifdef __cplusplus   
extern "C"  
{   
#endif  
/*
 * Class:     com_ndk_test_JniTest
 * Method:    AddStr
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_ndk_test_JniTest_AddStr
  (JNIEnv *env, jclass arg, jstring instringA, jstring instringB)
{
    jstring str = (*env)->NewStringUTF(env, "HelloWorld from JNI !");
    return str;       
}


/*
* Class:     com_ndk_test_JniTest
* Method:    AddInt
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_ndk_test_JniTest_AddInt
  (JNIEnv *env, jclass arg, jint a, jint b)
{
    return a + b;
}


#ifdef __cplusplus   
}   
#endif
此刻,当编辑com_ndk_test_JniTest.c并保存后,project下的—clean  一下工程,
就可以看到TestNkd工程下的obj/local/armeabi目录下将自动生成libTestNdk.so库。
5.在TestNdkActivity.java中完成对JniClient.java中函数的调用(首先静态加载动态链接so库)
package com.ndk.test;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;


public class TestNdkActivity extends Activity {
    static {
        System.loadLibrary("TestNdk");
    }
    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.main);
        //第一个方法传入的两个参数没有做操作,直接返回hello jni,不用管
        String str = JniClient.AddStr("test", "test");
        //第二个方法暂时不实现
        //  int iSum = JniClient.AddInt(5, 2);        
       // String strSum = "5 + 7 = " + iSum;
        
        TextView tv1 = new TextView(this);
        tv1.setText(str);
        setContentView(tv1);
    }
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值