jni中使用libcurl做网络开发

curl对android提供了支持,在curl的代码根目录中有相应的makefile文件Android.mk。使用libcrul必须先对curl进行交叉编译

 

一、curl的交叉编译:

 

1、编译android源代码。编译方法参考http://source.android.com。

 

2、在android源码中编译curl,从http://curl.haxx.se/download.html下载curl源码,解压到external/curl目录。

 

3、在external/curl目录中进行configure,(红色字部分根据自己的环境做相应的更改)

 

ANDROID_ROOT=`realpath /android/source/` && \

TOOLCHAIN_VER="4.4.0"  \

PLATFORM_VER="8" \

CROSS_COMPILE=arm-eabi- \

PATH=$ANDROID_ROOT/prebuilt/linux-x86/toolchain/arm-eabi-$TOOLCHAIN_VER/bin:$PATH  && \

CPPFLAGS="-I $ANDROID_ROOT/system/core/include -I$ANDROID_ROOT/bionic/libc/include -I$ANDROID_ROOT/ndk/build/platforms/android-5/arch-arm/usr/include -I$ANDROID_ROOT/bionic/libc/kernel/arch-arm -L $ANDROID_ROOT/prebuilt/linux-x86/toolchain/arm-eabi-$TOOLCHAIN_VER/lib/gcc/arm-eabi/$TOOLCHAIN_VER/interwork -L$ANDROID_ROOT/ndk/build/platforms/android-$PLATFORM_VER/arch-arm/usr/lib  -L$ANDROID_ROOT/out/target/product/generic/system/lib " \

CFLAGS="-fno-exceptions -Wno-multichar -mthumb -mthumb-interwork -nostdlib -lc -ldl -lm "  \

./configure CC=arm-eabi-gcc --host=arm-linux --disable-tftp --disable-sspi --disable-ipv6 --disable-ldaps --disable-ldap --disable-telnet --disable-pop3 --disable-ftp --without-ssl --disable-imap --disable-smtp --disable-pop3 --disable-rtsp --disable-ares --without-ca-bundle --disable-warnings --disable-manual --without-nss --enable-shared --without-zlib --without-random

 

如果需要openssl或zlib,可以把configure参数改为

./configure CC=arm-eabi-gcc --host=arm-linux --disable-tftp --disable-sspi --disable-ipv6 --disable-ldaps --disable-ldap --disable-telnet --disable-pop3 --disable-ftp --with-ssl=$ANDROID_ROOT/external/openssl --disable-imap --disable-smtp --disable-pop3 --disable-rtsp --disable-ares --without-ca-bundle --disable-warnings --disable-manual --without-nss --enable-shared --with-zlib=$ANDROID_ROOT/external/zlib --without-random

 

4、进入ANDROID_ROOT目录,执行source build/envsetup.sh,如果需要编译curl 执行make curl,或者仅编译libcurl make libcurl

 

5、如果要生成动态库需要修改curl下的Android.mk : 

LOCAL_PRELINK_MODULE := false 

LOCAL_MODULE:= libcurl 

LOCAL_MODULE_TAGS := optional 

# Copy the licence to a place where Android will find it. 

# Actually, this doesn't quite work because the build system searches 

# for NOTICE files before it gets to this point, so it will only be seen 

# on subsequent builds. 

ALL_PREBUILT += $(LOCAL_PATH)/NOTICE 

$(LOCAL_PATH)/NOTICE: $(LOCAL_PATH)/COPYING | $(ACP) 

$(copy-file-to-target) 

#include $(BUILD_STATIC_LIBRARY) 

include $(BUILD_SHARED_LIBRARY)

 

二、在jni中使用libcurl

1、在android源码目录中创建一个带jni的应用。

 

2、把libcurl的头文件拷贝到jni目录,在jni目录下创建3rd/include目录: 

cp -r $ANDROID_ROOT/out/target/product/generic/obj/include/libcurl/curl/  jni/3rd/include

 

3、修改jni目录下的Android.mk文件,实例如下

 

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

 

LOCAL_C_INCLUDES += \

$(JNI_H_INCLUDE) \

$(LOCAL_PATH) \

$(LOCAL_PATH)/3rd/include \

 

LOCAL_PRELINK_MODULE:=false

 

LOCAL_STATIC_LIBRARIES := libcurl

 

LOCAL_MODULE:= libXXXXXX

 

LOCAL_MODULE_TAGS := optional

 

include $(BUILD_SHARED_LIBRARY)

 

4、事例代码如下:

#include "curl/curl.h"

#include <stdlib.h>

 

typedef struct pageInfo_t {

    char *data;

    int len;

} pageInfo_t;

static size_t

HTTPData(void *buffer, size_t size, size_t nmemb, void *userData) {

    int len = size * nmemb;

    pageInfo_t *page = (pageInfo_t *)userData;

 

    if (buffer && page->data && (page->len + len < (16 * 1024)) ) { memcpy(&page->data[page->len], buffer, len);

        page->len += len;

    }

    return len;

}

 

void curltest()

{

pageInfo_t page;

   CURL *curl;

   CURLcode res;

   char *buffer;

 

   page.data = (char *)malloc(16 * 1024);

   page.len = 0;

   if (page.data)

       memset(page.data, 32, 16 * 1024);

 

   buffer = (char *)malloc(1024);

 

   curl = curl_easy_init();

   if(curl) {

       curl_easy_setopt(curl, CURLOPT_URL, "http://baihexss.sinaapp.com/plugin.html");

       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPData);

       curl_easy_setopt(curl, CURLOPT_WRITEDATA, &page);

 

       res = curl_easy_perform(curl);

       /* always cleanup */

       curl_easy_cleanup(curl);

       if(res == 0) {

           if (buffer) {

               page.data[page.len < 256 ? page.len : 256] = '\0';

               LOG("pagedata(%d): %s. done.\n", page.len, page.data);

 

           }

       }

       LOG("Result %d", res);

 

   } else {

   LOG("Unable to init cURL");

   }

 

}

 

5、在应用代码根目录执行mm编译,最后输出

============================================

PLATFORM_VERSION_CODENAME=REL

PLATFORM_VERSION=2.2.2

TARGET_PRODUCT=generic

TARGET_BUILD_VARIANT=eng

TARGET_SIMULATOR=

TARGET_BUILD_TYPE=release

TARGET_BUILD_APPS=

TARGET_ARCH=arm

HOST_ARCH=x86

HOST_OS=linux

HOST_BUILD_TYPE=release

BUILD_ID=FRG83G

============================================

make: Entering directory `/android/source'

target Non-prelinked: lib***** (out/target/product/generic/symbols/system/lib/lib*****.so)

Copying: out/target/common/obj/APPS/*****_intermediates/classes-full-debug.jar

Install: out/target/product/generic/data/app/*****.apk

Copy: out/target/product/generic/system/etc/apns-conf.xml

make: Leaving directory `/android/source'

 

6、把out/target/product/generic/data/app/*****.apk安装执行即可看到结果






备注:

开发环境:Android ndk1.5_r1,cygwinm

libcurl 7.19.6 源码  下载地址 http://curl.haxx.se/

 

参考文章:http://blog.csdn.net/choujs/archive/2010/02/10/5304978.aspx

http://curl.haxx.se/mail/lib-2009-12/0071.html

 

如ndk开发一样,先刚libcurl源码放置 Android-ndk/source/sampel/ 下

在Android-ndk/apps 建相应的文件夹和application.mk    

 

对ndk不熟悉可以先参考 Android ndk开发

 

 

1.在cygwin下,进入Android-ndk/ 目录, 运行 ./configure

自动checking 。(自过程需要花一些时间请耐心等待)

 完成,自动创建相应配置文件

 

手动修改 lib/curl_config.h和src/curl_config.h,打开宏定义HAVE_LIBSSL、 HAVE_OPENSSL_CRYPTO_H、HAVE_OPENSSL_ERR_H、HAVE_OPENSSL_PEM_H、 HAVE_OPENSSL_PKCS12_H、HAVE_OPENSSL_RSA_H、HAVE_OPENSSL_SSL_H、 HAVE_OPENSSL_X509_H、USE_OPENSSL、USE_SSLEAY(但是注意android没有编译openssl中的 engine,因此不要打开宏定义HAVE_OPENSSL_ENGINE_H),同时注释掉宏定义HAVE_MALLOC_H和HAVE_IOCTL

(本段参考以上给出链接)

 

android.mk

[cpp:showcolumns]  view plain copy
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. LOCAL_PATH:= $(call my-dir)  
  2.   
  3. common_CFLAGS := -Wpointer-arith -Wwrite-strings -Wunused -Winline -Wnested-externs -Wmissing-declarations -Wmissing-prototypes -Wno-long-long -Wfloat-equal -Wno-multichar -Wsign-compare -Wno-format-nonliteral -Wendif-labels -Wstrict-prototypes -Wdeclaration-after-statement -Wno-system-headers -DHAVE_CONFIG_H  
  4.   
  5. #########################  
  6. # Build the libcurl library  
  7.   
  8. include $(CLEAR_VARS)  
  9. include $(LOCAL_PATH)/lib/Makefile.inc  
  10.   
  11. CURL_HEADERS := /  
  12.     curlbuild.h /  
  13.     curl.h /  
  14.     curlrules.h /  
  15.     curlver.h /  
  16.     easy.h /  
  17.     mprintf.h /  
  18.     multi.h /  
  19.     stdcheaders.h /  
  20.     typecheck-gcc.h /  
  21.     types.h  
  22.   
  23.   
  24. LOCAL_SRC_FILES := $(addprefix lib/,$(CSOURCES))  
  25. LOCAL_C_INCLUDES += $(LOCAL_PATH)/include   
  26. LOCAL_CFLAGS += /  
  27. $(common_CFLAGS) /  
  28. -I$(LOCAL_PATH)/include /  
  29. -I/usr/include  
  30.   
  31. LOCAL_COPY_HEADERS_TO := libcurl/curl  
  32. LOCAL_COPY_HEADERS := $(addprefix include/curl/,$(CURL_HEADERS))  
  33.   
  34. LOCAL_MODULE:= libcurl  
  35.   
  36. include $(BUILD_STATIC_LIBRARY)  

 

在cygwin中运行

make APP=libcurl -B

 

出现2个警告信息:

/ssluse.c: In function 'Curl_ossl_init':
/ssluse.c:632: warning: nested extern declaration of 'ENGINE_load_builtin_engines'

/strerror.c: In function 'Curl_strerror':
/strerror.c:642: warning: initialization makes pointer from integer without a cast


其他均无报错。但成功生成了libcurl.a文件。

 

测试过程:

测试中,发现IDN 的lib包始终找不到。

 

 

找了android的模拟器的lib文件下,也没有找到libidn 。所以准备重新编译libcurl.a,去掉与IDN相关的部分。

 

再次编译成功。

但在模拟器上始终得到7(Failed to connect() to host or proxy)

 

郁闷了一阵,最后发现应该在AndroidManifest.xml中

加入

    <uses-permission android:name="android.permission.INTERNET"/>

再次测试,成功得到0。

编译完成!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值