Android So库增加和生成

一:前言
日常开发咱们常常会应用到第三库,波及到底层的语音,视频等都须要增加so库。
而so库的体积一般来说十分的大,不搞清楚随便增加会导致apk体积暴增。
下面问题:
Android提供abifilters为咱们提供了解决方案abifilters为咱们提供了抉择适配指定CPU架构的能力,只须要在app下的build.gradle增加如下配置:

android{ defaultConfig{ ndk {            //抉择要增加的对应cpu类型的.so库。            abiFilters 'arm64-v8a','armeabi', 'armeabi-v7a', 'x86_64','x86'        }        }        }

为何大厂APP如微信、支付宝等只适配了armeabi-v7a/armeabi?
https://mp.weixin.qq.com/s/jn...
Android中的so文件是动态链接库,是二进制文件,即ELF文件。多用于NDK开发中
二:什么是ABI
ABI是英文Application Binary Interface的缩写,即利用二进制接口。
不同Android设施,应用的CPU架构可能不同,因而反对不同的指令集。
CPU 与指令集的每种组合都有其本人的利用二进制界面(或 ABI),ABI十分准确地定义了应用程序的机器代码应如何在运行时与零碎交互。
您必须为要与您的应用程序一起应用的每种CPU架构指定一个ABI(Application Binary Interface)
Android 目前反对7种ABIs:arm64-v8a,armeabi, armeabi-v7a,X86, X86–64,mips, mips64
三:CPU架构


总结:
(1)只适配arm64-v8a 能够运行在arm64-v8a上
长处: 性能最佳
毛病:只能运行在arm64-v8上,要放弃局部老旧设施用户
(2)只适配armeabi-v7a能够运行在armeabi-v7a和arm64-v8a
只是又筛掉了一部分老旧设施,在性能和兼容二者中比拟均衡
(3)只适配armeabi的APP能够跑在armeabi,x86,x86_64,armewabi-v7a,arm64-v8上
长处:基本上适配了全副CPU架构(除了淘汰的mips和mips_64)
毛病:性能低,相当于在绝大多数手机上都是须要辅助ABI或动静转码来兼容

将来只须要适配一款cpu架构arm64-v8a,这些缓缓曾经淘汰了,支流是cpu架构arm64-v8a
四:ADB查看手机的CPU架构
F:\soudaoProject\MyGitignore>adb shell
onc:/ $ cat /proc/cpuinfo

Processor       : AArch64 Processor rev 4 (aarch64)//这里能够看出手机是CPU架构是ARM v8 64位processor       : 0BogoMIPS        : 38.40Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32CPU implementer : 0x51CPU architecture: 8CPU variant     : 0xaCPU part        : 0x801CPU revision    : 4processor       : 1BogoMIPS        : 38.40Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32CPU implementer : 0x51CPU architecture: 8CPU variant     : 0xaCPU part        : 0x801CPU revision    : 4processor       : 2BogoMIPS        : 38.40Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32CPU implementer : 0x51CPU architecture: 8CPU variant     : 0xaCPU part        : 0x801CPU revision    : 4processor       : 3BogoMIPS        : 38.40Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32CPU implementer : 0x51CPU architecture: 8CPU variant     : 0xaCPU part        : 0x801CPU revision    : 4processor       : 4BogoMIPS        : 38.40Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32CPU implementer : 0x51CPU architecture: 8CPU variant     : 0xaCPU part        : 0x800CPU revision    : 2

五:Android Studio增加So库
办法一:在src/main中新建jniLibs文件夹,把.so复制进去
我这是ijkplayer的so库

办法二:是在app/中新建libs文件夹,把.so复制进去

这须要在app下build.gradle中增加五行脚本即可(注:以下脚本意思是会把libs文件夹当成jniLibs文件夹,能够间接用so库了)

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

六.Android So库生成
JNI是Java Native Interface的缩写,它的次要作用是提供了若干API来实现Java和其余语言的通信(次要是C和C++)。
NDK是一系列工具的汇合,它能够帮忙开发者疾速开发C(或者C++)的动静库(也称So库),并So库和Java利用一起打包。
JNI的应用就是须要将C(或者C++)代码编译成动静库供Java办法调用
生成SO库(形式一)
第一步:下载NDK,配置NDK,下载CMake,这个是写C语言的
File-->Settings

![上传中...]()

下载完NDK后,去local.properties文件中查看是否定义了ndk的存储门路,

而后到gradle.properties文件中增加android.useDeprecateNdk=true,示意咱们的利用须要应用NDK

第二步:NDK开发建设一个C++我的项目

早android构造下

查看CMakeLists.txt并批改

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.             demo//默认是native-lib             # Sets the library as a shared library.             SHARED             # Provides a relative path to your source file(s).             demo.cpp //默认是native-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.                       demo//默认是native-lib                       # Links the target library to the log library                       # included in the NDK.                       ${log-lib} )

在这里你能够发现app下的build.gradle曾经编译生成了

android {    compileSdkVersion 28    buildToolsVersion "28.0.3"    defaultConfig {        applicationId "com.randao.myproject"        minSdkVersion 15        targetSdkVersion 28        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        //这里是创立C++我的项目默认生成的        externalNativeBuild {            cmake {                cppFlags ""            }        }        //这个是我本人增加去匹配cPU架构        ndk{            abiFilters 'arm64-v8a'        }    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'        }    }    //默认生成去构建CMakeLists.txt    externalNativeBuild {        cmake {            path "src/main/cpp/CMakeLists.txt"        }    }}

第三步:编写Java调用类

/** JNI测试类*/public class TestJNI {    static {        System.loadLibrary("demo");    }    public native void set();//C语言中实现,输入这就是一个JNI的调用}

Java调用类的阐明:
1、动态代码块表明了该Java类须要加载哪一个So库,例子中的demo是So库的名称。(留神:实际上NDK生成的So库的名称为libdemo.so,然而So库的名称就是demo)
2、native关键字申明了set()办法,这个办法须要在C(或者C++)中实现。
第四步:生成.h头文件,编写C(或者C++)代码
关上demo.cpp文件编写

#include <jni.h>#include <string>extern "C"JNIEXPORT jstring JNICALLJava_com_randao_myproject_TestJNI_set(JNIEnv *env, jobject thiz) {    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}//Java_com_randao_myproject_TestJNI_set(JNIEnv *env, jobject thiz)//Java+我的项目名+类名+办法名后果是输入Hello from C++


第五步:调用在Activity

String aa=new TestJNI().set();//调用办法输入        Toast.makeText(this,aa,Toast.LENGTH_SHORT).show();

第六步:查看生成的so库

1.什么是CMake?
定义:容许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,而后再依据指标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。
2.如果我想JNI中减少一个办法

/** JNI测试类*/public class TestJNI {    static {        System.loadLibrary("demo");    }    public native void set();//C语言中实现,输入这就是一个JNI的调用        public native void add(int x,int y);//demo.cpp实现add

对应的demo.cpp下办法

#include <jni.h>#include <string>extern "C"JNIEXPORT jstring JNICALLJava_com_randao_myproject_TestJNI_set(JNIEnv *env, jobject thiz) {    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}extern "C"JNIEXPORT jstring JNICALLJava_com_randao_myproject_TestJNI_add(JNIEnv *env, jobject thiz,jint x,jint y){//具体操作add}

END:将来可期