我正在开发一个基于 Qt 的 Android 应用程序,它使用 QSslSocket 下载数据。由于 Android 从 OpenSSL 转向 BoringSSL,因为依赖 OpenSSL 库的 Marshmallow Qt 程序在 Android 6+ 上会产生以下警告:
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve CRYPTO_free
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve EVP_CipherFinal
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve EVP_rc2_cbc
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve OPENSSL_add_all_algorithms_noconf
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve OPENSSL_add_all_algorithms_conf
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot resolve EC_get_builtin_curves
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot call unresolved function OPENSSL_add_all_algorithms_conf
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot call unresolved function EC_get_builtin_curves
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot call unresolved function EC_get_builtin_curves
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: could not set SSL_CTRL_SET_TLSEXT_HOSTNAME, Server Name Indication disabled
W libtestopenssl.so: (null):0 ((null)): qt.network.ssl: QSslSocket: cannot call unresolved function CRYPTO_free
但是,套接字本身成功连接到远程主机并从那里读取数据,没有任何明显的问题。这让我想知道是否需要自己构建OpenSSL库并将其打包,或者使用平台提供的BoringSSL也可以。
我还注意到,Android 6 版本以下的应用程序倾向于使用系统版本的 OpenSSL,即使我提供了自己的版本。我尝试添加构建的 libssl.so 和 libcrypto.so (从 libssl.so.1.0.0 和 libcrypto.so.1.0.0 重命名)ANDROID_EXTRA_LIBS
(不确定是否LIBS+=
也需要使用)甚至静态链接 libssl.a 和 libcrypto.a。 QSslSocket::sslLibraryVersionString() 仍然返回平台上可用的版本。
我的问题是:
- 我需要自己构建OpenSSL库并将其打包还是使用平台提供的库就可以?
- 如果我这样做,如何让Android识别libssl.so和libcrypto.so?
1. 需要自己构建OpenSSL库并打包还是使用平台提供的库也可以?
- 是的 - 您应该构建 OpenSSL 并将其打包。
https://developer.android.com/about/versions/nougat/android-7.0-changes.html https://developer.android.com/about/versions/nougat/android-7.0-changes.html
从 Android 7.0 开始,系统会阻止应用程序动态链接非 NDK 库,这可能会导致应用程序崩溃。这种行为变化旨在跨平台更新和不同设备创建一致的应用程序体验。
- 使用已安装的 BoringSSL 目前可能可行,但建议应用程序自带自己的 OpenSSL 库。
- 否则,您的用户将看到弹出警告消息,并且该应用程序可能无法在更高版本的 Android 上运行。
为了减少此限制可能对当前发布的应用程序产生的影响,在 Android 7.0 上可以暂时访问一组重要用途的库(例如 libandroid_runtime.so、libcutils.so、libcrypto.so 和 libssl.so) (API 级别 24)适用于面向 API 级别 23 或更低级别的应用。如果您的应用程序加载这些库之一,logcat 会生成一条警告,并且目标设备上会出现一个 toast 来通知您。如果您看到这些警告,您应该更新您的应用程序以包含这些库自己的副本或仅使用公共 NDK API。 Android 平台的未来版本可能会完全限制私有库的使用,并导致您的应用程序崩溃。
2. 如果我这样做,如何让Android识别libssl.so和libcrypto.so?
我使用 API 级别 19。一旦我使用 API 级别 23 或 25 进行测试,我将更新此答案。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)