美文网首页android实用技术编程算法Android JNI
【NDK】Android在JNI中请求网络并解析JSON数据展示

【NDK】Android在JNI中请求网络并解析JSON数据展示

作者: ldlywt | 来源:发表于2017-04-03 10:28 被阅读1449次

如果不知道在CMake中依赖第三方库,请看我以前的文章:

http://www.jianshu.com/p/5f29fd671750

需求

我们在安卓中使用网络请求并解析json很容易,有很多很方便的框架,如:okhttp,retrofit,android-async-http,volley。
但是如果我们的需求是:不能把请求网络的协议url暴露出去,并且把直接返回的JSON阉割部分字段再抛出去,例如做SDK开发。
虽然我们可以使用java的混淆,但是如果多用点心,混淆过的jar还是可以反编译出来的。(使用抓包工具Fidder请忽略,o(╯□╰)o)
此时,在JNI中使用C/C++请求网络是很不错的选择。

第三方库

curl:C中请求网络很好的库,项目地址:

https://github.com/curl/curl

jsoncpp:c++中解析json很方便的库,项目地址:

https://github.com/open-source-parsers/jsoncpp

工程结构

  • cpp:与C有关的代码
  • cpp/include:第三方库依赖的头文件
  • JniUtils.cpp/JniUtils.h:我封装的常用JNI工具类
  • native-lib.cpp:与java交互的类
  • web_task.cpp/web_task.h:对curl库第二次封装
工程结构.png

curl请求网络

身边的一个大神把libcurl封装下,封装源码太长了,放在github上,封装后请求网络就变得非常容易,几行代码搞定,返回的json数据在jsonResult中。

GET请求

//GET请求
string url = "http://www.weather.com.cn/data/sk/101280601.html";
WebTask task;
task.SetUrl(url.c_str());
task.SetConnectTimeout(5);
task.DoGetString();
if (task.WaitTaskDone() == 0) {
    //请求服务器成功
    string jsonResult = task.GetResultString();
}

POST请求

//POST请求,url随便举例的
string url = "http://www.weather.com.cn/user/add";
WebTask task;
task.SetUrl(url.c_str());
task.SetConnectTimeout(5);
task.AddPostString("username", username);
task.AddPostString("password", password);
task.AddPostString("email", email);
if (task.WaitTaskDone() == 0) {
    //请求服务器成功
    string jsonResult = task.GetResultString();
}

几行代码搞定网络请求,是不是有种使用安卓框架的感觉。

jsoncpp解析json

接下来该使用jsoncpp解析json数据,请求天气网址返回的json如下:

{
    "weatherinfo": {
        "city": "深圳", 
        "cityid": "101280601", 
        "temp": "21", 
        "WD": "南风", 
        "WS": "1级", 
        "SD": "31%", 
        "WSE": "1", 
        "time": "17:05", 
        "isRadar": "1", 
        "Radar": "JC_RADAR_AZ9755_JB", 
        "njd": "暂无实况", 
        "qy": "1014", 
        "rain": "0"
    }
}
  • 如果是json根节点,如下:
//根节点
Json::Value weatherinfo = root["weatherinfo"];
string js1 = weatherinfo["city"].asString();
LOGI("根节点解析: %s\n", js1.c_str());
  • 如果字段是string,如下:
    string city = root["weatherinfo"]["city"].asString();
  • 如果字段是int,如下:
    int year= root["year"].asInt();

回到上面的例子,附上解析的代码:

Json::Reader reader;
Json::Value root;
//从字符串中读取数据
if (reader.parse(jsonResult, root)) {
    /*//根节点
    Json::Value weatherinfo = root["weatherinfo"];
    string js1 = weatherinfo["city"].asString();
    LOGI("根节点解析: %s\n", js1.c_str());*/
    //读取子节点信息
    string city = root["weatherinfo"]["city"].asString();
    string temp = root["weatherinfo"]["temp"].asString();
    string WD = root["weatherinfo"]["WD"].asString();
    string WS = root["weatherinfo"]["WS"].asString();
    string time = root["weatherinfo"]["time"].asString();
    string result = "城市:" + city + "\n温度:"+ temp+ "\n风向:" + WD + "\n风力:"+ WS + "\n时间:" + time;

结束

如果你不想自己生成libcurl.a和libjsoncpp.a文件,可以直接使用我工程的。
此外对网络库libcurl封装的代码也放在github上。
工程中的JniUtils.h和JniUtils.cpp是我封装的,功能如下:

  • 在JNI中打印Android的log
  • 将java的string转化成c的字符串
  • 将C字符串转java字符串

https://github.com/ldlywt/JniHttp_Sample

才是开始做NDK开发,也才开始写blog,请赏我个star,感激不尽!

更多jsoncpp使用

Json文件的生成和解析
C++ 解析Json——jsoncpp
C++的Json解析库:jsoncpp和boost
C++ JSON文件的读取和生成

相关文章

网友评论

  • 阿信yinX:Post的示例代码是不是漏了调用task.DoGetString();?
  • 90c3d81776fb:最新版本的androidstudio编译时需要x84_64等不同架构平台的libcurl.a和libjsoncpp.a库,你那里有编译好的嘛,有的话能否上传下,不胜感激!!!
    ldlywt:@Kenny_cffd 我已经一年把没做JNI了,你到网上搜下
  • 254e43316a07:使用Post走到 task.GetResultString();就崩溃,提示Fatal signal 11 (SIGSEGV), code 1,
  • AlanFu:谢谢。
  • 爬着的蜗牛:这个不考虑线程间的并发切换这些吗?
  • 81c17c76d562:没有新开线程请求网络没问题吗?
  • 梦遥不可及:post不崩了,但是提交不上去啊,抓包显示的是get的,下面也没任何参数
  • 梦遥不可及:使用给出的post代码,崩溃什么问题?走到task.WaitTaskDone()这个会崩溃
  • c3eceb89c8c5:网络请求抓个包就出来了,不知道费劲藏到jni里有什么用
    GLee9507:@矿泉汽水 代理环境下禁止访问网络٩(ˊvˋ*)و
    ldlywt:@皮卡丘0812 有时老大就是这么要求,有啥办法呢,o(╯□╰)o

本文标题:【NDK】Android在JNI中请求网络并解析JSON数据展示

本文链接:https://www.haomeiwen.com/subject/dcvnottx.html