本文主要目的如题所示,并针对一些创建过程中可能会遇到的问题提供解决方案。
本文主要参考: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文件
编译通过之后如下图所示
在此目录下会出现JniUtil.class文件。
3、制作JniUtil.class的头文件
3.1打开terminal终端,主要有两种方法:
3.1.1.菜单栏View视图下,选择tool windows,再点击terminal即可进入
3.1.2.快捷键进入
3.2 jni生成头文件
终端进入app\src\main文件下,再输入以下指令(javah及以后),如图
主要格式为 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文件夹)。里面有编译好的头文件
可能遇到的问题:
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 { }
这种情况会导致appCompatActivity找不到,因为e:\android-sdks\platforms\android-23\android.jar 路径中没有这个类,appCompatActivity的实际路径是 E:\android-sdks\extras\android\m2repository\com\android\support \appcompat-v7\23.1.1(本人路径)
解决方案:将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"); };
注意事项:一定要添加新建的头文件,如蓝色文字所示。
可能遇到问题:有些AS的bug必须要创建两个.c文件才能编译成功。
关于.c文件的语法问题可参考http://blog.chinaunix.net/uid-26000296-id-5296362.html。
4、配置sdk、ndk路径,并编译
4.1打开local.propertiesZ文件
ndk.dir=E\:\\android-sdks\\ndk-bundlesdk.dir=E\:\\android-sdks
4.2设置好路径之后编译一下就能看到build问价下的ndk中的库了
可能遇到的问题
:
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 后重新编译即可
5、给自己的库取名字并在activity中调用native方法
5.1在app目录选的build.gradle中添加ndk
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()); } }); } }
至此,确保编译通过就能能正常运行,模拟器效果图如下:
如有问题、意见或者建议的欢迎留言交流。