转载请注明出处:http://blog.csdn.net/langtuteng136/article/details/50894142


前言: 在写这篇博客前,找了很多关于Android jni 开发的教程,但大都是基于eclipse 中开发的,就算是找到了用Android studio开发的教程,也没有一个能正确成功的,当时就感觉真是莫名的恼火,不过还好,最后按照自己的理解试成功了,下面就来仔细说下过程,有点多,因为要把我自己遇到的坑说出来。


注意:因为使用的工具和SDK版本不同,过程可能就不同,我把我试验过的几种情况都会说下。

一、工具和SDK版本:Android studio1.51, SDK版本:23 (最新的6.0)

二、工具和SDK版本:Android studio1.51, SDK版本:21 


在这两种情况之前你必须做好一件事:安装NDK。过程如下:

在setting 中appearance -> Android SDK -> SDK Tools -> Android NDk 打钩,然后点击apply -> OK. 如下图:

Android Jni 开发(Android studio)_第1张图片


自动安装好DN卡之后,会在 local.properties 中有显示:如下图

Android Jni 开发(Android studio)_第2张图片


到此ND就安装完成了,那么接下来就是关键时刻了,先来看看情况一的具体过程:

1.  新建一个工程,就是一个简单的空白工程,功能也没有

2.  定义native 接口 和 加载即将生成的库。就几行代码,代码如下:

package zhanghuan.cn.jnitest1;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.TextView;public class MainActivity extends AppCompatActivity {    static {        System.loadLibrary("JniTest");    }    public native String getStringFromNative();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView textView = (TextView)findViewById(R.id.text);        textView.setText(getStringFromNative());  // 调用接口    }}

3. 写好接口之后接下来就是关键了,点击 Build -> Make Project, 如下图:

Android Jni 开发(Android studio)_第3张图片

然后在底部的状态栏Messages 中查看Build的情况,必须是0错误才行,如下图:

Android Jni 开发(Android studio)_第4张图片

4. Build 成功之后,就在Terminal 命令行中开始生成.h 文件

命令为:

javah -d jni -classpath D:\tools\android-sdk\platforms\android-23\android.jar;D:\MyProject\AndroidStudio\JniTest1\app\src\main\java zhanghuan.cn.jnitest1.MainActivity

就是这一步卡了我好久,之前找的教程每个的命令都是这样的:

javah -d jni -classpath D:\tools\android-sdk\platforms\android.jar;..\..\build\intermediates\classes\debug zhanghuan.cn.jnitest1.MainActivity

结果报错  “找不到android.support.v7.app.AppCompatActivity的类文件” 如下图:



怎么试都不成功,最后发现除非不用V7特性,不继承AppCompatActivity 类,继承成普通的Activity就没事,这其中的差异我在后面会说的。但是我想如果在AppCompatActivity不应该不行的,虽然这是新特性,但它肯定能包容以前的。既然在debug 这中找不到,那我就直接在main 中指定类文件,不在debug中找了,结果让我发现居然成功了!当时心里呼了好长的一口气。成功的命令就是上面的第一个命令,直接指向类文件,然后生成了.h 文件,但是这个.h 文件和用debug 中的类文件生成的.h 文件是有区别的,这个区别待会在后面把.h 文件一对比就知道了。

回归正题,命令成功之后,在main 目录下回生成jni目录,然后还有一个.h 文件:如下图:

Android Jni 开发(Android studio)_第5张图片


我贴下.h 文件的代码:

/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class zhanghuan_cn_jnitest1_MainActivity */#ifndef _Included_zhanghuan_cn_jnitest1_MainActivity#define _Included_zhanghuan_cn_jnitest1_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class:     zhanghuan_cn_jnitest1_MainActivity * Method:    getStringFromNative * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_zhanghuan_cn_jnitest1_MainActivity_getStringFromNative  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
5. 复制.h 文件放在相同的目录下,改个名称(名字任意)为my.c , 代码如下:

#include "zhanghuan_cn_jnitest1_MainActivity.h"JNIEXPORT jstring JNICALL Java_zhanghuan_cn_jnitest1_MainActivity_getStringFromNative  (JNIEnv * env, jobject job) {  return (*env)->NewStringUTF(env, "Hello form JNI!");}

但是这时你会发现有错误,NDK support is an experimental feature and all use cases are not yet supported, 如下图:

Android Jni 开发(Android studio)_第6张图片

解决方法是在 gradle.properties 文件中加入一句代码: 

android.useDeprecatedNdk=true


6. 在app 中的build.gradle 文件的defaultConfig 中加入NDK配置,指定生成的so文件名和适配的arm 类型. 加入代码:

 ndk{            moduleName "JniTest"            abiFilters "armeabi", "armeabi-v7a", "x86"        }
我的build.gradle 文件代码如下:

apply plugin: 'com.android.application'android {    compileSdkVersion 23    buildToolsVersion "23.0.2"    defaultConfig {        applicationId "zhanghuan.cn.jnitest1"        minSdkVersion 11        targetSdkVersion 23        versionCode 1        versionName "1.0"        ndk{            moduleName "JniTest"            abiFilters "armeabi", "armeabi-v7a", "x86"        }    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    testCompile 'junit:junit:4.12'    compile 'com.android.support:appcompat-v7:23.2.1'}

到此,基本步骤就全部完成了,然后就直接运行一下,看下效果,效果图如下:

Android Jni 开发(Android studio)_第7张图片


成功完成!如果有兴趣可以看下下面的第二种情况。


好了,接下来我们就看看第二种情况:不使用V7。

1. 前面的几步步骤和第一种情况是一样的,到第4步的命令行开始有重要的差别, 我就直接跳到命令行那步了,命令如下:

javah -d jni -classpath D:\tools\android-sdk\platforms\android-21\android.jar;D:\MyProject\AndroidStudio\JinTest\app\build\intermediates\classes\debug zhanghuan.cn.jintest.MainActivity

注意如果出错要写绝对的地址,网上的教程都是什么”..\..\buidl\...“这种写法,但是我一次都没成功,折腾了很久都没成功,如果你成功了就请告诉我。

最后生成的.h 文件代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class zhanghuan_cn_jintest_MainActivity */#ifndef _Included_zhanghuan_cn_jintest_MainActivity#define _Included_zhanghuan_cn_jintest_MainActivity#ifdef __cplusplusextern "C" {#endif#undef zhanghuan_cn_jintest_MainActivity_BIND_ABOVE_CLIENT#define zhanghuan_cn_jintest_MainActivity_BIND_ABOVE_CLIENT 8L#undef zhanghuan_cn_jintest_MainActivity_BIND_ADJUST_WITH_ACTIVITY#define zhanghuan_cn_jintest_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L#undef zhanghuan_cn_jintest_MainActivity_BIND_ALLOW_OOM_MANAGEMENT#define zhanghuan_cn_jintest_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L#undef zhanghuan_cn_jintest_MainActivity_BIND_AUTO_CREATE#define zhanghuan_cn_jintest_MainActivity_BIND_AUTO_CREATE 1L#undef zhanghuan_cn_jintest_MainActivity_BIND_DEBUG_UNBIND#define zhanghuan_cn_jintest_MainActivity_BIND_DEBUG_UNBIND 2L#undef zhanghuan_cn_jintest_MainActivity_BIND_IMPORTANT#define zhanghuan_cn_jintest_MainActivity_BIND_IMPORTANT 64L#undef zhanghuan_cn_jintest_MainActivity_BIND_NOT_FOREGROUND#define zhanghuan_cn_jintest_MainActivity_BIND_NOT_FOREGROUND 4L#undef zhanghuan_cn_jintest_MainActivity_BIND_WAIVE_PRIORITY#define zhanghuan_cn_jintest_MainActivity_BIND_WAIVE_PRIORITY 32L#undef zhanghuan_cn_jintest_MainActivity_CONTEXT_IGNORE_SECURITY#define zhanghuan_cn_jintest_MainActivity_CONTEXT_IGNORE_SECURITY 2L#undef zhanghuan_cn_jintest_MainActivity_CONTEXT_INCLUDE_CODE#define zhanghuan_cn_jintest_MainActivity_CONTEXT_INCLUDE_CODE 1L#undef zhanghuan_cn_jintest_MainActivity_CONTEXT_RESTRICTED#define zhanghuan_cn_jintest_MainActivity_CONTEXT_RESTRICTED 4L#undef zhanghuan_cn_jintest_MainActivity_MODE_APPEND#define zhanghuan_cn_jintest_MainActivity_MODE_APPEND 32768L#undef zhanghuan_cn_jintest_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING#define zhanghuan_cn_jintest_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L#undef zhanghuan_cn_jintest_MainActivity_MODE_MULTI_PROCESS#define zhanghuan_cn_jintest_MainActivity_MODE_MULTI_PROCESS 4L#undef zhanghuan_cn_jintest_MainActivity_MODE_PRIVATE#define zhanghuan_cn_jintest_MainActivity_MODE_PRIVATE 0L#undef zhanghuan_cn_jintest_MainActivity_MODE_WORLD_READABLE#define zhanghuan_cn_jintest_MainActivity_MODE_WORLD_READABLE 1L#undef zhanghuan_cn_jintest_MainActivity_MODE_WORLD_WRITEABLE#define zhanghuan_cn_jintest_MainActivity_MODE_WORLD_WRITEABLE 2L#undef zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_DIALER#define zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_DIALER 1L#undef zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_DISABLE#define zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_DISABLE 0L#undef zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL#define zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L#undef zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL#define zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L#undef zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_SHORTCUT#define zhanghuan_cn_jintest_MainActivity_DEFAULT_KEYS_SHORTCUT 2L#undef zhanghuan_cn_jintest_MainActivity_RESULT_CANCELED#define zhanghuan_cn_jintest_MainActivity_RESULT_CANCELED 0L#undef zhanghuan_cn_jintest_MainActivity_RESULT_FIRST_USER#define zhanghuan_cn_jintest_MainActivity_RESULT_FIRST_USER 1L#undef zhanghuan_cn_jintest_MainActivity_RESULT_OK#define zhanghuan_cn_jintest_MainActivity_RESULT_OK -1L/* * Class:     zhanghuan_cn_jintest_MainActivity * Method:    getStringFromNative * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_zhanghuan_cn_jintest_MainActivity_getStringFromNative  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif


是不是发现和第一种情况生成的.h 文件不同,多了很多的东西。不过这些东西好像然并卵,如果你知道其中的区别还请留言告诉我,非常感谢。

当然了,你还可以用第一种情况中的命令,也是OK的,同时不加上-classpath 和 android.jar,只指定要编译的类文件和.h文件目录就可以,如下:

javah -d jni D:\MyProject\AndroidStudio\JinTest\app\build\intermediates\classes\debug zhanghuan.cn.jintest.MainActivity

-d jni 是指定.h 生成后放的位置,不要自己建也是可以的。


最后生成的.so 文件在 app\build\intermediates\ndk\debug\lib 下,如下图:

Android Jni 开发(Android studio)_第8张图片


到此,全部的情况都已介绍完毕,当然了,如果你在做的时候有问题的话欢迎留言,我们大家一起讨论交流。

源码我放在了github上:

https://github.com/john123fd/AndroidJNI21

https://github.com/john123fd/AndroidJNIV7










更多相关文章

  1. 分析Android 根文件系统启动过程(init守护进程分析)
  2. 在Ubuntu16.04上下载并编译Android内核源代码
  3. Android 根文件系统启动过程(init进程 详细分析)
  4. 批量反编译Android XML文件Python脚本
  5. android文件管理实现源码
  6. Android 最简单的SD卡文件遍历程序
  7. Android实用代码片段(一)

随机推荐

  1. 解决Android(安卓)Studio和Android(安卓)
  2. Android(安卓)4.0.1 源码下载,编译和运行
  3. Gradle多渠道打包
  4. Android工程集成flutter
  5. android Manifest.xml选项-android:Confi
  6. android 目录结构,adb环境变量配置
  7. 修复Android(安卓)App在开机后入口类被启
  8. Android(安卓)屏幕设置
  9. This Android(安卓)SDK requires Android
  10. Android(安卓)实现View中添加子元素的动