AndroidStudio使用JNI教程
环境必须有NDK,androidstudio
如果是Android—22(含)以上的包,要让主Activity继承Avtivity,而不是其他Androidstudio自动继承的类,不要用23以上的包,会报v7包找不到。(该问题以后再解决)
-
在project目录下的gradle.propertied添加一句
android.useDeprecatedNdk=true
说明可以使用NDK
具体实现
-
在Activity中定义一个native方法,如下:
public native String getStringFromNative();
然后make project一下 (目的就是编译成对应的class文件。然后根据生成的class文件,利用javah生成对应的.h头文件)
- 点开Androidstudio的Terminal标签页,默认进入到该项目的app文件夹下。用cd src/main 切换到main目录下。
我的路径为:E:\AndroidApp\NDKDemo\app\src>cd main
用javah生成c的头文件,(除了路径可能跟我不同,其他任何一个标点都要跟我的一样):
E:\AndroidApp\NDKDemo\app\src\main>javah -d jni -classpath E:\Android\SDK\platforms\android-22\android.jar;..\..\build\intermediates\classes\debug com.example.ndkdemo.MainActivity
前面javah -d jni -classpath 是固定 后面跟的是 "SDK的android.jar文件路径" ;.... "工程路径加包名加Activity名"
就会发现在main目录下多了一个jni文件夹,里面有生成好的头文件:com_example_ndkdemo_MainActivity.h
会生成很多#undef #define信息,但最主要有如下函数:
JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_MainActivity_getStringFromNative(JNIEnv *, jobject);
- 在jni目录下新建一个 .c文件。来实现头文件里面声明的方法。我的叫main.c
内容如下:
#include "com_example_ndkdemo_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_example_ndkdemo_MainActivity_getStringFromNative
(JNIEnv * env, jobject obj){
return (*env)->NewStringUTF(env,"I'm comes from to Native Funtion!");
}
在jni下面再建一个空的.c文件。要不编译有问题,这个应该是android studio的一个bug。
这时,Androidstudio会报NDK错,叫你选择NDK目录,选择目录即可
这也可以手动执行:
在 local.properties 文件中设置ndk的路径:
我的是:ndk.dir=F:\NDK\NDK
- 在app目录下的 build.gradle中设置库文件名(生成的so文件名):
找到 defaultConfig 这项,在里面添加如下内容:
ndk{
moduleName "MyJni" //设置库(so)文件名称
}
在activity中添加一个TextView以便显示从native方法中获取的字符信息(修改对应的布局文件添加一个TextView,并设定其ID值)。
在activity中增加对so的加载:
static {
System.loadLibrary("MyJni");
}
附上主Activity代码:
public class MainActivity extends Activity {
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
tv.setText(getStringFromNative());
}
public native String getStringFromNative();
static {
System.loadLibrary("MyJni");
}
}
编译,并运行。界面上就会显示从native方法传过来的值。