4.5 Android上使用libcurl

下载和编译

libcurl想要在Android上开发,显然不能只能用C++的so文件。

所以我们需要将curl的源代码通过Android.mk重新编译一次,但是显然很是麻烦。

这里我用就用别人写好的东西。

https://github.com/gcesarmza/curl-android-ios

这个是一个已经写好的移动端使用libcurl的源代码。

下载curl_android_ios

git clone https://github.com/gcesarmza/curl-android-ios.git

由于这个库依赖于 curl库和 openssl,所以需要再次关联下载

git submodule init && git submodule update

编译android版本

/curl-android-ios-master/curl-compile-scripts/

./bulid_android.sh

(1) 问题1

如果提示需要NDK_ROOT环境变量,需要在~/.bashrc加入NDK安装的路径.

vim ~/.bashrc

export NDK_ROOT=/home/itcast/BC-Project/Android-SDK/ndk-bundle

source ~/.bashrc

(2) 问题2

./build_Android.sh: 行 34: ./Configure: 没有那个文件或目录
Error running the ssl configure program

可能是没有下载依赖库openssl 和curl导致。


这个编译可能会话费很长时间,因为他要编译很多种平台的Android。如x86,mips,arm等等。

最后,我们会得到以下静态库文件。

[arm64-v8a] StaticLibrary  : libcurl.a
[x86_64] StaticLibrary  : libcurl.a
[mips64] StaticLibrary  : libcurl.a
[armeabi] StaticLibrary  : libcurl.a
[armeabi-v7a] StaticLibrary  : libcurl.a
[x86] StaticLibrary  : libcurl.a
[mips] StaticLibrary  : libcurl.a

对应我们Android的设备的平台型号,选择一款就好了,一般我们都是用的[armeabi]

配置和部署

将生成的libcurl.a 和所对应的头文件拷贝到Android项目中的jni/路径下。

cd ./curl-android-ios-master/prebuilt-with-ssl/android/

cp armeabi/libcurl.a ~/AndroidStudioProjects/testApp/jni/
cp include/curl/ ~/AndroidStudioProjects/testApp/jni/ -R

以上如果您使用的开发环境是Linux。

如果是Windows,需要将armeabi下的libcurl.a通过远程传输,拷贝到当前windows项目中的jni路径下.

测试libcurl

目前我们jni/路径下已经有 libcurl.a 和curl/头文件了。

现在我们可以实现一个login的jni接口,让java调用,来完成客户端和服务端的网络通信。

(1)首先在java类中,定义一个native接口。

    //登陆服务器login接口
    public native void testLibcurl();

(2) 给该native通过javah生成头文件.

cd testApp/app/src/main/java/

javah -jni com.cpp.itcast.testapp.HelloJni

(3)测试libcurl代码

在jni.cpp中 实现jni接口。 就是访问一个网页,然后将网页的信息打印到debug上。

size_t print_html( void *ptr, size_t size, size_t nmemb, void *stream)
{
    int len = size*nmemb;
    char *buf = new char[len+1];

    memcpy(buf, ptr, len);

    buf[len] = '\0';

    __android_log_print(ANDROID_LOG_ERROR, "jnitag", "%s\n", buf);

    delete [] buf;

    return len;
}

JNIEXPORT void JNICALL Java_com_cpp_itcast_testapp_HelloJni_testLibcurl
  (JNIEnv *, jobject)
{    
    CURL *curl = NULL;
    CURLcode ret;

    curl = curl_easy_init();

    curl_easy_setopt(curl, CURLOPT_URL, "www.baidu.com");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, print_html);

    ret = curl_easy_perform(curl);
    if (ret != CURLE_OK) {
        __android_log_print(ANDROID_LOG_ERROR, "jnitag", "curl_easy_perform error");
        return ;
    }

    curl_easy_cleanup(curl);

    return ;
}

(4)修改Android.mk文件

LOCAL_PATH:=$(call my-dir)

include $(CLEAR_VARS)

# libcurl.a
LOCAL_MODULE := libcurl
LOCAL_SRC_FILES := libcurl.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)

#libmyJni.so
LOCAL_MODULE := myJni
LOCAL_SRC_FILES := test.cpp jni.cpp
LOCAL_LDLIBS := -llog -lz
LOCAL_STATIC_LIBRARIES := libcurl
include $(BUILD_SHARED_LIBRARY)

(5) 编译生成libmyJni.so

进入到jni/路径 执行。

ndk-build APP_ABI="armeabi"

(6)测试 该Jni接口

此过程需要两个必要条件:

1.Android移动设备必须可以上网。

2.给该APP应用开辟上网权限

开辟上网权限如下:

打开testApp/app/src/main/AndroidManifest.xml:

标签里面加入如下标签:

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

3.在app源根文件夹下build.gradle文件的配置

这里面加注释的是额外需要关注的地方。

    compileSdkVersion 24
    buildToolsVersion "24.0.3"
    defaultConfig {
        applicationId "com.example.ace.obo"
        minSdkVersion 10
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"


        // 不声明ndk标签,项目默认会创建一个libapp.so的文件
        ndk {
            // 声明创建so库的文件名,会自动添加lib前缀, 添加了前缀,不会自动添加
            moduleName "OBOjni"

            //声明启用Android日志, 在c/c++的源文件中使用的#include <android/log.h> 日志将得到输出
            //这里我们关联了两个库 一个是liblog 和 libz
            ldLibs "log","z"


            // 声明创建指定cpu架构的so库, 不声明的话, 默认(gradle 1.5.0)会生成7中架构,如果你的libcurl没有提供别的平台,那么就会链接失败,
            //所以此条配置很重要,这里我们只生成一个平台
            abiFilters "armeabi"

        }

    }

4.另外最好加上如下配置

项目根文件夹下的gradle.properties文件中添加如下配置(解决AS中NDK插件过时不能编译的问题)

android.useDeprecatedNdk=true

5.最后执行测试代码,在真机上运行,观察结果.

     HelloJni.getInstance().testLibcurl();

注意事项:

如果在生成连接到时候 出现 error: linker command failed with exit code 1 (use -v to see invocation)错误

需要过滤生成的ABI平台

results matching ""

    No results matching ""