参考文档:

http://blog.sina.com.cn/s/blog_a11f64590101924l.html

http://www.cnblogs.com/hoys/archive/2010/10/28/1863612.html

http://www.cnblogs.com/bastard/archive/2012/05/19/2508913.html

http://blog.csdn.net/zhenyongyuan123/article/details/5862054

Android通过JNI来实现Java层调用C层代码。当我们在进行NDK开发时候,并且提供Java层接口,则我们必须创建c代码,然后编译*.so库,编写JNI中的代码,最后Java层通过System.loadLibrary()方法加载*.so动态库,即可实现。

编写一个具有*.so, jni , java整体模块,一般有个步骤:(1)编写Java层代码,里面主要实现两个步骤,一个是定义native方法,另一个是调用System.loadLibrary()方法加载C层要写的动态库;(2)由Java代码所生层的class文件,使用javah命令生成JNI中所需的*.h头文件;(3)实现上面所生存的*.h头文件;(4)编写Android.mk文件,生存*.so库(5)编译整个工程生成apk。

第一:编写Java文件

根据我们需要实现的Java程序,来编写native方法和调用System.loadLibrary()方法加载动态库,一般开发Android工程我们都在Eclipse环境下,因此,这里也在该环境下编写一个Demo。

  1. packagecom.example.nativetest;
  2. publicclassNativeClass {
  3. static
  4. {
  5. System.loadLibrary("NativeClassJni");
  6. }
  7. privatestaticnativeintnativeGetResult(intsrc);
  8. publicintgetResult(intsrc){
  9. returnnativeGetResult(src);
  10. }
  11. }

当我们编写好Java代码后,Eclipse会自动在工程bin目录中生成对应的class文件,里面包含了所有Java文件所生的.class文件。

第二:由javah命令生成JNI中所需的*.h头文件

javah命令是将Java源文件生存C头文件,具体原理可参考:http://blog.csdn.net/sheji105/article/details/7730223http://blog.csdn.net/archfree/article/details/6155995

在第一步中,我们知道在工程的bin/classes/*目录里有生成的.class文件,这里就需要使用javah命令将对应的NativeClass.class生成*.h文件,我们进入到工程根目录里面,执行如下命令:

javah-classpath
./bin/classes -d jni com.example.nativetest.NativeClass

该命令解析如下:-classpath选项表示工程Java文件所生成的所有.class所在的目录,必须指定bin/classes目录下面,即所有.class所在的目录,不能是它的子目录或者父目录,否则就会出现错误:error:cannot
access com.example.nativetest.NativeClass ,这点非常重要。-djni表示在当前的目录下新建一个jni文件夹,然后将生成的*.h文件放入到该目录中,因为测试当前目录是工程的根目录,因此,会在根目录中新建jni文件夹;若无该选先,则生成的.h文件会在当前目录中。

当我们进入jni文件中,就会发现所生成的头文件com_exmaple_nativetest_NativeTest.h。

  1. /*DO NOT EDIT THIS FILE - it is machine generated */
  2. #include<jni.h>
  3. /*Header for class com_example_nativetest_NativeClass */
  4. #ifndef_Included_com_example_nativetest_NativeClass
  5. #define_Included_com_example_nativetest_NativeClass
  6. #ifdef__cplusplus
  7. extern"C" {
  8. #endif
  9. /*
  10. *Class: com_example_nativetest_NativeClass
  11. *Method: nativeGetResult
  12. *Signature: (I)I
  13. */
  14. JNIEXPORTjint JNICALL Java_com_example_nativetest_NativeClass_nativeGetResult
  15. (JNIEnv*, jclass, jint);
  16. #ifdef__cplusplus
  17. }
  18. #endif
  19. #endif

第三:实现.h头文件,编写c/c++文件

我们要在前面所生成的.h文加夹目录中编写c/c++文件来实现该头文件,*.c和*.cpp文件的名称由用户自己定义,但是必须要在Android.mk文加中的LOCAL_SRF_FILES指向该文件即可,一般情况下,取和*.h相同的名字。

上面实现的.cpp文件内容如下:

  1. #include<jni.h>
  2. #include<com_example_nativetest_NativeClass.h>
  3. /*
  4. *Class: com_example_nativetest_NativeClass
  5. *Method: nativeGetResult
  6. *Signature: (I)I
  7. */
  8. JNIEXPORTjint JNICALL Java_com_example_nativetest_NativeClass_nativeGetResult
  9. (JNIEnv* env, jclass obj, jint in)
  10. {
  11. returnin + in;
  12. }

很多人在最终成功编译so并载入so后,在java层调用native方法时会出现java.lang.UnsatisfiedLinkError这个异常.原因是就在第一行,这里c和c++是有些区别的,如果用c实现的话,只需要includejni.h即可,但是如果用c++实现,那么必须要include你刚刚生成的.h文件,而不是jni.h.虽然编译可以通过,但是调用时你会发现报了java.lang.UnsatisfiedLinkError这个异常.原因就是java层没找到对应的方法.还有就是c和c++语法上的一些小区别,但这些错误是可以在编译so期间发现的.

第四:编写Android.mk文件,生成*.so动态库

当我们实现好.c或者.cpp文件后,编写Android.mk文件,来生成动态库,一般使用NDK工具进行生成,首先是下载ndk包,然后设计全局变量,进入Android.mk文件夹中执行ndk编译命令即可。

ndk编译命令使用参考:

http://www.cnblogs.com/lipeil/archive/2012/08/27/2659378.html

http://blog.csdn.net/laczff21/article/details/7542236

我们进入.c,.h, Android.mk所在的文件下面,然后执行ndk编译命令:

ndk-build

信息如下:

abc@abc:~/workspace/NativeTest/jni$ndk-build

AndroidNDK:
WARNING: APP_PLATFORM android-19 is larger thanandroid:minSdkVersion 8
in/home/archermind/workspace/NativeTest/AndroidManifest.xml

[armeabi]Compile++ thumb: NativeClassJni <=com_example_nativetest_NativeClass.cpp

[armeabi]StaticLibrary : libstdc++.a

[armeabi]SharedLibrary : libNativeClassJni.so

[armeabi]Install : libNativeClassJni.so =>libs/armeabi/libNativeClassJni.so

我们可以看到,在工程目录libs生成了一个armeabi文件夹,里面有一个libNativeClassJni.so文件,就是NDK生成的动态库,注意,这个名称前面的lib是系统自动加上去的,在Java代码中的System.loadLibrary()中是不需要,即只是System.loadLibrary(NativeClassJni).

第五:编译整个工程

当.so库编译好之后,我们在Eclipse里面对整个工程进行编译,生成apk,导入到Devices里面即可运行。

Android 中JNI创建实例的更多相关文章

  1. Android中JNI编程的那些事儿(1)

    转:Android中JNI编程的那些事儿(1)http://mobile.51cto.com/android-267538.htm Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须 ...

  2. 【转】Android中JNI的使用方法

    Android中JNI的使用方法 首先看一下Android平台的框架图:(网上盗用) 可以看到Android上层的Application和ApplicationFramework都是使用Java编写, ...

  3. Android中JNI的使用方法(转载)

    Android中JNI的使用方法 首先看一下Android平台的框架图:(网上盗用) 可以看到Android上层的Application和ApplicationFramework都是使用Java编写, ...

  4. Android中的创建型模式总结

    共5种,单例模式.工厂方法模式.抽象工厂模式.建造者模式.原型模式 单例模式 定义:确保某一个类的实例只有一个,而且向其他类提供这个实例. 单例模式的使用场景:某个类的创建需要消耗大量资源,new一个 ...

  5. Android中JNI编程详解

    前几天在参加腾讯模拟考的时候,腾讯出了一道关于JNI的题,具体如下: JNI本身是一个非常复杂的知识,但是其实对于腾讯的这道题而言,如果你懂JNI,那么你可能会觉得这道题非常简单,就相当于C语言中的h ...

  6. 【转载】如何在Android中避免创建不必要的对象

    在编程开发中,内存的占用是我们经常要面对的现实,通常的内存调优的方向就是尽量减少内存的占用.这其中避免创建不必要的对象是一项重要的方面. Android设备不像PC那样有着足够大的内存,而且单个App ...

  7. Kotlin 第二弹:Android 中 PDF 创建与渲染实践

    这是 Kotlin 练习的的第二篇.这一篇的由来是因为刚刚在 Android 开发者官网查看 API 的时候,偶然看到了角落里面的 pdf 相关. 我仔细看看了详细文档,发现这个还蛮有意思的,关键是编 ...

  8. Android中JNI 的一些常用Method说明

    Android JNI和NDK关系  1.什么JNI Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程 ...

  9. Android中JNI的使用方法

    可以看到Android上层的Application和ApplicationFramework都是使用Java编写,底层包括系统和使用众多的LIiraries都是C/C++编写的. 所以上层Java要调 ...

随机推荐

  1. [WF] Quickstart Sample

    [WF] Quickstart Sample 前言 Workflow Foundation(WF),总是给人一种很有用.可是却不知道怎么用的印象.这主要是因为前置的功课太多.要整合很多底层知识,才能完 ...

  2. sharepoint 2013 文件“/_controltemplates/SPMRB/AllStatBookingsForm.ascx”不存在

    现象: 文件“/_controltemplates/SPMRB/AllStatBookingsForm.ascx”不存在. 分析: 此代码在sp2010好用,但是在sp2013则报以上错误. 解决办法 ...

  3. linux服务器如何设置目录权限,让开发只能在测试目录下开发,不在线上目录上开发

    当一台服务器上,既有测试环境,也有生成的环境,开发需要在线上测试,如果开发生产环境的权限,那开发容易误操作 需求如下: (1)生产环境的代码,必须有专用的账号登陆进行管理 (2)开发测试环境的代码,开 ...

  4. sudo gem install cocoapods 没反应问题

    1. 尝试更新 sudo gem update --system 2. 查看安装详细 sudo gem install cocoapods -V 3.详细使用有个链接 http://blog.csdn ...

  5. IOS字典NSDictionary与NSMutableDictionary知识点

    字典中的元素是以键值对的形式存储的,键值对的键和值,都是任意的对象,但是键往往使用字符串,字典存储对象的地址没有顺序,字典的遍历分为:键的遍历和值的遍历,字典与数组的区别:数组讲究顺序,而字典可以快速 ...

  6. View的生命周期

    当一个进入一个新viewController的时候,viewController的view的生命周期一般是这样的: 1.先判断内存是否有这个View a.没有的话:生命周期为loadView-> ...

  7. 【原】PSD图标素材的全自动切图方法,适用于IOS、安卓、web前端等领域

    屌丝个人开发者经常遇到的尴尬问题是,自己不会设计UI素材又请不起专业的美工.最好的方式是去网上下载符合自己需求的素材修修改改直接用上.但是,在这个过程中会发现很多下载下来的素材是PSD格式的,很多图标 ...

  8. Sencha Cmd是什么

    Sencha Cmd的简介 ~~~~~~~~~~~~~~~~~~~~~~~ Sencha cmd 是一个跨平台的命令行工具,它从你应用程序的新创建到部署入产品中的整个生命周期都提供了许多自动化的执行任 ...

  9. paas架构之docker——安装

    1. 概要 本文描述docker的安装 参考官方文档:https://docs.docker.com/engine/installation/linux/ubuntulinux/ 安装操作系统: Ub ...

  10. log4net资料收集

    Log4net 日志使用介绍 http://www.cnblogs.com/jys509/p/4699813.html log4net Tutorial http://www.codeproject. ...