零基础带你吃掉JNI全家桶(二)

前言

上篇通过一个简单的例子大概阐述了jni开发的基本流程,最后也编译出了自己的so文件,本篇主要介绍怎么引入第三方的so文件并进行调用

一、如何调用第三方so中的方法?

通过上篇我们知道,从Java层要调用native层的方法,要么是静态注册,要么是动态注册,但是不管是哪一种,两个方法之间必须需要建立一定的通道关系,静态注册需要对应好方法名,动态注册需要对两个方法进行绑定,都是需要知道包名的,但是问题来了,那么如何在我的项目中调用第三方so中的方法呢?自己的项目包名都是不一样的,实际上有两种方式:

  • 如果第三方提供了so文件,同时也提供了SDK jar包文件,那实际上自己本身就不需要做太多的操作,直接调用API中的方法,sdk内部再去跟native方法进行映射,我们只要将so库文件导入进来放在指定位置,一般是在jniLibs目录下,这样sdk里面就可以跟native层通信了。
  • 上面那种方式一般适用于集成第三方服务,比如高德、友盟等等,局限性较大,只能在sdk限制下进行操作,假如是需要对其进行一定的扩展性或者没有人给你提供SDK包(比如自己公司的一些内部库经常会有这种情况),那么这个时候就需要自己通过需要把so导进来之后,编写本地方法来进行映射通信

二、关联第三方so库

上面第一种方法就不说了,一般直接调用sdk即可,我们直接看第二种,大概分为以下几个步骤:

  • 导入第三方so文件,放在指定目录下,一般就放在jniLibs目录下面
  • 编写CMakeLists.txt文件,引入so库并进行关联
  • 编写native方法,包名一定要和so中对应的包名一样

我们就使用上篇例子生成出来的so,我们来调用下,从build中把so拷出来,位置如下,这里我们用arm架构就行了,一个是64位的,一个是32位的


image.png

然后放到我们新建的一个项目中,这里把so名字重命名下,防止混淆


image.png

然后我们需要在build.gradle中指定so文件目录

sourceSets {
        main {
            jni.srcDirs = []
            jniLibs.srcDirs = ['src\\main\\jniLibs']
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

然后,因为本身自己是不需要生成so库的,所以CMakeLists.txt中的native-lib可以删掉,我们加入要引入的so库,并与之关联


#定义cmake支持的最小版本号
cmake_minimum_required(VERSION 3.4.1)
#加入lib2库 ,定义为导入形式
add_library(lib2 SHARED IMPORTED)

#关联lib2库为我们要导入进来的libdata.so文件,ANDROID_ABI会根据自身cpu架构选择so文件
set_target_properties( lib2
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libdata.so)
# 从系统里查找依赖库,可添加多个
find_library( # 例如查找系统中的log库liblog.so
              log-lib

              # liblog.so库指定的名称即为log,如同上面指定生成的libnative-lib.so库名称为native-lib一样
              log )

这样CMakeLists文件在执行的时候就会把libdata.so文件加载进来。

最后一步,编写本地方法,新建一个类

package com.example.taolin.jni_project;

public class NativeHelper {
    static {
        System.loadLibrary("data");
    }
    public static native String stringFromJNI();
    public static  native int add(int a,int b);
}

主要包名,要和so中的一直的,也是上篇文章中的动态注册代码,这里粘贴部分

//动态注册
jint registerMethod(JNIEnv *env) {
    jclass clz = env->FindClass("com/example/taolin/jni_project/NativeHelper");
    if (clz == NULL) {
        LOGD("con't find class: com/example/taolin/jni_project/NativeHelper");
    }
    JNINativeMethod jniNativeMethod[] = {{"stringFromJNI",    "()Ljava/lang/String;",                       (void *) backStringToJava},
                                         {"add",              "(II)I",                                      (void *) addNum},};
    return env->RegisterNatives(clz, jniNativeMethod,
                                sizeof(jniNativeMethod) / sizeof(jniNativeMethod[0]));
}

这样的话,就在调用的时候,就可以找到对应的类,将Java层方法和Native层方法进行关联起来,进行通信

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.


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

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(NativeHelper.stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */

}

具体图我就不截了,也是能成功显示出字符串的,这样就调用了外部so的方法,大功告成!

这里只是最简单的,从native层返回一个字符串,比较浅显局限,下篇将接着介绍下,Jni的语法,以及java层和native间更为复杂的交互过程,对象怎么传输?,native层怎么操作java层的类?等等。

有新的想法和疑问的老哥可以留言一起讨论哦,溜了溜了~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,089评论 4 62
  • ref: Android Studio开发JNI示例Android NDK 开发(二)JNI 传递参数和返回值An...
    richy_阅读 1,583评论 0 8
  • 本人为初学者,文章写得不好,如有错误,请大力怼我 或者看这里 如何使用jni进行开发 本文主要针对Android环...
    AlbertHumbert阅读 4,657评论 2 12
  • 1, 1) 快速反应:如饿了想吃,危险想跑 2)慢速反应:如买房子 3)大多数情况下都是非理性决定,作为动物本性很...
    王阿熊阅读 666评论 0 0
  • 1.男女通婚 黄帝和嫘祖是华夏民族第一对夫妻,预示着传统的“欢乐谷野合”与“走访婚”的伴侣关系的全新升级,也宣告男...
    独孤无尘阅读 554评论 0 0