JNI开发入门教程,实现输出一段字符串

9 篇文章 0 订阅


  • 为什么使用JNI
        效率上 C/C++是本地语言,比java更高效;
        代码移植,如果之前用C语言开发过模块,可以复用已经存在的c代码;
        java反编译比C语言容易,一般加密算法都是用C语言编写,不容易被反编译;

  • JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。 标准的java类库可能不支持你的程序所需的特性。 JNI·或许你已经有了一个用其他语言写成的库或程序,而你希望在java程序中使用它。你可能需要用底层语言实现一个小型的时间敏感代码,比如汇编,然后在你的java程序中调用这些功能。
  • NDK是Google公司推出的帮助Android开发者通过C/C++本地语言编写应用的开发包,包含了C/C++的头文件、库文件、说明文档和示例代码,我们可以理解为Windows Platform SDK一样,是纯C/C++编写的,但是Android并不支持纯C/C++编写的应用,同时NDK提供的库和函数功能很有限,仅仅处理些算法效率敏感的问题,所以推荐初学者学好Java后再学习JNI。 NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。 NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。



    搭建环境
     首先配置jdk环境 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html下载jdk,并且安装到电脑上。
     
    第一步: JAVA_HOME (没有就新建一个),变量值(jdk路径,我的jdk是1.8): c:\Program Files(x86)\Java\jdk1.8.0_18
    第二步:找到变量名为 Path的,在变量值前面加上 %JAVA_HOME%/bin;用分号隔开,如果 放到后面就是 ;%JAVA_HOME%/bin
    第三步:新建classpath(有的直接打开)输入.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar,千万不能漏掉.;表示当前路径。
    然后 打开AS,选择file->project Structure->SDK Location,如图:


    记得配置jdk时一定要先把上面那个默认勾选的去掉。
    接下来是给AS配置NDK环境
  •     下载NDK包,https://developer.android.com/ndk/downloads/index.html?hl=zh-cn 这个网址需要开发者翻墙才能访问下载,我用的是蓝灯翻到日本去下载。。。win64位的包约莫760M
  •     下载好并且解压放到你要放的文件夹中,打开AS,选择file->project Structure->SDK Location,如图:

        其中,ndk的路径改为你刚刚解压NKD包放置的文件里面的android-ndk-xxx的绝对路径。
      记得配置完之后,要重启AS
  •    重启完AS重新进来,打开Terminal界面,先试着输入javah,看看是否已经完成jdk的配置,如图:

      如果出现了如下的提示,则说明jdk配置正确了,不然就是环境变量没有配置正确
  •      确认jdk环境配置无误后,打开项目的local.properties文件,在里面输入nkd的路径
       
      
     
  •     接着在gradle.properties里面声明开启ndk,声明代码: android.useDeprecatedNdk=true
           
     
  •      然后在module的build.gradle里面配声明生成的so文件
       
      
        
     在android括号里面声明一个ndk配置信息
ndk{
    moduleName  "WangicClock" //生成的so名字
    abiFilters  "armeabi""armeabi-v7a""x86", "x86_64", "arm64-v8a"  //输出指定五种abi体系结构下的so库。目前可有可无。
}
     这个配置信息包括moduleName和abiFilters,moduleName指的是你要声明的so文件的名字,abiFilters可有可无,目前主流的体系就5种。


      到这一步配置阶段基本就告一段落了,接下来要开始写代码了
  •     首先在java文件夹里面创建一个新的文件夹,里面创建一个class文件,声明native方法
     
public class JniClient {

      public native String  getStr() ;

     public native int  AddInt( int a , int b) ;

}
        
  •      然后找到app文件夹下的build->intermediates->classes->debug(release)
  •      接着打开Terminal,把路径定到刚刚的路径上
            
输入:javah -jni 你创建的包名.你创建的类名.例如:
按回车之后就会执行命令,得到一个.h文件,在刚刚的build.intermediates.classes.debug(release)文件夹中
这个.h文件就是我们需要的C++文件了
打开.h文件
         
这里可以看到两个圈起来的方法,就是我们刚刚写的class定义的两个方法名
  • 在java目录下再创建一个jni文件夹,将刚刚的.h文件剪切放入jni文件夹中,并且创建多一个.c文件,名字随意

  • 打开刚刚创建的.c文件,输入
#include  "c_JniClient.h"
/*
 * Class:     io_github_yanbober_ndkapplication_NdkJniUtils
 * Method:    getCLanguageString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_c_JniClient_getStr //.h里面的其中一个方法名
  (JNIEnv *env, jobject obj){
      return (*env) ->NewStringUTF(env, "This just a test for Android Studio NDK JNI developer!");
  }
解释:
首先include "包名_类名.h"
然后 JNIEXPORT jstring JNICALL +.h里面的方法名+(*形参名,jobject obj){
     return (*形参名)->NewStringUTF(形参名,“你要输出的文字”);
}
  • 最后,回到最开始声明的java文件里面,加上一个静态加载代码
static {
     System. loadLibrary( "WangicClock") ;    //defaultConfig.ndk.moduleName
}
静态方法就是loadLibray("你在build.gradle声明的so名字");

  • 在你要获得字符串的地方执行方法即可
  • 你就可以看到来自C的问候
 
有疑问的可以直接留言。。。。

     

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值