在Android中调用jni使用libcurl返回错误码28(超时)的可能原因
这个问题困扰了我很久。。。
出现场景:
在ndk开发中传递java数据到native接口,处理完后直接在c接口使用libcurl发送http的post请求,这样可以将很多协议和处理逻辑隐藏在so中,但是当代码写完,使用postman进行接口调试发送post数据的接口也是正常的,但放到libcurl的处理接口中发送就一直显示超时(打印的curl的错误码是28),百度、谷歌等都没找到方法解决。
解决过程
有的说是主进程没有进行全局初始化,但是这一步我做了,还是一样;
怀疑是c/c++混用,但是我全部改成c或者全部改成c++的都不行,也是一样;
然后没办法了,换成我之前比较常用的mongoose,只有一个c和h,比较方便加入到项目中,加进来后发现还是不行,这说明不是库的问题,也不是libcurl的使用问题,但是mongoose的在回调中连接判断的MG_EV_CONNECT的错误打印中出现了这样的打印:connect() failed: Permission denied。根据这个打印搜索Android发送网络请求出现权限问题的原因之后很容易发现了是demo app没有给与网络权限。。。
如下是mongoose的http客户端回调:
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
struct http_message *hm = (struct http_message *) ev_data;
switch (ev) {
case MG_EV_CONNECT:
if (*(int *) ev_data != 0) {
char errinfo[1024] = {'\0'};
//这里的打印更加智能,比libcurl提供的错误信息更具体
sprintf(errinfo, "connect() failed: %s", strerror(*(int *) ev_data));
LOGE("%s,FILE:%s,LINE:%d.", errinfo, __FILE__, __LINE__);
g_exit_flag = 1;
}
break;
case MG_EV_HTTP_REPLY:
switch(hm->resp_code) {
case 200:
LOGD("http post success, 200.FILE:%s,LINE:%d.", __FILE__, __LINE__);
break;
case 302:
LOGW("302,FILE:%s,LINE:%d.", __FILE__, __LINE__);
break;
default:
LOGW("response code:%d.FILE:%s,LINE:%d.", hm->resp_code, __FILE__, __LINE__);
break;
}
g_exit_flag = 1;
break;
case MG_EV_CLOSE:
if (g_exit_flag == 0) {
LOGD("Server closed connection.FILE:%s,LINE:%d.", __FILE__, __LINE__);
g_exit_flag = 1;
}
break;
default:
break;
}
}
解决方法
解决方案就是增加app的网络权限即可,我这里选择在app/src/main/AndroidManifest.xml中添加,这个很好搜索到:
<uses-permission android:name="android.permission.INTERNET" />