Android minSdkVersion大于等于23时,v8a应用找不到so文件

238 阅读2分钟

出现的现象

在Android64位的手机上,使用arm64-v8a打包的apk,打开人脸识别瞬间闪退,armabi-v7a没事,很疑惑....

崩溃日志:

java.lang.UnsatisfiedLinkError: No implementation found for void com.sensetime.senseid.sdk.liveness.interactive.d.start()
	at com.sensetime.senseid.sdk.liveness.interactive.d.start(Native Method)
	at com.sensetime.senseid.sdk.liveness.interactive.InteractiveLivenessApi.init(Unknown Source:13)
	at saas.sensetime.liveness.motion.MotionLivenessActivity.onCreate(MotionLivenessActivity.java:340)
	at android.app.Activity.performCreate(Activity.java:8592)
	at android.app.Activity.performCreate(Activity.java:8565)
	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1344)
	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4756)
	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:5006)
	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:123)
	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:3082)
	at android.os.Handler.dispatchMessage(Handler.java:117)
	at android.os.Looper.loopOnce(Looper.java:205)
	at android.os.Looper.loop(Looper.java:293)
	at android.app.ActivityThread.loopProcess(ActivityThread.java:9986)
	at android.app.ActivityThread.main(ActivityThread.java:9975)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1240)

或者

Caused by: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v7/app/AppCompatActivity;
  	at android.view.View.performClick(View.java:7729) 
  	at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1202) 
  	at android.view.View.performClickInternal(View.java:7698) 
  	at android.view.View.access$3700(View.java:886) 
  	at android.view.View$PerformClick.run(View.java:30220) 
  	at android.os.Handler.handleCallback(Handler.java:966) 
  	at android.os.Handler.dispatchMessage(Handler.java:110) 
  	at android.os.Looper.loopOnce(Looper.java:205) 
  	at android.os.Looper.loop(Looper.java:293) 
  	at android.app.ActivityThread.loopProcess(ActivityThread.java:9986) 
  	at android.app.ActivityThread.main(ActivityThread.java:9975) 
  	at java.lang.reflect.Method.invoke(Native Method) 
  	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586) 
  	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1240) 
  Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v7.app.AppCompatActivity" on path: DexPathList[[dex file
  	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:218)
  	at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
  	at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
  com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:586) 

或者

at android.app.NativeActivity.onCreate(NativeActivity.java:170)
at com.hikvision.frame.view.MvpNativeActivity.onCreate(MvpNativeActivity.kt:25)
at com.hikvision.frame.act.BaseMvpNativeActivity.onCreate(BaseMvpNativeActivity.kt:24)
at com.hikvision.cast.reverse.view.act.ReverseCastActivity.onCreate(ReverseCastActivity.kt:69)
at android.app.Instrumentation.call

ActivityOnCreate(Instrumentation.java:1108)

崩溃直接原因:so没找到

现象分析 libcast.so在启动时就加载且成功了,那说明正常的System.loadLibrary是没问题的 具体是NativeActivity.onCreate()出异常,那肯定是NativeActivity里的实现有问题。 最可疑的地方在:NativeActivity.loadNativeCode(path) 题外话:为什么需要使用NativeActivity? NativeActivity是用C/C++开发Android的方案。在实现反向传屏时,可以直接在C++层采集触控事件,实现反向控制,减少不必要的反射调用(频率还挺高的),降低CPU和延时。

回归正题,继续分析:
看一下loadNativeCode的参数:

mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(), getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()), getAbsolutePath(getExternalFilesDir(null)), Build.VERSION.SDK_INT, getAssets(), nativeSavedState);

先看第一个参数path:

File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
                System.mapLibraryName(libname));
if (libraryFile.exists()) {
    path = libraryFile.getPath();
}

如果extractNativeLibs为false时,应用的so文件不解压而且页面对齐;如果设置为true时,系统安装服务会把so文件解压到系统目录。extractNativeLibs默认值是true,但是在使用Android Gradle plugin 3.6.0 及以上,没有配置extractNativeLibs时,会把此属性重置为false。

当然还一个隐藏条件,minSdkVersion为23以上。

题外话 android:extractNativeLibs=false:安装时不需要解压,安装速度比较快 android:extractNativeLibs=true:安装变慢,但so会进行压缩,apk大小减小

另外解压后,如果在代码里使用nativeLibraryDir来加载也没问题,像NativeActivity出现的这个问题,本质上其实就是Google的代码写挫了嘛。

举一反三 所以代码里如果有使用到 ActivityInfo.ApplicationInfo.nativeLibraryDir的需要注意版本兼容问题。

原文借鉴 : blog.csdn.net/gab25920hoi…