ndk编译生成so

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ndk编译生成so相关的知识,希望对你有一定的参考价值。

参考技术A 本文讲述使用android 的ndk-build来编译生成so库,在命令行中编译。编译后的so库可以调用。
环境问题略过,请自行百度或谷歌安装ndk。

新建文件夹/cn/scnu
并在文件夹中创建java 文件:

该命令会编译java文件并在build目录下生成,然后我们打开build目录

然后我们使用javah命令:

然后会生成一个.h头文件,我们打开这个头文件看看:

可以看到这里面只有一个函数,这个函数返回一个整形,和前面的java头文件对应。
接下来我们另外创建一个Test文件夹,在Test文件夹下创建jni目录,然后将刚才生成的头文件拷贝进来。

然后我们创建JNITest.c文件,文件内容如图:

这个文件的主要内容就是调用头文件并实现头文件中的方法,我们返回了1024。

LOCAL_MODULE 就是我们要生成的so,LOCAL_SRC_FILES就是编译的文件

这里就表示我们要生成的so库的CPU架构。

使用命令行进入到Test目录下,即jni的根目录处,然后打命令:

结果如图,然后我们就可以在libs目录下发现生成的so库了。

Android NDK系列-AS生成jar包导入so库并使用方法

NDK系列(一)-AS使用javah生成so文件
NDK系列(二)-AS使用CmakeLists生成so文件
NDK系列(三)-AS编写C文件没有提示和不识别NULL

AS导入so库呢,这其实很简单。很多的三方都会使用到so文件,和一些jar包。这里呢,还有一种就是我们在编写自己的C/C++文件的时候,需要用到三方so库的一些方法,这个时候需要导入别人的so库,从而调用C/C++的方法。

第一步:生成jar包

生成jar包,在其他应用中调用封装好的Java方法。就用之前的例子生成的代码(AS使用javah ibrary生成的so文件)。
如何生成jar包呢,在jnilibrary里加入一个任务。

task makeJar(type: Copy) 
    //删除存在的
    delete 'build/libs/myjni.jar'
    //设置拷贝的文件  release或者debug都可以,看你有没有release版的文件夹
    from('build/intermediates/bundles/debug/')
    //打进jar包后的文件目录
    into('build/libs/')
    //将classes.jar放入build/libs/目录下
    //include ,exclude参数来设置过滤
    //(我们只关心classes.jar这个文件)
    include('classes.jar')
    //重命名
    rename ('classes.jar', 'myjni.jar')


makeJar.dependsOn(build)

整个gradle文件我贴出来

apply plugin: 'com.android.library'

android 
    compileSdkVersion 25
    buildToolsVersion "25.0.3"

    defaultConfig 
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        ndk
            moduleName "nativeUtil"
            ldLibs "log","z","m"
            abiFilters "armeabi","armeabi-v7a","x86"
        
    
    buildTypes 
        release 
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        
    
    lintOptions 
        abortOnError false
    



dependencies 
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', 
        exclude group: 'com.android.support', module: 'support-annotations'
    )
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'


task makeJar(type: Copy) 
    //删除存在的
    delete 'build/libs/myjni.jar'
    //设置拷贝的文件
    from('build/intermediates/bundles/debug/')
    //打进jar包后的文件目录
    into('build/libs/')
    //将classes.jar放入build/libs/目录下
    //include ,exclude参数来设置过滤
    //(我们只关心classes.jar这个文件)
    include('classes.jar')
    //重命名
    rename ('classes.jar', 'myjni.jar')


makeJar.dependsOn(build)

然后在Terminal里输入,gradlew makeJar 运行这个任务。

gradlew makeJar

成功之后就能在该library下的libs里发现一个myjni.jar的jar包。

第二步:导入jar包和so文件

这个时候就可以把jar包和so库导入需要使用的项目中就ok了。
拿这个项目的jar和so举例。新建一个AS项目。将jar包放在醒目的libs下。

然后就是依赖jar包。

依赖完成之后,接下来就导入so文件。

把这些so文件导入新项目中。

我使用的是项目默认的文件夹,so文件放在jniLibs,jniLibs自己创建的,也可以放在libs里面,自己在gradle手动修改src.jnilibs的源文件路径。

第三步:使用jar包的方法

public class MainActivity extends AppCompatActivity 

    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.text1);

        textView.setText(JniLib.getStringFromC());
    

好啦,这个结合之前的文章,也算把so文件生成、导入、使用都走了一遍,在使用的这个环节,我想很多道友都是老手了,就不多说了。

感谢动脑学院NDK专题资源
http://ke.qq.com/cgi-bin/agency?aid=26937

以上是关于ndk编译生成so的主要内容,如果未能解决你的问题,请参考以下文章

windows系统OLLVM + NDK 混淆编译环境搭建

如何用Android NDK编译FFmpeg

android ndk 编译的时候指令集的选取

如何把ndk编译出来的可执行文件伪装成so打包到apk中

NDK编译FFMpeg[Linux]

生成ARM汇编