我有app包含两个本机库(例如libfirst.so,libsecond.so)。现在是一个加载库标准方法。
System.loadLibrary("first");
System.loadLibrary("second");
现在我需要能够在不重新安装应用程序的情况下更新库(无需更新.apk)。 我可以加载本机库这个方法
System.load("/storage/emulated/0/armeabi/libfirst.so");
System.load("/storage/emulated/0/armeabi/libsecond.so");
我认为这是一种不好的做法。
我试图复制文件夹getApplicationInfo()。nativeLibraryDir中的库,但系统错误:
打开失败:EACCES(权限被拒绝)
在没有更新apk的情况下更新本机库的最佳实践是什么?
答案 0 :(得分:1)
在没有更新apk的情况下更新本机库的最佳做法是什么?
我不相信会有意外情况。
代码签名可以做两件事。首先,它确保发布应用程序的开发人员与更新应用程序的开发人员相同。其次,它在相关应用程序之间创建信任关系(但这不适用于此)。 Nikolay Elenkov在Code signing in Android's security model讨论了这个话题。
如果要更新依赖库,则需要重建APK以证明您有权进行更新。这是上面讨论的代码签名的第一部分。
如果您想更新应用程序的个人副本(而不是发布它),则只需删除现有签名,更新库,使用Debug signing key签名,然后推送到设备。
此外,您可以安全地执行adb install -r <the apk>
。 -r
“替换现有应用程序”,它实际上是重新安装。它保留以前的应用程序数据,如数据库。
更新应用时还需要做一些其他事情,比如增加版本号,以便在Google Play中正确处理。但它们与你的问题无关。
答案 1 :(得分:0)
实际上有一种方法可以做到这一点
安装你的apk:
adb install -r path_to_my_apk.apk
现在您可以更改代码并重新编译.so,当您想要更新它时,您可以执行以下操作:
adb push -p path_to_my_so.so /data/local/tmp/libmyso.so
adb shell cat /data/local/tmp/libmyso.so | run-as com.mycomp.myapp sh -c 'cat > /data/data/com.mycomp.myapp/lldb/libmyso.so; chmod 700 /data/data/com.mycomp.myapp/lldb/libmyso.so'
adb shell rm /data/local/tmp/libmyso.so
Android studio正是这样做,以便在调试本机代码时安装lldb服务器 它假设您的app目录中有一个名为lldb的文件夹。如果您正在使用Android Studio进行调试,则此文件夹已经存在。
您的Java代码需要确保使用
加载正确的.soSystem.load("/data/data/com.mycomp.myapp/lldb/libmyso.so");
而不是System.loadLibrary()
,它不会在某个地方的静态初始化块中占用完整路径,类似于您加载任何其他的.so
如果您的apk非常庞大并且您只想更新二进制文件以便于调试,则此方法非常有用。