• Android NDK开发


    Android NDK 开发教程(极客学院)

     

    一、Android NDK环境搭建

          使用最新ndk,直接抛弃cygwin,以前做Android的项目要用到NDK就必须要下载NDK,下载安装Cygwin(模拟Linux环境用的),下载CDT(Eclipse C/C++开发插件),还要配置编译器,环境变量,特别麻烦,新版就不需要了。

    方法/步骤

    1. Android官网下载Android的开发工具ADT(Android Development Tool的缩写),该工具集成了最新的ADT和NDK插件以及Eclipse,还有一个最新版本SDK,解压之后就可以用了。
    2. ADT插件:管理Android SDK和相关的开发工具的

       ;

      NDK插件:用于开发Android NDK的插件,ADT版本在20以上,就能安装NDK插件,另外NDK集成了CDT插件 。下载链接见:http://developer.android.com/sdk/index.html
    3. Android官网下载最新的NDK,注:NDK版本在r7以上之后就集成了Cygwin,而且还是十分精简版。

       

      下载链接见:http://developer.android.com/tools/sdk/ndk/index.html

    eclipse配置

    解压ndk并配置环境变量:添加系统环境变量NDK_ROOT为: D:Androidandroid-ndk-r10d。

    1. 打开Eclipse,点Window->Preferences->Android->NDK,设置NDK路径,例如Shamoo的是E:android-ndk-r9c

       

      (如果没有ndk选项,则可能是因为没有ndk插件,自行下载一个放入eclipseplugins下重启即可)

      Android NDK环境搭建
       
       
       
       
    2. 新建一个Android工程,在工程上右键点击Android Tools->Add Native Support...,然后给我们的.so文件取个名字,例如:my-ndk

      Android NDK环境搭建
       
      这时候工程就会多一个jni的文件夹,jni下有Android.mk和my-ndk.cpp文件。Android.mk是NDK工程的Makefile,my-ndk.cpp就是NDK的源文件。
       
    3. 接下来仿着NDK的demo,Hello-JNI工程写一下。使用Alt + '/'可以代码提示!很爽!有木有?

       

       

    4. JNI接口的命名规范是:Java_ + 调用该方法的包名(包名的点用_代替) + _ + 调用该接口的类名 + _ + 方法名,对于实例方法,有两个参数是必要的,一个JNI的环境指针JNIEnv *

      Android NDK环境搭建
       
       
       
    5. 完成了,然后运行。运行之前先编译NDK,然后在编译JAVA代码。

     

     

    二、开发中遇到的问题

    问题一、编译也许会遇到Unable to launch cygpath. Is Cygwin on the path?错误,解决办法如下:

    1.工程右键,点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd

    (注意:这里是正斜杠/)

    2.在C/C++ Build中点击Environment,点Add...添加环境变量NDKROOT,值为NDK的根目录.(注意:这里是反斜杠)

    3.再编译,问题就解决啦!

     

     

    问题二、使用c++来编写本地库,会有一些兼容问题。

    (1)直接黏贴HelloJni的stringFromJNI函数过来测试,提示Method 'NewStringUTF' could not be resolved
    解决方法
    :将(*env)->NewStringUTF(env, "Hello from JNI !")改为return env->NewStringUTF("Hello from JNI !")即可

    原因是:NDK plugin默认为我们生成的是cpp文件,而C与C++调用函数的参数不一致,因此找不到函数,具体参考jni.h中的定义。cpp文件中形如(*env)->Method(env, XXX)改成env->Method(XXX)即可。 

    (2)运行c++生成的.so库,若报以下错误:(既找不到函数)

    No implementation found for native Lcom/dgut/android/MainActivity;.stringFromJNI ()Ljava/lang/String;

    java.lang.UnsatisfiedLinkError: stringFromJNI

    at com.dgut.android.MainActivity.stringFromJNI(Native Method)

    解决方法:

    为供Java调用的c++函数前加入extern "C" 修饰,如:(NDK example里面的cpp文件也是这么声明的,参考hello-gl2) 

    [java] view plaincopy
     
    1. extern "C" {
      JNIEXPORT jstring JNICALL ava_com_wytiger_jnidemo_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz);
      }; 

    2.   
    3. JNIEXPORT jstring JNICALL ava_com_wytiger_jnidemo_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz )  
    4. {  
    5.     return env->NewStringUTF("Hello from JNI bear c++");  
    6. }  

    原因是: 

            被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。

            首先看看C++中对类似C的函数是怎样编译的:作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数voidfoo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
            同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

            因此,若我们没有使用extern "C"修饰函数,按照C语言方式编译和连接,Jni调用将可能找不到该函数。

    问题三、Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml    (这个是NDK工具的一个BUG,若build Target大于minSdkVersion,则会报这个错误,导致无法运行)
    解决方法:在Application.mk文件中添加APP_PLATFORM := android-8   

    问题四、Type 'jint' could not be resolved, and JNIEnv, jclass

    Project Properties -> C/C++ General -> Path and Symbols,选择include标签,Add -> $Android_NDK_HOME/platforms/android-14/arch-arm/usr/include
    选中All languages.  最后Apply -> OK

  • 相关阅读:
    【浏览器】谷歌浏览器快捷键
    【问题】html页面不能自动更新,重启项目也不行。package时可以。
    Hibernate与mybatis的区别
    ssh的执行流畅
    ssm执行流程
    struts的上传下载
    HTML列表
    什么是HTML,HTML的简介,HTML结构
    hadoop hdfs 分布式存储
    面向对象的七大原则
  • 原文地址:https://www.cnblogs.com/wytiger/p/5401185.html
Copyright © 2020-2023  润新知