用NDK生成cURL和OpenSSL库

最近在用Qt开发Android应用时需要获取https页面内容,但Qt内置的QNetworkAccessManager类只支持下面这些协议(调用其supportedSchemes成员函数获取):

("ftp", "file", "qrc", "http", "data")

而网上我找到的支持https的介绍是使用QSslConfiguration类,然后把OpenSSL的两个DLL(libeay32.dll和ssleay32.dll)复制到Qt库目录中,但我始终没成功,也就懒得在手机上折腾了。

这个思路不行,还有两个方案:一是通过QAndroidJniEnvironment和QAndroidJniObject调用Android SDK中封装的Https访问代码,还有就是通过cURL库,可以复用以前的代码,而且性能也不错,所以选择这个方案。

首先是准备工作:

  • Windows(Win10 x64)

    • 下载并安装msys2(http://repo.msys2.org/distrib/x86_64/),启动msys2_shell.cmd脚本,运行“pacman -Syuu”升级后关闭控制台窗口,重新启动后再运行一遍。这一步是可选的,如果不更新应该也可以,但我是更新后开始下一步的。
    • 下载Windows版NDK并安装
    • 设置ANDROID_NDK_HOME环境变量:exprot ANDROID_NDK_HOME=/d/android-ndk-r20
    • 更新PATH环境变量:export PATH="/d/android-ndk-r20/toolchains/llvm/prebuilt/windows-x86_64/bin/":$PATH
  • Linux(CentOS 8)
    • 下载Linux版NDK并安装
    • 设置ANDROID_NDK_HOME环境变量:exprot ANDROID_NDK_HOME=/home/user/android-ndk-r20
    • 更新PATH环境变量:export PATH="/home/user/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin":$PATH
  • 下载OpenSSL源码包,版本必须是1.1.x,开始我没注意,用的是之前下载的1.0.x,折腾了很长时间也没搞定,郁闷!
  • 下载cURL源码包,我用的版本是7.66.0

然后就可以开工,下面列出的命令都是Linux平台,Windows里面msys2的命令大同小异。

生成OpenSSL

  • cd openssl-1.1.1d
  • ./Configure shared android-arm -D__ANDROID_API__=23 no-asm no-ssl2 no-ssl3 no-comp no-hw no-engine --prefix=/usr/local/ssl
  • make -j && make install

上面第二行命令中的android-arm参数要注意,脚本提示可选的系统/编译器有很多:

android-arm android-arm64 android-armeabi android-mips android-mips64 android-x86 android-x86_64 android64 android64-aarch64 android64-mips64 android64-x86_64

但要选择哪个取决于你所用NDK根目录下“platforms/android-xx”里面的子目录能对应上才行,例如android-ndk-r20中的android-16里面只有arch-arm和arch-x86,所以如果命令行设置__ANDROID_API__=16的话,是不能生成android-arm64版库文件的。

接下来是cURL

  • cd curl-7.66.0
  • CC=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi23-clang ./configure --prefix=/usr/local/curl --host=arm-linux-androideabi --with-ssl=/usr/local/ssl/
  • make -j && make install

在用到Qt项目之前,先写个控制台程序测试一下:

 1 #include <iostream>
 2 #include <map>
 3 #include <string>
 4 #include <curl/curl.h>
 5
 6
 7 using namespace std;
 8
 9
10 #define URL u8R"(https://raw.githubusercontent.com/LCTT/LFS-BOOK/9.0-translating/README.md)"
11
12
13 typedef std::map<std::string, std::string> HeaderFields;
14 typedef struct {
15     int code;
16     std::string body;
17     HeaderFields headers;
18 } Response;
19
20
21 size_t write_callback( void *data, size_t size, size_t nmemb, void *userdata )
22 {
23     Response *r = reinterpret_cast< Response * >( userdata );
24     r->body.append( reinterpret_cast< char * >( data ), size * nmemb );
25     return size * nmemb;
26 }
27
28
29 int _cURL()
30 {
31     if( curl_global_init( CURL_GLOBAL_ALL ) != CURLE_OK )
32     {
33         cout << "Call curl_global_init failed! \n";
34         return 1;
35     }// if
36
37     CURL *curlHandle = curl_easy_init();
38     CURLcode res = CURLE_OK;
39     curl_slist *headerList = nullptr;
40     Response ret = {};
41     curl_easy_setopt( curlHandle, CURLOPT_URL, URL );
42     curl_easy_setopt( curlHandle, CURLOPT_WRITEFUNCTION, write_callback );
43     curl_easy_setopt( curlHandle, CURLOPT_WRITEDATA, &ret );
44     curl_easy_setopt( curlHandle, CURLOPT_SSL_VERIFYPEER, 0 );
45     curl_easy_setopt( curlHandle, CURLOPT_SSL_VERIFYHOST, 0 );
46     res = curl_easy_perform( curlHandle );
47     if( res != CURLE_OK )
48         cout << "The result code is: " << ( int )res << "\n";
49     if( false == ret.body.empty() )
50         cout << ret.body << "\n";
51     curl_easy_cleanup( curlHandle );
52     curl_global_cleanup();
53
54     return 0;
55 }
56
57
58 int main()
59 {
60     return _cURL();
61 }

保存为test.cc,然后生成Android控制台程序:

$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi23-clang++ test.cc -I/usr/local/curl/include -Wl,-Bstatic -lcurl -lssl -lcrypto -Wl,-Bdynamic -o test

注意curl、ssl和crypto三个库用-Wl,-Bstatic方式指定链接静态库(顺序不能错),否则默认会链接动态库,但非root手机没有复制动态库到系统目录的权限,所以需要静态链接得到test,然后开启Android手机的调试模式并连接主机USB,最后在命令行切换到Android SDK的platform-tools目录:

  • 把文件复制到手机存储器:adb push test /data/local/tmp
  • 启动adb Shell:adb shell
  • 文件添加可执行权限:chmod +x /data/local/tmp/test
  • 启动:/data/local/tmp/test

顺利的话就可以正确获取并显示页面中的文本,然后就可以导入Qt项目,首先把cURL的头文件都复制到项目的目录中,然后把libcurl.a、libssl.a和libcrypto.a三个库文件复制到项目路径的android/lib中,修改*.pro文件,添加下面一行:

LIBS += -L$$PWD/android/lib -lcurl -lssl -lcrypto

如果已经有LIBS就在后面加上-lcurl -lssl -lcrypto三个库的引用,最后即可生成APK。

注意:

  1. 如果系统没有GNU binutils,运行cURL的configure脚本前需要把NDK的路径添加到PATH,而且是添加对应生成目标的路径,例如:PATH=“$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin/”:$PATH,然后在生成不同目标平台库的时候先切换。
  2. Qt应用项目的Android系统版本号要大于等于生成cURL和OpenSSL设置的__ANDROID_API__版本号,否则链接时可能会出现找不到stdin、stdout和stderr外部符号的错误,一般生成库都是选个低点的系统版本兼容性更好。

原文地址:https://www.cnblogs.com/qiliang/p/11663058.html

时间: 2024-10-08 09:59:05

用NDK生成cURL和OpenSSL库的相关文章

添加curl的openssl的功能,实现https的正确访问

公司开发部遇到一个难题,服务器环境的curl的功能参数无法支持ssl,那么很多功能将会无法实现.那么好吧,这个问题只好抛到运维这边了,我也是个新手,下边的见解纯属个人分析(如有问题,欢迎讨论): 首先系统:Centos 6.5 x86_64, 服务器版本的默认安装路径:curl在/usr下,openssl在/usr下  (当然,版本都是挺低的,yum更新后,版本还是很低,而且理所当然的,yum安装是无法带参数的,那么很显然,更新后curl还是无法支持openssl) 安装所有常用的开发包yum

Elasticsearch之curl创建索引库和索引时注意事项

前提, Elasticsearch之curl创建索引库 Elasticsearch之curl创建索引 注意事项 1.索引库名称必须要全部小写,不能以下划线开头,也不能包含逗号 2.如果没有明确指定索引数据的ID,那么es会自动生成一个随机的ID,需要使用POST参数 curl -XPOST http://192.168.80.200:9200/zhouls/emp/ -d '{"name" : "tom"}' 3.如果想要确定我们创建的都是全新的数据 1:使用随机I

iOS App中 使用 OpenSSL 库

转自:http://blog.csdn.net/kmyhy/article/details/6534067 在你的 iOS App中 使用 OpenSSL 库 ——译自x2on的“Tutorial: iPhone App with compiled OpenSSL 1.0.0a Library” 原文地址:http://www.x2on.de/2010/07/13/tutorial-iphone-app-with-compiled-openssl-1-0-0a-library/,本文有少许地方做

使用openssl库实现RSA、AES数据加密

使用openssl库实现RSA.AES数据加密 openssl是可以很方便加密解密的库,可以使用它来对需要在网络中传输的数据加密.可以使用非对称加密:公钥加密,私钥解密.openssl提供了对RSA的支持,但RSA存在计算效率低的问题,所以一般的做法是使用对称密钥加密数据,然后再把这个只在当前有效的临时生成的对称密钥用非对称密钥的公钥加密之后传递给目标方,目标方使用约定好的非对称密钥中的私钥解开,得到数据加密的密钥,再进行数据解密,得到数据,这种使用方式很常见,可以认为是对HTTPS的裁剪.对称

vs2010编译curl为static库及测试

1,编译curl为static库 用vs2010打开: curl-7.32.0\vs\vc6\vc6curl.dsw 选择LIB Release生成libcurl静态库: curl-7.32.0\vs\vc6\lib\lib-release\libcurl.lib 2,重新建立一个testcurl控制台程序 添加curl头文件:拷贝curl-7.32.0\include\curl  到 testcurl\testcurl 目录下 拷贝libcrul.lib静态库:拷贝curl-7.32.0\vs

android开发 NDK 编译和使用静态库、动态库 (转)

在eclipse工程目录下建立一个jni的文件夹 在jni文件夹中建立Android.mk和Application.mk文件 Android.mk文件: Android提供的一种makefile文件,用来指定诸如编译生成so库名.引用的头文件目录.需要编译的.c/.cpp文件和.a静态库文件等.详见附件中的Android.mk. Application.mk文件: 定义了项目的一些细节,比如APP_ABI := x86(编译X86平台库).APP_PLATFORM := android-9(使用

在你的 iOS App中 使用 OpenSSL 库

在你的 iOS App中 使用 OpenSSL 库 ——译自x2on的“Tutorial: iPhone App with compiled OpenSSL 1.0.0a Library” 原文地址:http://www.x2on.de/2010/07/13/tutorial-iphone-app-with-compiled-openssl-1-0-0a-library/ ,本文有少许地方做了调整. 1.下载OpenSSL源代码库: http://www.openssl.org/source/

android开发 NDK 编译和使用静态库、动态库

在eclipse工程目录下建立一个jni的文件夹. 在jni文件夹中建立Android.mk和Application.mk文件. Android.mk文件: Android提供的一种makefile文件,用来指定诸如编译生成so库名.引用的头文件目录.需要编译的.c/.cpp文件和.a静态库文件等.详见附件中的Android.mk. Application.mk文件: 定义了项目的一些细节,比如APP_ABI := x86(编译X86平台库).APP_PLATFORM := android-9(

RSA加解密 私钥加密公钥解密 私加公解 &amp;&amp; C++ 调用openssl库 的代码实例

前提:秘钥长度=1024 ============================================== 对一片(117字节)明文加密  私加 ============================================== // 私钥加密 std::string rsa_pri_encrypt(const std::string &clearText, std::string &pubKey) { std::string strRet; BIO *keybio