android studio怎么调用jni

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android studio怎么调用jni相关的知识,希望对你有一定的参考价值。

参考技术A (1)老版本,方法如下:task copyNativeLibs(type: Copy) from(new File(project(':MyProject').buildDir, 'native-libs')) include '**/*.so' into new File(buildDir, 'native-libs') tasks.withType(Compile) compileTask -> compileTask.dependsOn copyNativeLibs clean.dependsOn 'cleanCopyNativeLibs' tasks.withType(com.android.build.gradle.PackageApplicationTask) pkgTask -> pkgTask.jniDir new File(buildDir, 'native-libs')(2)新版本三种方法:(2.1)打包前先生成.Jar文件后自动解包到apk文件task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') destinationDir file("$buildDir/native-libs") baseName 'native-libs' extension 'jar' from fileTree(dir: 'libs', include: '**/*.so') into 'lib/' tasks.withType(Compile) compileTask -> compileTask.dependsOn(nativeLibsToJar)下面一句话就是打包生成目录(build\native-libs)中的.jar文件compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')(2.2)手动生成.Jar文件后自动解包到apk文件这个方式需要自己手动进行.SO文件压缩,具体步骤为:将所有需要使用的.so文件压缩为.zip文件(zip中的文件目录结构为: lib/armeabi/*.so)然后把zip文件后缀改为.Jar然后放到libs生成apk就ok默认就是自动打包所有.Jar文件:dependencies compile fileTree(dir: 'libs', include: '*.jar')(2.3)这也就是现在正在使用的方式(推荐) ,其实无非就是把.SO文件打包到APK的lib文件夹中,假如仔细阅读了Gradle的使用方法,自然就知道其实Gradle官方在新版已经自动实现了打包.SO文件的.很简单级就是在配置的android节点下加入下面的内容就ok:sourceSets main jniLibs.srcDirs = ['libs'] 其他地方无需修改,整个项目的配置文件如下:apply plugin: 'android' android compileSdkVersion 19 buildToolsVersion "19.0.0" defaultConfig minSdkVersion 16 targetSdkVersion 19 versionCode 1 versionName "1.0" buildTypes release runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' sourceSets main jniLibs.srcDirs = ['libs'] dependencies compile fileTree(dir: 'libs', include: ['*.jar'])

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

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

 

注意点:

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

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

 


什么是NDK与JNI技术?

NDKNative 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++的部分。

 

JNIJava 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

 

 

以上是关于android studio怎么调用jni的主要内容,如果未能解决你的问题,请参考以下文章

如何在android studio中用JNI调用静态库

如何用android studio

怎么用android studio设计安卓界面布局

Android Studio下Java Jni技术

android studio里的ndk toolchains问题,请问怎么解决

androidstudio调用别的界面值