zoukankan      html  css  js  c++  java
  • JNI 使用笔记

    1.

    实现在的功能是写一个 c++的库 , 去调用jar 包。 

    通过 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved); 方法获得 java 虚拟机。 

    android 平台在加载 .so 的时候会去查找是否实现了 这个函数。如果实现了就会直接调用。

    我们就可以获得 jvm 。 因为每个虚拟机只有一个jvm  。 所以可以保存为全局,在之后通过jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) 

    获得当前线和的env ,因为每个线和有自己的env  所以在使用的时候要保证当前线程正确。 否则就会出错crash

     .cpp 中
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void*) {
        LOGI(" JNI_ONLOAD ...... BEGIN.. OK");
        gc_jvm = jvm;
        gc_env = getEnvForCurrentThread(jvm);
        if (gc_env == NULL) {
            return -1;
        }
    
    
        return JNI_VERSION_1_6;
    }
    .h
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved);

    2.

    要求android 支持 stl  要在 application.mk 中加入 APP_STL := gnustl_static

    ndk编译时默认会去jni 目录下找 Android.mk application.mk 文件。

    所以要需要建一个jni 文件夹,

    因为cpp 文件很多 所以不一定必须放在jni 文件中。在mk 文件中指定相关目录。 

    3.

    生成一个android 可用的jar 包。 android studio 的生成方式 要写个任务。 而且不能带资源。 还是用了eclipes. 

    虽然最终半没有用到资源,其它的jar 包也提取出来了。 

    只是生成了代码的jar 包。

    需要在一个android工程下导出。 

    4 何为NDK,它和SDK以及JNI有什么关系?请前看下图:

       

    JNI (Java Native Interface),Java的本地接口

          JNI是Java众多开发技术中的一门,意在利用本地代码,为Java程序提供 更高效,更灵活的拓展。应用场景包括:对运行效率敏感的算法实现、跨平台应用移植、调用系统的底层驱动、调用硬件等。尽管Java一贯以其良好的跨平台性 而著称,但真正的跨平台之王,应该是C/C++,因为当前世上90%的系统都是基于C/C++编写的。Java的跨平台,是以牺牲效率换来对多种平台的兼 容性,因而JNI可以说是Java短板的补充!举一例子说明,当前流行的移动操作系统Android,一直被说系统操作的流畅性不如IOS,原因在于 Android的App是基于Java开发的,IOS的是基于Object-C开发的,区别在于同样的操作,在IOS上一条指令完成,在Android上 则需要多大三条指令才能完成(数据来自于网络,不一定准确)!于是在Android JellyBean版本中,Google为其引入ProjectButter(黄油计划),在应用层大量使用了本地库,并优化了系统的架构,以提升 Android系统整体的操作反应!

    咔咔,JNI的介绍就先说到这里,总之,JNI是一门技术,是Java Code和C/C++ Code联系的桥梁!

    JNI开发的流程

    1、编写Java Code,如下面的例子:

    public class MainActivity extends Activity {

     @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      Toast.makeText(getApplicationContext(), sayHellow(), Toast.LENGTH_LONG).show();
    }

     public native String sayHellow();  //调用本地方法

     static {
                  System.loadLibrary("Scgps_Client");  //加载本地共享库
            }

    }

    2、编写C/C++ Code,如下面的例子:

    #include
    #include 

    JNIEXPORT jstring JNICALL Java_com_scgps_client_MainActivity_sayHellow(JNIEnv* env, jobject thiz)
    {
    const char * ret = "Hellow Form Ndk";
            return (*env)->NewStringUTF(env, ret);
    }

    3、编译 C/C++ Code,成功并得到本地共享库

        本地共享库是Linux下的叫法,文件扩展名是.so,windows下叫动态链接库,文件扩展名是.dll。前 面说到C/C++才是跨平台之王,这就是其中的道理,面对不同的平台,编译不同的结果。相对于Java的一次编译到处运行的跨平台性牺牲运行效率,C /C++的跨平台性则是牺牲编译时间以及编译的难度。这里的编译难度是指为适应不同平台而做的编译过程的调整,这个活 的难度可大可小,还不一定成功,视乎平台的兼容性以及支持。说到这里,难免会有人喷了:说什么跨平台性,这么复杂还不稳定!的确C/C++的跨平台性是有 局限性的,但是纵观当前的各种平台和系统,有哪家是不支持C/C++本地开发的?只是各自提供的底层API和编译条件不同而已,只需要调整一下C/C++ 的编译代码,通过编译即可运行,难道也不是一件美事?

    4、编译并打包Java

        把本地共享库放置到Java项目的指定目录,一般是libs文件件,Android的项目是libs/armeabi(armeabi 是对应的平台,后面会详讲),然后编译Java的代码即可运行!

    NDK,(Native develop kit),本地开发工具包 

        NDK是Google为Android进行本地开发而放出的一个本地开发工具, 包括Android的Native API、公共库以及编译工具, 注意,NDK需要Android 1.5版本以上的支持哦。

        按照上图的解说,NDK处在开发流程的编译环节,对,简单来说,NDK是JNI开发的一个扩展工具包!针对Android平台,其支持的设备型号繁多,单 单就设备的核心CPU而言,都有三大类:ARM、x86和MIPS,况且ARM又分为ARMv5和ARMv7等等,为何Android又能适配如此之多的 设备?接着JNI开发流程的话,利用NDK,我们可以针对不同的手机设备,编译出对应可运行的本地共享库了,至于如何使用NDK进行编译、开 发,我们留作下次再进行探讨。

    SDK,(Standard Develop Kit),标准开发包

        SDK是Google提供的Android标准开发工具包,里面包含了完整的 API文档,各Android版本的开发库,Android的虚拟机以及Android的打包工具等。众所周知,Android的应用开发语言是 Java,App的运行时是Delvik Runtime,属于JVM的改良版本,官方说Delvik VM更适用于移动设备。一般而言,由于Google的SDK提供了强大又完善的API,开发一般需求的应用,SDK足矣。然而前面已经说过,Java的运 行效率引发了不少问题,因而才有了JNI技术的存在,那SDK和NDK的关系是怎样的呢?NDK是SDK的一个补充。

       

    SDK,JNI,NDK的开发流程

       这个开发流程大致与JNI的开发流程差不多,下面我再详细说明一下每个环节:

       SDK开发,编写Java代码,调用各种Android的API实现功能,编写含有native关键字的代码开始JNI;

       JNI开发,按照 JNI编码规范,编写与Java交互的本地代码,一般就是数据类型的转换,把 C/C++的数据类转换成Java能识别的,或反过来。也因为这样子,我认为JNI其实就是Adapter,作为数据转换层而存在,具体JNI的一般操 作,我之后再分享;

       C/C++开发,编码实现业务逻辑,或调用NDK提供的本地API或库,完成Android平台上特定功能的开发、封装;

       NDK编译,编写.mk文件,编译调试,最后修改.mk文件,针对特定的平台(ARM/x86)做编译结果的优化;

       最后就是SDK编译、打包,上真机调试了...

  • 相关阅读:
    第15周作业
    软件工程结课作业
    第13次作业--邮箱的正则表达式
    第12次作业
    第10次作业
    Java 8 新的时间日期库
    你还在用if-else吗?
    Java并发编程:4种线程池和缓冲队列BlockingQueue
    ZooKeeper学习第八期——ZooKeeper伸缩性(转)
    ZooKeeper学习第七期--ZooKeeper一致性原理(转)
  • 原文地址:https://www.cnblogs.com/blackcatx/p/5997298.html
Copyright © 2011-2022 走看看