Android Studio最新CMake使用教程(二): 生成共享库.so文件并在其他项目中引用

在实际的Android开发中,我们经常要用到外部的动态链接库.so文件,有时我们是使用别人编译好的.so 文件,有时需要我们自己用NDK编译出.so文件,并且在另外的工程里使用。所以本文旨在编写自己的Jni并且编译生成特定的共享库.so文件,然后在另外的工程里使用该共享链接库。
首先我们先创建一个Naive C++工程,具体创建方法见我上一篇博客。创建完成的目录结构大致如下:

image

这里为了在调用.so文件时方便区分开来,我的工程名、包名以及共享库名和库源文件名都做了修改。所以对应的CMakeLists也做了修改:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        testso-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        testso-lib.cpp)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        testso-lib

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

在上篇博文里,我们知道初始创建的Native C++工程是在MainActivity调用Jni方法的,这里我们新建了一个接口类TestSoHelper,并通过这个类调用Jni方法。TestSoHelper的代码如下:

package com.test.mytestsoproject;

public class TestSoHelper {
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("testso-lib");
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public static native int intFromJNI(int a, int b);
}

对应的Jni方法是:

extern "C"
JNIEXPORT jint JNICALL
Java_com_test_mytestsoproject_TestSoHelper_intFromJNI(JNIEnv *env, jclass instance, jint a,
                                                     jint b) {

    // TODO
    int returnValue = a + b;

    return returnValue;
}

这个Jni的方法十分简单,方法传入两个整数,然后返回这两个数的和。关于Jni的编写,学过C语言的同学应该一看就会了,基本是跟C/C++编写一模一样,在此不再赘述。

下面就是对应的native方法的调用了,我这里在MainActivity里简单调用了一下,由于我们是为了编译成.so文件,给其他工程用的,所以在此不写native方法的调用也是可以的。下面是我的调用:

public class MainActivity extends AppCompatActivity {

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

    // Example of a call to a native method
    TextView tv = findViewById(R.id.sample_text);
    tv.setText(TestSoHelper.intFromJNI(1,2) + "");
}

}

基本是默认的工程,只是把要显示的文本改成了我Jni方法返回的数据。打包运行的结果就是在手机上输出数字1+2的和3。

然后我们把编写好的Jni封装成共享库.so。只需要点击Build [图片上传失败...(image-883908-1583744056196)]

Make Project即可生成.so文件。生成的.so文件可以在下面的路径下找到:app\build\intermediates\cmake\debug\obj。可以看到工程生成了对应不同android CPU架构的.so文件:

image

​这样我们就可以在别的工程里使用该.so 文件了。
这里我是直接用上篇博客创建的工程(MyTestProject)来引用这个共享库.so文件的,当然,理论上这个共享库可以被任意android工程引用。首先,我们要把刚才生成的共享库.so文件拷贝到我们要使用它的工程的libs文件夹下,最好是把不同CPU架构的.so文件都拷贝进去,这样我们的应用就能支持各种android系统:

image

然后,在build.gradle里添加以下代码:

image
sourceSets.main {
    jniLibs.srcDirs = ['libs']
    jni.srcDirs = []
}


这是告诉工程要引用的共享库所在的位置。接下来把刚才生成.so文件的工程里的Jni接口类TestSoHelper拷贝到我们当前的工程里,注意,路径也必须与原工程相同!另外,该类里的native方法可能会显示为红色,无法解析,这个不用去管,程序可以正常编译运行。

image

​到这里我们就可以直接在当前工程(MyTestProject)里调用共享库里的方法了,简单的调用如下:

image

​打包执行下,结果果然与之前一样!

以上方法是我个人使用Android Jni 的经验,应该是比网上其他引用自编写共享库的方法简单很多,希望能帮助大家。如有错误和不足,希望大家指正!

​您的赞赏是我坚持分享的最大动力 :)

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

推荐阅读更多精彩内容