Android JNI NDK 编程学习

最近一直在研究 Android NDK 编程。把过程记录下来。以帮忙巩固学习。

一 NDK 简介

      NDK全称:Native Development Kit

         官方网址:http://developer.android.com/tools/sdk/ndk/index.html

         

       The NDK is a toolset that allows you to implement parts of your app using native-code languages such as C and C++. For certain types of apps, this can be helpful so you can reuse existing code libraries written in these languages, but most apps do not need the Android NDK.

        Before downloading the NDK, you should understand that the NDK will not benefit most apps. As a developer, you need to balance its benefits against its drawbacks. Notably, using native code on Android generally does not result in a noticable performance improvement, but it always increases your app complexity. In general, you should only use the NDK if it is essential to your app—never because you simply prefer to program in C/C++.

       Typical good candidates for the NDK are self-contained, CPU-intensive operations that don't allocate much memory, such as signal processing, physics simulation, and so on. When examining whether or not you should develop in native code, think about your requirements and see if the Android framework APIs provide the functionality that you need.

 翻译过来大概是:
 NDK提供了一系列的工具,帮助允许开发者C/C++等语言实现部分代码。这对特定类型的应用非常有用,但对大多数应用这并不使用。
 在下载NDK之前,你应该理解NDK对大部分应用并不会有好处。作为开发人员,你需要针对其缺点平衡它的好处。值得注意的是,在使用Android原生代码不一定带来性能改进,但它总是会增加你的应用程序的复杂性。一般情况下,你使用NDK,只有在它是必不可少的对你的应用程序,而不是为因为你使用C / C + +进行编程。
选择NDK的应用应该是自包含的,CPU密集型操作且不分配很多内存的,如信号处理,物理模拟,等等。当 您考虑使用ative code开发时,去看看Android FW框架API提供你所需要的功能。

二  环境打建

     1) 文件准备

               网上关于环境搭建的文章很多。看了一些,好多讲的是以前版本的NDK搭建很多。方法也很麻烦。其实,只使用新版本NDK就够了。从官网下载对应版本的开发包,解压到某个目录。比如我们下载的android-ndk-r9c。

      2) 配置环境变量。

              如果你使用的是Linux. 将你解压的目录添加进系统环境变量.方法:将这些信息

              export ANDROID_NDK_BUILD=/(你的目录)/android-ndk-r9c
              export PATH=$PATH:$ANDROID_NDK_BUILD

             写入~/.bashrd .然后 source ~./bashrc

             一切OK.

           

              如果你使用的是Windows 将你解压的目录添加进系统环境变量。.方法:在桌面,右击计算机-->属性--> 高级系统设置--环境变量-->找到PATH在前面添加你下载的NDK解压后的根目录例如:F:\android-ndk-r8d;。点击保存

             一切OK

三。 开发步骤

        就以NDKdemo中的helloword为例

      1.  创建正常的Android工程

             创建工程 com.example.jnilearn。这个就不多说了。

      2.  编写声明native方法的java类

             
public class PrintHello {

    static{
        System.loadLibrary("hello-jni");
    }
    public PrintHello() {
        // TODO Auto-generated constructor stub
    }

    public native String printHello();
}

        我们使用NDK编写的代码 最终都会编译成.so库文件。上面的static 代码块的作用就是将我们编译出的库文件加载进来。我们选择在加载类的时候 记载我们的so 文件。但这不是必须的。我们可以在我们使用里面的方法前的任何地方加载。其中, System.loadLibrary("hello-jni"); 里面的库文件名 我们可以指定。

         3. 编译java类

          我们可以选择直接运行工程,eclipse会自动帮忙编译,在bin/class生成我们的PrintHello.class 文件 .在eclipse看不到该目录
          我们也可以自己编译该文件。进入终端 进入工程所在的目录。javac src/com/example/jnilearn/PrintHello.java -d bin/class (如果没有该目录就需要我们自己建立 mkdir -p bin/class)。

           4. 实现

           首先,我们使用javah命令生成.h头文件。
            进入bin/class 目录 cd bin/class 
            javah -d ../../jni -jni com.example.jnilearn.PrintHello 
            会看到我们在工程根目录下的jni 目录下生成了我们的头文件com_example_jnilearn_PrintHello.h
           内容如下:
                         
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnilearn_PrintHello */

#ifndef _Included_com_example_jnilearn_PrintHello
#define _Included_com_example_jnilearn_PrintHello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_jnilearn_PrintHello
 * Method:    printHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnilearn_PrintHello_printHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

然后,编写实现此头文件的C文件com_example_jnilearn_PrintHello.c 如下
#include<stdio.h>  
#include <stdlib.h>  
#include "com_example_jnilearn_PrintHello.h"


/*
 * Class:     com_example_jnilearn_PrintHello
 * Method:    printHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnilearn_PrintHello_printHello
  (JNIEnv *env, jobject object){
	return (*env)->NewStringUTF(env, "Hello from JNI ! ");
}

接着 编写Android.mk 文件 熟悉linux编程的同学对makefile肯定都比教熟悉了。内容如下
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := com_example_jnilearn_PrintHello.c

include $(BUILD_SHARED_LIBRARY)
其中:

LOCAL_MODULE := hello-jni 中的hello-jni  就是我们指定的编译的库文件的名称。(最后生成的文件名字是libhello-jni.so 在我们指定的名称前添加lib)

LOCAL_SRC_FILES := com_example_jnilearn_PrintHello.c 指定我们编译的源文件

include $(BUILD_SHARED_LIBRARY) 指定我们最终生成共享库


最后,我们修改 MainActivity的onCreate方法。添加

PrintHello hello = new PrintHello();
setTitle(hello.printHello());
好了一切都编写好了。


进入工程根目录。执行 ndk-build

如果出现

[armeabi] Compile thumb  : hello-jni <= com_example_jnilearn_PrintHello.c
[armeabi] SharedLibrary  : libhello-jni.so
[armeabi] Install        : libhello-jni.so => libs/armeabi/libhello-jni.so

说明一切OK 。如果没有请确认环境变量是否设置正确。

运行工程 发现标题栏已经变成Hello from JNI ! 。






    

        

    

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值