说到 NDK 开发,其实是为了有些时候为了项目需求需要调用底层的一些 C/C++ 的一些东西;另外就是为了效率更加高些。谷歌主力推动 Android Studio 这个是个不错的工具,至少现在来看在 Eclipse 上能做到的 这边都有,这边有的Eclipse上不一定有。但是为了复习,两个IDE都记录一下。
准备工作
去官网下载NDK,这个需要翻墙,下面发放福利了。
- http://yunpan.cn/cdFTKe3Ty4D9e 访问密码 6776(Android-ndk-r10e0)
- http://yunpan.cn/cdFTQAmSAI9sY 访问密码 f594(我下载的翻墙工具,勉强过得去)
下载好了ndk,双击解压到当前目录,貌似时间有点忽悠人,耐心等待一下。接下来我们可以开始NDK开发了。之前我们可以去ndk目录下找samples,找官网给的例子。学习ing中……先从Eclipse开始吧。
一、Eclipse DNK开发
1、建立一个项目HelloNDK
在Activity 中写一个native方法
public class MainActivity extends Activity {
static{
System.loadLibrary("hello");
}
/**
* native
* @return
*/
public static native String getStringFromC();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView text = (TextView) findViewById(R.id.textView);
text.setText(getStringFromC());
}
}
写好了native方法后。来到java目录,执行javah命令,生成c/c++所需要的头文件xxx.h
-classpath 是项目bin目录下class文件
-d 输出目录(jni,是我刚才在工程目录下建好的jni文件夹)
**xxx/xxx/xxx.h文件**
extern "C" {
/*
* Class: com_example_jnindk_MainActivity
* Method: getStringFromC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_jnindk_MainActivity_getStringFromC
(JNIEnv *, jclass);
#ifdef __cplusplus
}
之后去官网的例子jni文件夹把Android.mk,application.mk复制到现在的工程jni文件夹。
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello
LOCAL_SRC_FILES := hello.c
include $(BUILD_SHARED_LIBRARY)
注意LOCAL_MODULE本地的moduleName。LOCAL_SRC_FILES本地写的c文件。
2、我们在jni文件夹中写一个hello.c文件
#include<stdio.h>
#include<stdlib.h>
#include "com_example_jnindk_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_example_jnindk_MainActivity_getStringFromC
(JNIEnv * env, jclass jclass){
return (*env)->NewStringUTF(env, "Hello from the world !");
};
返回一个字符串。仔细看类名,第一个是Java,接下是包名+类名+方法名。这里包名跟我cmd中写的类名不一样,失误,上面是我随便写的,注意一下就可以。
3、生成so文件
成功后会在工程目录生成一个obj文件夹,这里可以找到so文件。
做过百度地图的朋友们有没有看到so,感到很亲切。接下我们就去Maintivity中调用了。
static{
System.loadLibrary("hello");
}
测试通过。
二、下面把NDK开发切换到Android studio下。
前面的步骤差不多,只是不需要我们敲命令去生成so文件,我们在build.gradle中去配置就可以了。
注意ndk的位置,defaultConfig下面。
ndk的位置
刚在Eclipse中我们手动命令生成so文件,as只需要配置重新build的时候这个so文件生成都哪儿去了呢。请看。
看lib,so文件移植到这么多的APP_ABI里面。这是如何做到的,我们发现application.mk中的配置。和build.gradle中ndk的配置。
APP_ABI := APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64
APP_PLATFORM := android-
三:错误总结
1、`Error:Execution failed for task ‘:app:compileDebugNdk’.
com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process ‘command ‘D:\Users\htj-123\AppData\Local\Android\android-ndk-r10b\ndk-build.cmd” finished with non-zero exit value 2`
这个是我工程目录有空格导致的。
2、Process: com.eddie.ndk, PID: 23210
java.lang.UnsatisfiedLinkError: Native method not found: com.eddie.ndk.MainActivity.getStringFromC:()Ljava/lang/String;
1) Android.mk里面:
最后生成的时候
LOCAL_MODULE := testcmmb_jni 千万不能写成 libtestcmmb_jni!!!!虽然编译出来的文件名称貌似相同
2) C++ 的代码里面:
extern “C”{
。。。
}
这是因为生成的二进制文件中,C和C++的符号表不相同造成的。Jni是按照C的生成规则去找函数的, 所以要加上extern C使编译器把函数按照C的规则编译 这样才能被JAVA调用
项目源码:Android NDK demo欢迎下载。