你的位置:首页 > Java教程

[Java教程]最新版Android Studio 创建JNI教程


本文主要目的如题所示,并针对一些创建过程中可能会遇到的问题提供解决方案。

本文主要参考:http://ph0b.com/android-studio-gradle-and-ndk-integration/,里面有视频讲解,嫌看文档麻烦

的可以直戳进去。。。

主要思路:在一个类中创建native方法,编译生成该类的class文件,再去生成该类的头文件,有了头文件之后在c文件中编写代码的具体实现,配置sdk、ndk路径、给ndk模块起名,最后就是对该方法的调用。

详细步骤如下:

1、本地创建native方法

新建一个空的android工程,在类中声明native方法

建议:不在activity中声明native方法,一是为了设计上的简洁并功能分离,二是创建头文件时避免不要的麻烦。

public class JniUtil {  public native String getStringFromNative();}

 

2、编译

如图,主要是为了得到带有native方法类的.class文件

image

编译通过之后如下图所示

image

在此目录下会出现JniUtil.class文件。

3、制作JniUtil.class的头文件

3.1打开terminal终端,主要有两种方法:

3.1.1.菜单栏View视图下,选择tool windows,再点击terminal即可进入

3.1.2.快捷键进入

image

3.2 jni生成头文件

终端进入app\src\main文件下,再输入以下指令(javah及以后),如图

image

主要格式为 javah –d –jni –classpath,

不熟悉javah指令的朋友可以输入javah -help帮助下。

-o <file>                输出文件 (只能使用 -d 或 -o 之一)                                         
-d <dir>                 输出目录                                                                  
-v  -verbose             启用详细输出                                                              
-h  --help  -?           输出此消息                                                                
-version                 输出版本信息                                                              
-jni                     生成 JNI 样式的标头文件 (默认值)                                          
-force                   始终写入输文 件                                                                                                               
-classpath <path>        从中加载类的路径
                  

路径介绍:  e:\android-sdks\platforms\android-23\android.jar  为此android工程所依赖的sdk版本,最终锁定到android.jar文件; ..\..\build\intermediates\classes\debug com.example.hitman.final.JniUtil代表生成头文件所依据的.class文件.两个路径中间要用英文分号隔开

成功之后会看到main文件夹下多出一个-jni文件(有的可能直接生成jni文件夹)。里面有编译好的头文件

image

可能遇到的问题:

1)、某些类文件找不到  更多情况下是在activity中直接声明native方法导致的,由于AS工程依赖的android版本比较高,这就导致e:\android-sdks\platforms\android-23\android.jar 中没有所需的类,即javah –d找不到所需路径。以下文为例

import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity {}

View Code

 

这种情况会导致appCompatActivity找不到,因为e:\android-sdks\platforms\android-23\android.jar 路径中没有这个类,appCompatActivity的实际路径是 E:\android-sdks\extras\android\m2repository\com\android\support \appcompat-v7\23.1.1(本人路径)

image

解决方案:将native方法迁出activity中,此方法笔者编译一次通过或者将public class MainActivity extends AppCompatActivity 改为public class MainActivity extends Activity 。

3.3创建.c文件,一定要在jni文件夹中

这时我们要注意,将-jni文件夹改名为jni,否则编译时build文件下不能生成ndk库(笔者遇到过这个问题),改名后再jni文件夹下新建.c文件,任意取名为main.c。内容下图所示:

#include <com_example_hitman_finaljni_JniUtil.h> JNIEXPORT jstring JNICALL Java_com_example_hitman_finaljni_JniUtil_getStringFromNative    (JNIEnv *env, jobject obj){  return (*env)->NewStringUTF(env,"HELLO FROM NATIVEJNI");};

View Code

 

注意事项:一定要添加新建的头文件,如蓝色文字所示。

可能遇到问题:有些AS的bug必须要创建两个.c文件才能编译成功。

关于.c文件的语法问题可参考http://blog.chinaunix.net/uid-26000296-id-5296362.html。

4、配置sdk、ndk路径,并编译

4.1打开local.propertiesZ文件

image

ndk.dir=E\:\\android-sdks\\ndk-bundle
sdk.dir=E\:\\android-sdks

4.2设置好路径之后编译一下就能看到build问价下的ndk中的库了

image

可能遇到的问题

Error:Execution failed for task ':app:compileDebugNdk'.
> Error: NDK integration is deprecated in the current plugin.  Consider trying the new experimental plugin.  For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental.  Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.

这个可以在在gradle.properties 文件里面添加 android.useDeprecatedNdk=true 后重新编译即可

image

5、给自己的库取名字并在activity中调用native方法

5.1在app目录选的build.gradle中添加ndk

image

5.2加载本地库,并调用native方法

只需在activity中调用TextView.setText()方法就可以了。代码如下

public class MainActivity extends AppCompatActivity {   static{     System.loadLibrary("MyLib");   }   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.content_main);     TextView txt=(TextView)findViewById(R.id.txt);     JniUtil util=new JniUtil(this);     txt.setText(util.getStringFromNative());       }     });   } }

 

至此,确保编译通过就能能正常运行,模拟器效果图如下:

image

如有问题、意见或者建议的欢迎留言交流。