首先大家先了解下:

ABI和CPU

不同的 Android 手机使用不同的 CPU,而不同的 CPU 支持不同的指令集。CPU 与指令集的每种组合都有专属的应用二进制接口,即 ABI。
每个 ABI 支持一个或多个指令集,每个 ABI 支持的指令集如下图。

ABI

支持的指令集

备注

armeabi

ARMV5TE 和更高版本Thumb-1

在 r16 中已弃用。在 r17 中已移除。无硬浮点数。

armeabi-v7a

armeabiThumb-2VFPv3-D16其他(可选)

与 ARMv5、ARMv6 设备不兼容

arm64-v8a

AArch64

兼容armeabi-v7a

x86

x86 (IA-32)MMXSSE/2/3SSSE3

不支持 MOVBE 或 SSE4。

x86_64

x86-64MMXSSE/2/3SSSE3SSE4.1、4.2POPCNT

64 位设备也支持其 32 位变体。以 arm64-v8a 设备为例,该设备也可以运行 armeabi 和 armeabi-v7a 代码,但相对来说代码运行的效率也会略有降低。但请注意,如果应用以 arm64-v8a 为目标,而非依赖于运行 armeabi-v7a 版应用的设备,应用在 64 位设备上的性能要好得多。

报错原因

正常情况下,找到所需的库时,软件包管理器会将它们复制到应用的 data 目录 (data/data/<package_name>/lib/) 下的 /lib/lib.so。
如果根本没有共享对象文件,应用也会编译并安装,但在运行时会崩溃。

举个荔枝:如果你有两个文件夹armeabi和arm64-v8a。armeabi里面有a.so 和 b.so,arm64-v8a里面只有a.so,那么arm64-v8a的手机在用到b的时候发现有arm64-v8a的文件夹,但是里面没有b.so,就报错了,所以删掉arm64-v8a文件夹,这个时候手机发现没有适配arm64-v8a,就会直接去找armeabi的so库,所以要么你别加arm64-v8a,要么armeabi里面有的so库,arm64-v8a里面也必须有。

解决问题

既然已经知道了问题原因,那么咱们就单刀直入 直捣黄龙。

依旧以 arm64-v8a 设备为例,只留下armeabi-v7a文件夹(留下哪些文件夹应该根据提供的so库决定,如果有其他类型的so文件夹也可以不删除),其余的文件夹删除,并保持这两个文件夹里的文件是一样的。
然后在gradle.properties中添加:
android.useDeprecatedNdk=true
在build.gradle(app)中添加对应的cpu的.so库:

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

需要注意的是:可能有些时候为了打包方便,在打包时生成多个ABI的apk,但于此是大忌!因为通过此方法打包的apk lins下只会有一个对应ABI的文件夹。
举个荔枝,若include‘arm64-v8a’,那么打出的apk中lins里只会有一个名为arm64-v8a的空文件夹 ,因为我们的so文件只存在于’armeabi-v7a’中,那么在程序运行后就会报没有so文件的错误。所以在打包多个ABI类型的apk时,一定要于添加的cpu类型的so对应。

android {
   ...
    defaultConfig {
       .....
    }
    splits {
        abi {
            enable true
            reset()
            //include  'armeabi', 'armeabi-v7a','arm64-v8a','x86','x86_64'
            include 'armeabi-v7a'
            universalApk true
        }
    }

}

完整的配置为:

android {
   ...
    defaultConfig {
       .....
        ndk {
            //选择要添加的对应cpu类型的.so库。
            //abiFilters 'armeabi','arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
            abiFilters 'armeabi-v7a'
            moduleName "app"
        }
    }
    splits {
        abi {
            enable true
            reset()
            //同时打包出多个cpu类型的apk
            //include  'armeabi', 'armeabi-v7a','arm64-v8a','x86','x86_64'
            include 'armeabi-v7a'
            universalApk true
        }
    }

}

总结

使用上述方法虽然可以解决java.lang.UnsatisfiedLinkError的问题,但是在程序的运行效率上会有所降低。若可以选择还是建议编译CPU直接支持的指令集而不是兼容的指令集。

参考:

https://developer.android.google.cn/ndk/guides/abis https://www.zhihu.com/question/36893314/answer/78467097