zoukankan      html  css  js  c++  java
  • Android Studio开发JNI工程

    使用Android Sutdio创建一个新的工程后,接下来记录创建NDK工程的基本步骤。
     
    本文将达到:
    1. 创建NDK工程
    2. 在JNI中输出Log语句
    3. 指定编译的so库的abi版本
    4. 解决在创建NDK工程中的问题
     
    Step: 1. 添加native接口
    注意写好native接口和System.loadLibrary()即可了,并无特别之处。
    P.S:onCreate()中对R.id.txt执行setText(),所以这里需要对xml布局文件按正常的开发步骤进行修改即可。
     
    直接给出代码如下:
    [java] view plain copy 在CODE上查看代码片派生到我的代码片
    1. public class MainActivity extends Activity{  
    2.     static {  
    3.         System.loadLibrary("JniTest");  
    4.     }  
    5.      
    6.     public native String getStringFromNative();  
    7.     @Override  
    8.     protected void onCreate(Bundle savedInstanceState) {  
    9.         super.onCreate(savedInstanceState);  
    10.         setContentView(R.layout.activity_main);  
    11.         TextView txtView = (TextView) findViewById(R.id.txt);  
    12.         txtView.setText(getStringFromNative());  
    13.     }  
    14. }  



    Step: 2.执行Build->Make Project

    这一步骤执行一下,验证工程中并无其它错误,并对工程进行了编译,生成了.class文件.
    .class文件的生成路径是在 app_path/build/intermediates/classes/debug下的.如下图:

    Step: 3.javah生成c头文件

    点击"View->Tool Windows->Terminal",即在Studio中进行终端命令行工具.执行如下命令生成c语言头文件。
    这里需要注意的是要进入 <Project>appsrcmain的目录下执行javah命令,为的是生成的 .h 文件同样是在<Project>appsrcmain路径下,可以在Studio的工程结构中直接看到。
     
    操作命令:
    javah -d jni -classpath <SDK_android.jar>;<APP_classes> lab.sodino.jnitest.MainActivity
    具体操作图如下:

    [java] view plain copy 在CODE上查看代码片派生到我的代码片
    1. javah -d jni -classpath c:UserssodinochenAppDataLocalAndroidsdkplatforms  
    2. android-16android.jar;....uildintermediatesclassesdebug lab.sodino.jnitest.MainActivity  



    对于"主版本51比50新,此编译器支持最新的主版本"则是由于电脑上安装了两个版本的jdk引起的,而当前使用的是旧的jdk。
    把旧的jdk删除,并执行java version命令后显示当前jdk为最新的1.7时,则不会再有此提示了。如下图:

    最后的生成结果:

    Step: 4.编辑c文件

    在main.c文件中实现头文件中的方法,具体功能为直接return回一个String,并且使用android_log打印出相关日志。
    代码如下:
    [cpp] view plain copy 在CODE上查看代码片派生到我的代码片
    1. /* DO NOT EDIT THIS FILE - it is machine generated */  
    2. #include <jni.h>  
    3. #include <android/log.h>  
    4.   
    5. #ifndef LOG_TAG  
    6. #define LOG_TAG "ANDROID_LAB"  
    7. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)  
    8. #endif  
    9.   
    10. /* Header for class lab_sodino_jnitest_MainActivity */  
    11.   
    12. #ifndef _Included_lab_sodino_jnitest_MainActivity  
    13. #define _Included_lab_sodino_jnitest_MainActivity  
    14. #ifdef __cplusplus  
    15. extern "C" {  
    16. #endif  
    17. /* 
    18.  * Class: lab_sodino_jnitest_MainActivity 
    19.  * Method: getStringFromNative 
    20.  * Signature: ()Ljava/lang/String; 
    21.  */  
    22. JNIEXPORT jstring JNICALL Java_lab_sodino_jnitest_MainActivity_getStringFromNative  
    23.   (JNIEnv * env, jobject jObj){  
    24.       LOGE("log string from ndk.");  
    25.       return (*env)->NewStringUTF(env,"Hello From JNI!");  
    26.   }  
    27.   
    28. #ifdef __cplusplus  
    29. }  
    30. #endif  
    31. #endif  
     
    到这里后,我们再执行一个"Build->Make Project",发现"Messages Gradle Build"会给出提示如下:
    [java] view plain copy 在CODE上查看代码片派生到我的代码片
    1. Error:Execution failed for task ':app:compileDebugNdk'.   
    2. > NDK not configured.   
    3. Download the NDK from http://developer.android.com/tools/sdk/ndk/.Then add ndk.dir=path/to/ndk in local.properties.   
    4. (On Windows, make sure you escape backslashes, e.g. C:\ndk rather than C: dk)  
    这里提示了NDK未配置,并且需要在工程中的local.properties文件中配置NDK路径。好了,提示很清楚了,那我们就进入下一步吧。
     
     

    Step: 5.配置NDK

    这一步包括两个动作:
    1.指明ndk路径
    2. 修改build.gradle配置
        工程中共有两个build.gradle配置文件,我们要修改的是在<Project>appuild.gradle这个文件。为其在defaultConfig分支中增加上
    [java] view plain copy 在CODE上查看代码片派生到我的代码片
    1. ndk {  
    2.     moduleName "JniTest"  
    3.     ldLibs "log", "z", "m"  
    4.     abiFilters "armeabi", "armeabi-v7a", "x86"  
    5. }  
        以上配置代码指定的so库名称为JniTest,链接时使用到的库,对应android.mk文件中的LOCAL_LDLIBS,及最终输出指定三种abi体系结构下的so库。
    添加后如下图:
    这时,再执行"Build->Rebuild Project",就可以编译出so文件了。
    但在Window平台上会出现一个问题:
    [java] view plain copy 在CODE上查看代码片派生到我的代码片
    1. Error:Execution failed for task ':app:compileDebugNdk'.  
    2. > com.android.ide.common.internal.LoggedErrorException: Failed to run command:  
    3.  D:Missionadt-bundle-windows dk-r10b dk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=C:UserssodinochenAndroidstudioProjectsJniTest2appuildintermediates dkdebugAndroid.mk APP_PLATFORM=android-21 NDK_OUT=C:UserssodinochenAndroidstudioProjectsJniTest2appuildintermediates dkdebugobj NDK_LIBS_OUT=C:UserssodinochenAndroidstudioProjectsJniTest2appuildintermediates dkdebuglib APP_ABI=armeabi,armeabi-v7a,x86  
    4. Error Code:  
    5.  2  
    6. Output:  
    7.  make.exe: *** No rule to make target `C:UserssodinochenAndroidstudioProjectsJniTest2appuildintermediates dkdebugobj/local/armeabi/objs/JniTest/C_UserssodinochenAndroidstudioProjectsJniTest2appsrcmainjni', needed by `C:UserssodinochenAndroidstudioProjectsJniTest2appuildintermediates dkdebugobj/local/armeabi/objs/JniTest/C_UserssodinochenAndroidstudioProjectsJniTest2appsrcmainjnimain.o'. Stop.  
    出现这个错误很莫名其妙..几番折腾下,找到一个视频出来了大概原因及解决方式:
    出处见Youtube视频 02:50分开始:https://www.youtube.com/watch?v=okLKfxfbz40#t=362
    在Windows下NDK一个bug,当仅仅编译一个文件时出现会出现此问题,解决方法就是再往jni文件夹加入一个空util.c文件即可。如下图:
     

    编译出来的库文件被Studio输出到了下图的路径中

    Step: 6.安装运行

    界面:

    查看Log打印:

     
  • 相关阅读:
    C# 2.0 中Iterators的改进与实现原理浅析
    C#窗口关闭时最小化到托盘
    设计模式有趣解释
    序列化学习
    线程学习
    正则表达式
    .net内存回收与Dispose﹐Close﹐Finalize方法 [摘]
    5.匿名函数lambda
    2dns服务器解析创建
    2.ftp匿名
  • 原文地址:https://www.cnblogs.com/android-blogs/p/5711930.html
Copyright © 2011-2022 走看看