Android Studio ndk-Jni开发详细

http://www.open-open.com/lib/view/open1451917048573.html

Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C、C++ 和汇编语言)编写的应用程序和库进行交互操作。
由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Bytecode之后,必须靠Dalvik虚拟机(VM: Virtual Machine)来执行。VM在Android平台里,扮演很重要的角色。
(多的咱不说了,介绍什么的 到处都有可以去搜一下)
咱们先建一个NdkJniDemo的工程

Android Studio ndk-Jni开发详细

新建工程.png

新建JniUtils类实现native方法

public class JniUtils {    public static native String getStringFormC();
}

Android Studio ndk-Jni开发详细

build.png

然后clean project 再rebuild project 生成class文件,
这时候打开如下图的文件夹看是否生成了classes文件夹,没有生成请重新来过。

Android Studio ndk-Jni开发详细

文件夹.png

再打开Terminal输入指令
cd app/build/intermediates/classes/debug
然后再输入指令
javah -jni com.wobiancao.ndkjnidemo.ndk.JniUtils
注意 这里javah -jni后面跟的是JniUtils类的全路径,如果javah报不存在之类的,是你的java环境没有配置好。

Android Studio ndk-Jni开发详细

Paste_Image.png

这时候打开classes/debug下面的文件发现多了一个文件
com_wobiancao_ndkjnidemo_ndk_JniUtils.h
然后在src/main下新建文件夹jni,把生成的.h文件复制或者剪切到jni文件夹下面去,新建一个c类随便取一个名字,添加代码如下

//// Created by XY on 16/1/4.//#include "com_wobiancao_ndkjnidemo_ndk_JniUtils.h"/* 
* Class:     Java_com_wobiancao_ndkjnidemo_ndk_JniUtils 
* Method:    getStringFormC 
* Signature: ()Ljava/lang/String; 
*/JNIEXPORT jstring JNICALL Java_com_wobiancao_ndkjnidemo_ndk_JniUtils_getStringFormC
        (JNIEnv *env, jobject obj){ 
   return (*env)->NewStringUTF(env,"这里是来自c的string");

这里发现头文件#include <jni.h>报红色,是因为咱们还没有配置ndk环境,打开file->project structure
选择你所下载的ndk环境路径,如果没有ndk这里有个地址大家可以去下载 一个安卓工具集合的网站:http://androiddevtools.cn/

Android Studio ndk-Jni开发详细

Paste_Image.png

设置好了之后,发现头文件还是红色的,然后再build一下工程,就会有提示

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就ok啦
然后在app文件下得build.gradle ->defaultConfig括号内添加如下代码

ndk {    
   moduleName "NdkJniDemo"          //生成的so名字 
   abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库,目前可有可无。}

到了这一步重新build项目,发现已经没有变红了。接下来就是运用了,在JniUtils类里面添加如下代码

static {    
   System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致}

然后简单调用就行了,MainActivity代码如下

public class MainActivity extends AppCompatActivity { 
   TextView textView;    
@Override    protected void onCreate(Bundle savedInstanceState) { 
       super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.ndk_text);
        textView.setText(JniUtils.getStringFormC());
    }
}

运行结果如图

Android Studio ndk-Jni开发详细

运行图.png

咱们打开app->intermediates-ndk-debug发现生成了三个文件夹,并且对应了之前我们在build.gradle配置的abiFilters
大功告成。
新建libs文件夹把这三个文件夹放进去

Android Studio ndk-Jni开发详细

Paste_Image.png

然后删除咱们的jni文件试试,是否工程还能运用?
ok 教程完毕
最后出一个利用jni的Aes加密demo运行结果如图所示

Android Studio ndk-Jni开发详细

Aes加密.png

项目地址:https://github.com/a12a15a05/NdkJniDemo
谢谢star欢迎点赞=。=转载请注明来源

来自: http://www.jianshu.com/p/d8cde65cb4f7

Android Studio进行NDK开发笔记

http://blog.csdn.net/enlangs/article/details/51881718

方案一

  • AS自带的有NDK插件,但是会出现Deprecated错误。解决方法:按提示操作即可。
  • AS的NDK插件不需要编写Application.mk和Android.mk,所以自己编写的无效!!,关键是那插件功能太弱了(很多Android.mk的属性不能修改)。如果想用自己的mk文件,需要在app/build.gradle中打掉NDK的所有配置。

    android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultConfig {
    applicationId "ckm.xxx.testndk"
    minSdkVersion 19
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
    // 如果要使用自己的Application.mk和Android.mk需要修改下面2处。
    // 修改1,直接打掉下面配置
    // ndk{
    // moduleName "test"
    // abiFilters "armeabi","armeabi-v7a"
    // }
    }
    buildTypes {
    release {
    minifyEnabled false
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    }
    // sourceSets { main { jni.srcDirs = ['src/main/jni'] } }
    // 修改2,需要把jni.srcDirs设置为空。
    // sourceSets {
    // main {
    // jni.srcDirs = []
    // }
    // }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 自动生成头文件,在extend tool中增加配置: 
    Android Studio ndk-Jni开发详细
    参数内容:

Program:C:\Program Files\Java\jdk1.8.0_25\bin\javah.exe
Parameters:-v -jni -d $ModuleFileDir$\src\main\jni $FileClass$
Working directory:$SourcepathEntry$
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

设置结果 
Android Studio ndk-Jni开发详细
- 设置ndk-build的extend tool

Program:C:\ndk\ndk-build.cmd
Parameters:NDK_PROJECT_PATH=$ModuleFileDir$/build/intermediates/ndk NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs NDK_APPLICATION_MK=$ModuleFileDir$/src/main/jni/Application.mk APP_BUILD_SCRIPT=$ModuleFileDir$/src/main/jni/Android.mk V=1
Working directory:$SourcepathEntry$
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

最终结果:Android Studio ndk-Jni开发详细

疑惑:

  • 我不相信AS不支持mk文件(只能当做文本文件识别),肯定有地方设置,还为找到设置地方。

注意:

如果按照上面的方式使用自定义Android.mk那么AS将无法识别到native函数。

方案二

来源:http://*.com/questions/21096819/jni-and-gradle-in-android-studio

此方案主要是直接修改build.gradle

apply plugin: 'com.android.application'

android {
compileSdkVersion 14
buildToolsVersion "20.0.0" defaultConfig {
applicationId "com.example.application"
minSdkVersion 14
targetSdkVersion 14 ndk {
moduleName "YourModuleName"
}
} sourceSets.main {
jni.srcDirs = [] // This prevents the auto generation of Android.mk
jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project.
} task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'-j', Runtime.runtime.availableProcessors(),
'all',
'NDK_DEBUG=1'
} task cleanNative(type: Exec, description: 'Clean JNI object files') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'clean'
} clean.dependsOn 'cleanNative' tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
} dependencies {
compile 'com.android.support:support-v4:20.0.0'
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

参考:图片和extend tool设置都来自这位博主,非常感谢。

参考(请同事写了段代码处理下):

#!/bin/sh

for arg in "$@"
do
if [[ $arg == NDK_PROJECT_PATH=* ]];then
param1=`echo $arg | awk -F = '{printf $1}'`
elif [[ $arg == APP_BUILD_SCRIPT=* ]];then
param2=`echo $arg | awk -F = '{printf $2}'`
else
param="$param $arg"
fi
done #echo $param2
param2=`echo $param2 | sed 's#build/intermediates/ndk/debug/Android.mk#src/main#g'`
#echo $param2
#echo "" if [[ -n "$param1" ]] && [[ -n "$param2" ]]
then
param1="$param1=$param2"
param="$param1 $param"
fi
DIR="$(cd "$(dirname "$0")" && pwd)"
$DIR/build/ndk-build $param
上一篇:转!!关于java类初始化顺序


下一篇:Linux查看文件编码格式及文件编码转换