在android開發(fā)過程中,無論是java層或者native層羹奉,我們經(jīng)常會寫一些關(guān)鍵日志信息到文件中秒旋,方便定位問題,可能存在將日志文件進行上傳到服務(wù)器上诀拭,或者需要從服務(wù)器上下載一些配置信息文件迁筛,當(dāng)然我們可以通過java層的http請求進行上傳或者下載操作,但是其實為了更好的跨平臺特性耕挨,我們可以使用libcurl來實現(xiàn)瑰煎。
簡介
libcurl為一個免費開源的,客戶端url傳輸庫俗孝,支持DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet and TFTP等協(xié)議酒甸。
libcurl也支持SSL證書,HTTP POST, HTTP PUT,FTP上傳,基于表單的HTTP上傳赋铝,代理(proxies)插勤、cookies、用戶名/密碼認證(Basic, Digest, NTLM等)革骨、下載文件斷點續(xù)傳农尖,上載文件斷點續(xù)傳(file transfer resume),http代理服務(wù)器管道(proxy tunneling)等良哲。這通常我們需要與openssl庫共同配合來完成加密請求盛卡。
libcurl是高度可移植的,可以工作在不同的平臺上筑凫,支持Windows滑沧,Unix,Linux等巍实。
libcurl是免費的滓技,線程安全的,IPV6兼容的棚潦,同時它還有很多其他非常豐富的特性令漂。libcurl已經(jīng)被很多知名的大企業(yè)以及應(yīng)用程序所采用。
總結(jié)起來:curl的特性就是開源丸边、支持協(xié)議多叠必、支持ssl、支持跨平臺妹窖、支持ipv6等等諸多特性纬朝。
在Android平臺的編譯
環(huán)境準(zhǔn)備
- ndk環(huán)境,ndk環(huán)境請自行下載
- curl源碼(7.64.1),下載地址嘱吗。
- 交叉編譯工具鏈玄组,請參考自定義NDK交叉編譯工具類
編譯
定義環(huán)境變量
export TOOLCHAIN=$ANDROID_HOME/toolchain // toolchain路徑滔驾,自行修改
export PKG_CONFIG_LIBDIR=$TOOLCHAIN/lib/pkgconfig
export CROSS_SYSROOT=$TOOLCHAIN/sysroot
export PATH=$TOOLCHAIN/bin:$PATH
export TOOL=arm-linux-androideabi
export CC=$TOOLCHAIN/bin/${TOOL}-gcc
export CXX=$TOOLCHAIN/bin/${TOOL}-g++
export LINK=${CXX}
export LD=$TOOLCHAIN/bin/${TOOL}-ld
export AR=$TOOLCHAIN/bin/${TOOL}-ar
export RANLIB=$TOOLCHAIN/bin/${TOOL}-ranlib
export STRIP=$TOOLCHAIN/bin/${TOOL}-strip
export ARCH_FLAGS="-mthumb"
export ARCH_LINK=
export CFLAGS="${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64"
export CXXFLAGS="${CFLAGS} -frtti -fexceptions"
export LDFLAGS="${ARCH_LINK}"
編譯并安裝
cd curl-7.64.1
autoreconf -i
./configure --prefix=$TOOLCHAIN/sysroot/usr/local \
--with-sysroot=$TOOLCHAIN/sysroot \
--host=arm-linux-androideabi \
--with-ssl=$TOOLCHAIN/sysroot/usr/local \
--with-nghttp2=$TOOLCHAIN/sysroot/usr/local \
--enable-ipv6 \
--enable-static \
--enable-threaded-resolver \
--disable-dict \
--disable-gopher \
--disable-ldap --disable-ldaps \
--disable-manual \
--disable-pop3 --disable-smtp --disable-imap \
--disable-rtsp \
--disable-shared \
--disable-smb \
--disable-telnet \
--disable-verbose
make -j4
make install
./configure ...
過程自己根據(jù)當(dāng)前項目的需求,disable不相關(guān)的配置俄讹,減少庫體積哆致。
生成庫
編譯完庫,生成在./configure時指定的prefix路徑下
將include和lib中的靜態(tài)庫引用到android工程中進行使用患膛。
遇到問題
生成的庫放在ndk中使用時摊阀,我們ndk如果APP_PLATFORM目標(biāo)小于android-21
,也就是LOLLIPOP版本以下時踪蹬,編譯會報錯:undefined reference to 'getpwuid_r'
胞此,鏈接不到getpwuid_r
方法,其實是在android-21以下的編譯環(huán)境中跃捣,沒有該方法漱牵,如果要使用,必須將APP_PLATFORM提升到android-21
疚漆,對應(yīng)的酣胀,我們的app minSdkVersion也必須要升到21。升級支持最低系統(tǒng)版本號這種做法娶聘,其實不是我們想要的闻镶。
沒辦法,只能去看curl源碼丸升,發(fā)現(xiàn)我們在使用到該方法的地方铆农,都有用宏HAVE_GETPWUID_R
控制
#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID)
if((!username || !username[0]) &&
!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) &&
pw_res) {
username = pw.pw_name;
}
#endif
那么只要在編譯的時候,將該宏undefine狡耻,在編譯和運行時就能跳過該方法墩剖,具體做法如下:
export CFLAGS="${ARCH_FLAGS} -fpic -ffunction-sections -funwind-tables -fstack-protector -fno-strict-aliasing -finline-limit=64 -DHAVE_GETPWUID_R=0"
或者在使用到該宏的源碼處,取消宏定義
#undef HAVE_GETPWUID_R
這樣curl重新編譯酝豪,就能夠在android-21以下的系統(tǒng)版本中使用啦...