Porting of cURL to Android OS using NDK (from The Software Rogue)
Porting of cURL to Android OS using NDK
I did see some examples of partial porting and even in the curl library source there is an Android.mk which describes how to set it up although not in enough detail. Both work helpful but didn't actually get me to the holy land of a usable test applications. (http://www.mail-archive.com/curl-library@cool.haxx.se/msg03433.html was helpful but didn't work for me.)
I found it worth the exercise of downloading the full android sources and building them. Look at the build process, the bionic library, and well as whats in external. The external directory is where you would add repositories to do things like run configure, etc
You won't actually need Linux since I have included the config file here but in case you want to follow way it was created, I've included it.
Summary of the steps to take for this port:
- Lots of searches and view the current state of curl porting
- Setup source repository (I used Linux, you could try windows using cygwin)
- Create curl_config.h under the full android source tree
- Untar curltest.tar.gz under $NDKROOT or Create NDK JNI App on Windows
- Cross-link or add to eclipse project to build Java front-end
- Unpack cURL into $NDKROOT/apps/curltest/jni/curl
- Copy curltest/jni/curlbuild.h to curltest/jni/curl/include/curl
- Copy curltest/jni/curl_config.h to curltest/jni/curl/lib
- Build and test
Setup source repository on Linux
It's one thing to describe doing X, quite another to actually do it. Anyway, I ended up creating my own android repository to start the process. While I was using Windows 7 for my NDK development, I switched to Linux to create the curl_config.h file needed in the build. What this means it that you run a couple of scripts. First up, repo. Created a directory and cd to it. Download the repo script 'wget https://android.git.kernel.org/repo'. Move repo script to somewhere in your path and issue 'repo init -u git://android.git.kernel.org/platform/manifest.git' then after run 'repo sync'. These two should get you all the goodies. I had some stalls where I had to restart the sync process but after a long while it completed successfully.
Create curl_config.h under the full android source tree
Next, I created a script to call the configure command to generated the curl_config.h. CD to $ANDROID_ROOT/external. Untar curl libraries, I renamed my from curl-7.20.1 to just curl. cURL has an Android.mk inside of it. In the file were some instructions for generating the curl_config.h. I found them helpful as a start but ultimately I had to fiddle with a number of things to get this to actually work. Here is the script I used:
ANDROID_ROOT="$HOME/android_src" && \
TOOLCHAIN_VER="4.4.0" \
PLATFORM_VER="5" \
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 version
#./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
Run the script in the top curl directory (where configure resides) and it should go through many tests before ultimately creating the lib/curl_config.h file.
Create NDK JNI App on Windows
Untar curltest.tar.gz under $NDKROOT. This has the Java side application already created. Or you can simply create a new Application under Eclipse which will generated the src & res directories that will need to be modified. I'm not going into App generation except that you will target $NDKROOT/apps/curltest/project as your directory tree.
Create library name under $NDKROOT/apps/, I used curltest.
CD to curltest and create the Application.mk file.
APP_PROJECT_PATH := $(call my-dir)/project
APP_MODULES := curltest libcurl
Once that is done, cd to project and create your standard Java AndroidManifest.xml file. If you created an App from Eclipse you'll need to modify this file. Make sure to give it INTERNET permissions. The rest depends on what's in your Java code.
<manifest xmlns:android="/apk/res/android"
android:versionCode="1"
android:versionName="1.0" package="com.mtterra.curltest">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".curltest"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="5"/>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Then cd to jni and create the Android.mk file. This is where the one from cURL would go. However, I didn't use it as anything more than a reference.
Now for the actual JNI interfacing. There are lots of complaints here because everything needs to be specified up front and you need different packages for different hardware. Except for some dynamic registration mechanism, I'm not sure you can get away with writing to hardware AND getting independence from it. Actually, I am sure, you can't.
Here is my curltest.c interface:
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;
}
//Interface function that will receive web page from Java
jstring
Java_com_mtterra_curltest_curltest_JNIGetWebpage( JNIEnv* env,
jobject entryObject,
jstring webpageJStr )
{
pageInfo_t page;
CURL *curl;
CURLcode res;
char *buffer;
const jbyte *webpage;
webpage = (*env)->GetStringUTFChars(env, webpageJStr, NULL);
if (webpage == NULL) {
return NULL; /* OutOfMemoryError already thrown */
}
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, webpage);
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);
(*env)->ReleaseStringUTFChars(env, webpageJStr, webpage);
if(res == 0) {
if (buffer) {
page.data[page.len < 256 ? page.len : 256] = '\0'; sprintf(buffer, "pagedata(%d): %s. done.\n", page.len, page.data); return (*env)->NewStringUTF(env, buffer);
}
}
sprintf(buffer, "Result %d", res);
return (*env)->NewStringUTF(env, buffer);
} else {
return (*env)->NewStringUTF(env, "Unable to init cURL");
}
}
Finally, it's time to setup Eclipse to build. There are some assumptions here, like having a functioning Eclipse build environment. In order to get your environment over to Eclipse, you can use File->Import then select 'Existing Projects into Workspace' function.
Unpack cURL into $NDKROOT/apps/curltest/jni/curl. Move the curl_config.h file created above to $NDKROOT/apps/curltest/jni/curl/lib.
Finally, we create the Android.mk file in curltest/jni and build it. The Android.mk use is as follows:
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
include $(CLEAR_VARS)
include $(LOCAL_PATH)/curl/lib/Makefile.inc
LOCAL_SRC_FILES := $(addprefix curl/lib/,$(CSOURCES))
LOCAL_CFLAGS += $(CFLAGS)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/curl/include/
LOCAL_COPY_HEADERS_TO := libcurl
LOCAL_COPY_HEADERS := $(addprefix curl/include/curl/,$(HHEADERS))
LOCAL_MODULE:= libcurl
include $(BUILD_STATIC_LIBRARY)
# Build shared library now
# curltest
include $(CLEAR_VARS)
LOCAL_MODULE := curltest
LOCAL_SRC_FILES := curltest.c
LOCAL_STATIC_LIBRARIES := libcurl
LOCAL_C_INCLUDES += $(LOCAL_PATH)/curl/include
include $(BUILD_SHARED_LIBRARY)
Going back to your $NDKROOT you should be able to build the library with 'make APP=curltest -B V=1'. The -B means rebuilt it all and V=1 makes it verbose.
After this, you should be able to build the application. When I get back to Eclipse I'll hit F5 to refresh the files as a habit although likely not necessary. Another interesting thing is that some people have indicated that you need to do an 'adb push' to the emulator so the library is there. I haven't found this is the case. Basically, if it doesn't find your library the interface name or some other part is broken and you need to find the issue.
The finished result looks something like:
Here is the NDK project files used. However, you'll have to add the curl sources to this.
The Software Rogue - http://thesoftwarerogue.blogspot.com
Bruce Smith
at
12:50 AM
Porting of cURL to Android OS using NDK (from The Software Rogue)的更多相关文章
- 【android 开 发 】 - Android studio 下 NDK Jni 开发 简单例子
Android 开发了一段时间,一方面 ,感觉不留下点什么.有点对不起自己, 另一方面,好记性不如烂笔头,为了往后可以回头来看看,就当做是笔记,便决定开始写博客.废话不多说 ! 今天想搞一搞 ndk ...
- Android应用---基于NDK的samples例程hello-jni学习NDK开发
Android应用---基于NDK的samples例程hello-jni学习NDK开发 NDK下载地址:http://developer.android.com/tools/sdk/ndk/index ...
- 【Android Studio安装部署系列】二十五、Android studio使用NDK生成so文件和arr文件
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 Android Studio使用ndk的简单步骤. NDK环境搭建 下载NDK 下载链接:https://developer.and ...
- [Android Studio] Using NDK to call OpenCV
NDK才是Android开发通向超高薪之路.(这句话,似乎四年前有云) 难点在于常用的non-free module (sift and surf) unsw@unsw-UX303UB$ pwd /h ...
- [ 转载 ] Android JNI(一)——NDK与JNI基础
Android JNI(一)——NDK与JNI基础 隔壁老李头 关注 4.4 2018.05.09 17:15* 字数 5481 阅读 11468评论 8喜欢 140 本系列文章如下: Androi ...
- Android JNI(一)——NDK与JNI基础
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- Android Studio 之 NDK篇
由于工作内容的关系,对于NDK的工作涉及比较广(保密性,安全性),所以本章内容讲述一下NDK的基本使用过程. 网上也有很多这样的教程或者描述,但描述的并不完全 开发工具:Android Studio ...
- Android JNI和NDK学习(03)--动态方式实现JNI(转)
本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092491.html 前面总结了静态实现JNI的方法,本文介绍如何动态实现J ...
- Android JNI和NDK学习(02)--静态方式实现JNI(转)
本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3095013.html JNI包括两种实现方法:静态和动态.两种方法的区别如下 ...
随机推荐
- vue添加属性绑定
html <div id="app-2"> <span v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定的 ...
- Git之安装及使用
学习使用Git来管理平时自己写的demo代码和阅读的一些源码,因为一直在windows中操作所以开始学习用Git Bash操作在github上的代码.git命令和svn命令是很相似的,我觉得没有必要把 ...
- python 深、浅拷贝
Python的数据结构总体分为两类: 1.字符串和数字 2.列表.元组.字典等 一.字符串和数字 对于字符串和数字而言,赋值(=).浅拷贝(copy)和深拷贝(deepcopy)其实都没有意义,因为它 ...
- ubuntu下MySQL的安装与卸载
1. 删除mysql a. sudo apt-get autoremove --purge mysql-server-5.0 b. sudo apt-get remove mysql-server c ...
- spring整合hibernate时报错:org.hibernte.engine.transaction.spi.transactioncontext
错误提示:Caused by:java.lang.ClassNotFoundException: org.hibernte.engine.transaction.spi.transactioncont ...
- java中16进制转换10进制
java中16进制转换10进制 public static void main(String[] args) { String str = "04e1"; String myStr ...
- 数据分析与展示---anaconda的使用
一:安装 官方源:https://repo.continuum.io/archive/(太慢) 清华源:https://mirrors.tuna.tsinghua.edu.cn/anaconda/ar ...
- JSON 为王,为什么 XML 会慢慢淡出人们的视野?
目前全球信息基础设施的特点是,拥有大量的数据交换格式.这一点也不奇怪.互联网几乎已经老了,而“物联网”及“大数据”正从概念走进现实.但我仍然相信,在这一领域还有一股较强的历史趋势,推动 JSON 数据 ...
- Web应用程序完全测试指南
随着Web技术和移动互联网的发展,越来越多的应用被迁移到了云端,这也使得用户可以随时随地使用它们.目前大量的优质应用,逐渐提升了用户的品味,也降低了用户的容忍度,如果你的Web应用无法使用户满意,那么 ...
- ajax做显示信息以后用ajax、Bootstrp做弹窗显示信息详情
1.用ajax做弹窗显示信息详情 nation.php <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&qu ...