JNI for Android, Android Studio NDK 入门 实例 demo

Jni是java用来和其他语言交互的一套规范,有了它java可以调用动态链接库中的方法,或者让其他语言掉用java方法。具体介绍和Demo可以浏览这篇博客

基础

NDK

Native Development Kit(NDK)是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C/C++的动态库,并能自动将so和Java一起打包成apk。

JNI与NDK的关系

NDK可以为我们生成了C/C++的动态链接库,JNI是java和C/C++沟通的接口,两者与Android没有半毛钱关系,只因为安卓是java程序语言开发,然后通过JNI又能与C/C++沟通,所以我们可以使用NDK+JNI来实现“Java+C”的开发方式。

NDK开发优点

  1. 项目需要调用底层的一些C/C++的一些东西(java无法直接访问到操作系统底层(如系统硬件等)),或者已经在C/C++环境下实现了功能代码(大部分现存的开源库都是用C/C++代码编写的。),直接使用即可。NDK开发常用于驱动开发、无线热点共享、数学运算、实时渲染的游戏、音视频处理、文件压缩、人脸识别、图片处理等。
  2. 为了效率更加高效些。将要求高性能的应用逻辑使用C/C++开发,从而提高应用程序的执行效率。但是C/C++代码虽然是高效的,在java与C/C++相互调用时却增大了开销;
  3. 基于安全性的考虑。防止代码被反编译,为了安全起见,使用C/C++语言来编写重要的部分以增大系统的安全性,最后生成so库(用过第三方库的应该都不陌生)便于给人提供方便。(任何有效的代码混淆对于会smail语法反编译你apk是分分钟的事,即使你加壳也不能幸免高手的攻击)
  4. 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

NDK配置

首先友情提醒摒弃Eclipse拥抱AndroidStudio吧。AS给了android程序员极大的支持,大大提高了效率。如果你在Eclipse+ADT下开发过NDK就能体会到要么是配置NDK还要下载Cygwin,配置Cygwin ,然后需要编译生成,相当的蛋疼。要么是直接用Eclipse开发,但是前期配置也是一堆;真心蛋疼。

首先下载NDK,在AS上点击File–>Project Structure,如果你已经下载,直接选择你 ndk 的位置;如果没有下载,在红色框这个位置会有位置提示你下载,点击下载就行。(不用翻墙哦,速度杠杠的)
这里写图片描述

添加 ndk 后你会在 local.properties 这个文件看到(路径取决于你 ndk 的位置):
这里写图片描述

最后在此处加上这句代码:android.useDeprecatedNdk=true
好了,ndk 环境搭建完毕!
这里写图片描述

实例

生成so文件

新建一个android项目,在项目中新建一个类,类中调用动态链接库“Jary”,并声明了一个本地方法“getString”,返回一个字符串。

package com.example.nickolas.jnitest3;

public class JniTest{
    static {
        System.loadLibrary("Jary");
    }
    public native String getString();
}

然后重新编译下你的 Project: Build–>Make Project
重新编译之后就可以在对应的文件夹看到编译后的 JniTest.class
这里写图片描述

下一步来看怎么生成 .h 的文件
在 studio 打开 Terminal 命令行工具,打开步骤是 View–>Tool Windows–>Terminal
默认进入到该项目的app文件夹下。输入如下命令跳转到class中间文件生成路径:

xxxxx\app> cd app/build/intermediates/classes/debug/

然后执行如下javah命令生成h文件。

xxxxx\debug> javah -jni icom.example.nickolas.jnitest3.JniTest

执行完之后你可以在文件夹app\build\intermediates\classes\debug下看见生成的 .h头文件为:

com_example_nickolas_jnitest3_JniTest.h

开始编写C/C++源文件。在 main 目录下新建“jni” 文件夹,把上一步生成的.h文件复制到“jni”文件夹中,并在该文件夹中新建C语言源文件jary.c。
这里写图片描述

C语言源代码如下:

#include "com_example_nickolas_jnitest3_JniTest.h"

JNIEXPORT jstring JNICALL Java_com_example_nickolas_jnitest3_JniTest_getString
        (JNIEnv *env, jobject jobject1){
    return (*env)->NewStringUTF(env, "hello nick");
}

依赖刚才生成的 .h 头文件 ; 方法名与 .h 里面方法名保持一致 ;
最后在 build.gradle defaultConfig 中添加如下代码

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

到这里,jni 调 C 就完成了,现在我们来测试一下,写个 TextView 显示一下调用的 C:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        TextView tvJni = (TextView) findViewById(R.id.tvJni);
        tvJni.setText(new JniTest().getString());
    }

效果如下图 :
这里写图片描述

使用so文件

要使用so文件首先得把so文件导入到项目。
倒入so文件有两种方法,一种直接在main文件夹下新建文件夹jniLibs把so文件放入该文件夹。
第二种方法在我们的Module的根目录中建立libs目录,把so文件放入该文件夹。同时需要在build.gradle 添加如下配置:
这里写图片描述

最后有个大坑敲黑板。调用so库的时候,将调用其中方法的类的包名改成so文件中写的包名。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值