您的位置:首页 > 移动开发 > Android开发

【JNI】拒绝各种坑!Android Studio 下创建JNI项目

2016-05-17 17:30 661 查看

一时间来,又是几个月的时间没有写文章了,你干啥去了=。=,忙着各种事情,让我这几个月感触最深的,就是JNI了,JNI真是个有趣的东西,废话少说,咱们一起来看看,怎么用JNI来写一些有用的东西,因为网上的教程很多,很多。。真的很多,而且有些已经很老了或是不能那么弄,坑还是很多的,所以写了这篇文章,希望初学者能少走一点坑,需要注意的几点如下:

注意点:

1.本人也是JNI新手,所以不足之处请多交流指教;

2.本文采用的是Android Studio +NDK来实现JNI,如果使用的是Eclipse环境的话,这里推荐您去这个网址去学习Eclipse的JNI实现方法,保票肯定能用,地址:/article/4854918.html

什么是NDK与JNI技术?

NDK:Native Development Kit

The NDK is a toolset that allows you to implement parts of your app using native-code languages such as C and C++.(谷歌官方文档)

大致意思:NDK是一个工具,可以让你实现你的应用程序使用本地代码的语言,如C和C++的部分。

JNI:Java Native Interface

它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。

准备工作

Android Studio配置NDK

【转】http://www.android100.org/html/201509/18/182761.html

开始实现

1.用android studio创建新的项目

2.修改生成的文件

a.修改AppCompatActivity为Activity



2..主题样式为@android:style/Theme.Black.NoTitleBar并删除颜色属性,暂时还未尝试与Material
Design结合,所以改下对JNI编译有影响的配置,后面我会尝试下是否支持



3.删除src下的test测试项目

3.修改Gradle

a.修改根目录下的build.gradle文件并同步



classpath 'com.android.tools.build:gradle:2.1.0'

改为

classpath 'com.android.tools.build:gradle-experimental:0.7.0'


这个gradle是实验性的gradle和平时用的不太一样,修改后同步下,发现报错了,别担心,还没有修改完,刚刚修改完一个,报错图片如下:



b.修改app的gradle配置

因为配置很多我这里贴出代码:

原来的:

apply plugin: 'com.android.application'

android {
compileSdkVersion 23
buildToolsVersion "23.0.3"

defaultConfig {
applicationId "com.windystory.hellojni"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
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.3.0'
}


修改后的配置:

/**
* 这里不是 apply plugin: 'com.android.application' 了,很多原来的配置大部分都有 = 号了
*/
apply plugin: 'com.android.model.application'
/**
* 这里不再是android开始了而是model
*/
model {
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"

defaultConfig {
applicationId "com.windystory.hellojni"
minSdkVersion.apiLevel = 14  //最低版本的SDK设置
targetSdkVersion.apiLevel = 23  //编译SDK设置
versionCode =  1   //注意加 = 号
versionName  = "1.0"
}
/*
* 设置NDK编译moduleName
*/
ndk {
moduleName = 'hello-jni'
toolchain = 'clang'
CFlags.addAll(['-Wall'])
}
buildTypes {
release {
minifyEnabled false
proguardFiles.add(file('proguard-rules.txt'))//这里不是原来的那个了
}
}

productFlavors {
create("arm") {
ndk.abiFilters.add("armeabi")
}
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
create("arm8") {
ndk.abiFilters.add("arm64-v8a")
}
create("x86") {
ndk.abiFilters.add("x86")
}
create("x86-64") {
ndk.abiFilters.add("x86_64")
}
create("mips") {
ndk.abiFilters.add("mips")
}
create("mips-64") {
ndk.abiFilters.add("mips64")
}
// 包括所有的CPU架构
create("all")
}
}
}


同步下,发现ok了

3.设置根目录下的gradle.properties支持NDK

android.useDeprecatedNdk=true






代码实现

1.创建JNI目录,右击src/main,创建JNI目录,并删除,app gradle的

android { sourceSets { main { jni.srcDirs = ['src/main/jni/','src/main/jni/'] } } }


删除后同步

2.创建一个名字叫JNI的类,并写一个native方法,native关键字修饰本地方法

public class JNI {
public native String Hello();
}



在MainActivity中实例化该类

a.编译类 点击Build --- Make Project,完成后会在build-intermediates-classes-all-debug项目目录下生成相应的class文件,

使用Android studio的Terminal功能切到debug目录下(cd命令),然后使用 javah -jni 项目目录+类 来生成头文件,如图所示



使用javah -jni 命令生成头文件,注意如果出现未找到错误,请审查目录,注意不要进入到debug目录中,到debug目录即可,如果未出现错误,恭喜,成功了



b.将生成的头文件放入jni目录下,并实现该头文件

实现的.c中方法与头文件中一样,实现可以直接粘贴复制改下拓展名即可,注意实现类中需要将参数实现,并且引入头文件,在windows平台下NDK有一个bug,所以需要在jni目录下新建一个util.c的空文件



如出现如下编译问题,先关闭android studio手动删除build目录下的所有文件,打开后再次编译即可



需要注意的还有引用头文件时候,如果不是系统的头文件,一律使用" "来引用而不是<>,否则会报错

#include "com_windystory_hellojni_JNI.h"
/*
* Class:     com_windystory_hellojni_JNI
* Method:    Hello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_windystory_hellojni_JNI_Hello
(JNIEnv *evn, jobject obj)
{
return (*evn)->NewStringUTF(evn, "Hello from My-JNI !");

}


c.使用本地方法

在MainActivity中调用JNI方法,需要将编译后的库引入,写在static静态块中,hello-jni这个名字要与gradle ndk配置中一样如下图所示:



gradle ndk:

<span style="white-space:pre">	</span>/*
* 设置NDK编译moduleName
*/
ndk {
moduleName = 'hello-jni'
toolchain = 'clang'
CFlags.addAll(['-Wall'])
}


好了,可以运行了,运行效果如下所示:



Demo下载地址:

http://download.csdn.net/detail/u011539882/9523065
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: