Qt on android:http download and JSON parsing

Source: Internet
Author: User
Tags emit

Baidu provides a query IP attribution to the open interface, when you enter an IP address in the search box to search, will open by the ip138 provided by the Baidu box application, you can directly enter the IP address within the box query. I looked at the page request and extracted an interface to query IP attribution, using Qt to write a simple IP attribution query application. You can run it on your PC and on your Android phone. The Baidu API is used here and is hereby declared to be used only as a demonstration and cannot be used for commercial purposes.

Copyright Foruok, reproduced Please specify the source (Http://blog.csdn.net/foruok).

This example uses HTTP download, layout manager, edit box, button, Json parsing and other knowledge, we will explain each. Figure 1 is the IP address entered on the phone:

Figure 1 Entering an Ip address

Look at Figure 2, which is the result of clicking on the query button:

Figure 2 IP Attribution Query Results

Okay, now let's go to the program.

The project is based on the QT Widgets Application template creation, select Qwidget as the base class, the specific creation process please refer to the "QT on Android: Graphic detailed Hello world process." The name of the project is called Ipquery, after the project is created, open the project file and add the network module for the QT variable because we want to use it when we query the IP. As shown in the following code:

QT       + + core GUI network
Project template for us to generate widget.h/widget.cpp, modify the code, first to get the interface up. First of all, widget.h file:

#ifndef widget_h#define widget_h#include <QWidget> #include <QPushButton> #include <qlineedit># Include <QLabel> #include "IpQuery.h" class Widget:public qwidget{    q_objectpublic:    Widgets (Qwidget * parent = 0);    ~widget ();p rotected slots:    void Onquerybutton ();    void onqueryfinished (bool bOK, QString IP, QString area);p rotected:    qlineedit *m_ipedit;    Qpushbutton *m_querybutton;    Qlabel *m_arealabel;    Ipquery M_ipquery;}; #endif//Widget_h

See Widget.cpp again:
#include "widget.h" #include <qgridlayout>widget::widget (Qwidget *parent): Qwidget (parent), m_ipquery (this) {C Onnect (&m_ipquery, SIGNAL (finished (bool,qstring,qstring)), this, SLOT (onqueryfinished (bool,qstring,qstring)    ));    Qgridlayout *layout = new Qgridlayout (this);    Layout->setcolumnstretch (1, 1);    Qlabel *label = new Qlabel ("IP:");    Layout->addwidget (label, 0, 0);    M_ipedit = new Qlineedit ();    Layout->addwidget (m_ipedit, 0, 1);    M_querybutton = new Qpushbutton ("Query");    Connect (M_querybutton, SIGNAL (clicked ()), this, SLOT (Onquerybutton ()));    Layout->addwidget (M_querybutton, 1, 1);    M_arealabel = new Qlabel ();    Layout->addwidget (M_arealabel, 2, 0, 1, 2); Layout->setrowstretch (3, 1);}    Widget::~widget () {}void Widget::onquerybutton () {QString IP = m_ipedit->text ();        if (!ip.isempty ()) {m_ipquery.query (IP);        M_ipedit->setdisabled (TRUE);    M_querybutton->setdisabled (TRUE); }}void widget::onqueryfinished (bool bOK, QString IP, QString area) {if (bok) {m_arealabel->settext (area);    } else {M_arealabel->settext ("Oh, something went wrong");    } m_ipedit->setenabled (True); M_querybutton->setenabled (TRUE);}

The interface layout is simple, and we use a qgridlayout to manage the IP address edit box, the Query button, and the Qlabel for displaying the results. Qgridlayout has a addwidget ()/Addlayout () method to add controls or sub-layouts. There are also Setcolumnstretch ()/Setrowstretch () Two methods to set the coefficients for the extrusion of rows and columns. In the example set the IP edit box in the column with the stretch factor of 1, set the stretch factor of the invisible 4th line to 1, because our applet's control is not full of the entire phone screen, so the settings will be more normal on the phone.

I also connected the Qpushbutton signal clicked () to the Onquerybutton () slot in the Widget constructor and called the Ipquery class for IP queries in the slot. The finished () signal of the Ipquery class and the onqueryfinished () slot of the Widget class are also connected, and the results are displayed to the M_arealabel Representative's label when the query is finished.

OK, the Widget is finished, let's take a look at the Ipquery class I've implemented. We added two file ipquery.h/ipquery.cpp to the project. First Look at IpQuery.h:

#ifndef ipquery_h#define ipquery_h#include <QObject> #include <QNetworkAccessManager> #include < Qnetworkreply>class ipquery:public qobject{    q_objectpublic:    ipquery (Qobject *parent = 0);    ~ipquery ();    void query (const QString &IP);    void query (Quint32 IP); signals:    void finished (bool BOK, QString IP, QString area);p rotected slots:    void Onreplyfinished (qnetworkreply *reply);p rivate:    qnetworkaccessmanager M_nam;    QString m_emptystring;};

Two query () functions are declared in the Ipquery class body, each of which accepts QString and uint32 two-format IP addresses. A finished () signal is also declared, with the Boolean parameter BOK indicating success or not, the IP address IP entered, and the returned attribution area. Finally, a slot onreplyfinished () is defined to respond to the finished () signal of the Qnetworkaccessmanager class.

See IpQuery.cpp again:

#include "ipQuery.h" #include <QJsonDocument> #include <QByteArray> #include <QHostAddress> #include <QJsonObject> #include <QNetworkRequest> #include <QJsonArray> #include <QTextCodec> #include <qdebug>ipquery::ipquery (Qobject *parent): Qobject (parent), M_nam (this) {Connect (&m_nam, SIGNAL (finis Hed (qnetworkreply*)), this, SLOT (onreplyfinished (qnetworkreply*)));} Ipquery::~ipquery () {}void ipquery::query (const QString &ip) {QString strURL = QString ("http://opendata.baidu.com/    Api.php?query=%1&resource_id=6006&ie=utf8&format=json "). Arg (IP);    Qurl URL (strurl);    Qnetworkrequest req (URL);    Req.setrawheader ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); Req.setheader (Qnetworkrequest::useragentheader, "mozilla/5.0 (Windows NT 6.1;    WOW64) applewebkit/537.36 (khtml, like Gecko) chrome/35.0.1916.114 safari/537.36 ");    Qnetworkreply *reply = M_nam.get (req); Reply->setprOperty ("string_ip", IP);}    void ipquery::query (Quint32 IP) {qhostaddress addr (IP); Query (addr.tostring ());}    void ipquery::onreplyfinished (qnetworkreply *reply) {reply->deletelater ();    QString strIp = Reply->property ("String_ip"). ToString (); if (reply->error () = Qnetworkreply::noerror) {qdebug () << "Ipquery, Error-" << Reply->error        String ();        Emit finished (false, strIp, m_emptystring);    Return    } int status = Reply->attribute (Qnetworkrequest::httpstatuscodeattribute). ToInt ();    Qdebug () << "ipquery, Status-" << status;        if (status! =) {emit finished (false, strIp, m_emptystring);    Return    } Qbytearray data = Reply->readall ();    QString ContentType = Reply->header (Qnetworkrequest::contenttypeheader). toString ();    Qdebug () << "ContentType-" << contentType;    int charsetindex = Contenttype.indexof ("charset="); if (Charsetindex > 0) {charsEtindex + = 8;        QString charset = Contenttype.mid (Charsetindex). Trimmed (). ToLower (); if (Charset.startswith ("GBK") | | | charset.startswith ("gb2312")) {Qtextcodec *codec = qtextcodec::codecfor            Name ("GBK");            if (codec) {data = Codec->tounicode (data). ToUtf8 ();    }}} int parenthesisleft = Data.indexof (' (');    int parenthesisright = Data.lastindexof (') ');        if (parenthesisleft >=0 && parenthesisright >=0) {parenthesisleft++;    data = Data.mid (Parenthesisleft, parenthesisright-parenthesisleft);    } Qjsonparseerror Err;    Qjsondocument JSON = Qjsondocument::fromjson (data, &err); if (err.error! = qjsonparseerror::noerror) {qdebug () << "Ipquery, JSON error-" << err.errorstring (        );        Emit finished (false, strIp, m_emptystring);    Return    } Qjsonobject obj = Json.object (); Qjsonobject::const_iterator it = obj.find ("Data");   if (It! = Obj.constend ()) {Qjsonarray DataArray = It.value (). ToArray ();        Qjsonobject info = Dataarray.first (). Toobject ();        QString area = Info.find ("location"). Value (). toString ();    Emit finished (true, strIp, area); }}

The implementation of Ipquery is straightforward, initiating a network request to parse the returned Json data.

I connect Qnetworkaccessmanager's finished () signal and Ipquery's onreplyfinished () slot in the Ipquery constructor.

The key functions are two query (const qstring&) and onreplyfinished (qnetworkreply*). Look at the query () function, which demonstrates the basic steps for HTTP download using Qnetworkaccessmanager:

    1. Construct requests using qnetworkrequest (including URLs and HTTP headers)
    2. Call Qnetworkaccessmanager's Get () method to submit a download request
    3. Using Qnetworkreply, save some properties related to the download, SetProperty () can generate properties dynamically, and property () can take the attributes out
    4. Response to Qnetworkaccessmanager's finished () Signal processing network feedback (can also be connected to qnetworkreply readyread ()/downloadprogress ()/error ()/finished () and other signals for more detailed download control)

As for the HTTP header settings, Qnetworkrequest provides the SetHeader () method to set common headers such as user-agent/content-type and so on, which Qt does not define, you need to call Setrawheader () method to set, please refer to the HTTP protocol, here is no longer detailed.

All right, now look at what the onreplyfinished () function has done:

    1. Remove the properties set when submitting the download request (IP address in string format)
    2. Call Qnetworkreply::error () to check for errors
    3. Call Qnetworkreply::attribute () or HTTP status code to see if the HTTP protocol itself is an error (such as 404/403/500, etc.)
    4. Reading data
    5. Call the Qnetworkreply::header () method to get the Content-type header, view the character encoding, or convert to Utf-8 if it is GBK or GB2312 (qjsondocument format is required when parsing)
    6. Parsing Json Data

According to the above explanation of the code, it should be easy to understand everything. This explains the next 5 or 62 slightly more complex steps.

To convert GBK encoded text data to Utf-8, follow these steps:

    1. Use Qtextcodec static method Codecforname () to obtain a Qtextccodec instance of the specified encoding
    2. Call Qtextcodec's Tounicode () method to convert to a Unicode-encoded QString object
    3. Call QString's ToUtf8 () method to convert to Utf-8 format

See the API documentation for the Qtextcodec class for more detailed instructions.

Finally, we say Json data parsing. Starting with Qt 5.0, the support for Json has been introduced, and you may need to use open source Cjson or Qjson before, and now it's better, officially supported, to be more practical.

Qt can parse JSON data in textual form, use the Qjsondocument::fromjson () method, or parse the JSON data compiled into binary, using Frombinarydata () or Fromrawdata (). corresponding, ToJson () and Tobinarydata () can be converted in reverse.

Our example calls the Fromjson () method to parse Json data in the form of text. Fromjson () accepts Json data in the UTF-8 format and also accepts a Qjsonparseerror object pointer to output errors that may be encountered. Once the Fromjson () method returns, the JSON data is parsed into various JSON objects defined by Qt, such as Qjsonobject/qjsonarray/qjsonvalue, and so on, you can use the methods of these classes to query the data you are interested in.

Do a simple science, explain the Json format.

JSON refers to JavaScript Object notation (JavaScript objects Notation), which is a lightweight text data interchange format that is self-descriptive and easy to understand. Although it is derived from the JavaScript language, it is independent of language and platform.

There are two types of data structures in Json:

    1. A collection of key-value pairs, commonly called objects.
    2. An ordered list of values, often called an array.

The Json object is represented in curly braces in the simplest example:

{"IP": ""}
As you can see, a pair of curly braces represents an object, separated by a colon between key and value, and the Key-value pair is separated by commas. An object can have more than one key-value pair. The following is an example of two:

{    "status": "0",    "T": "1401346439107"}

There are six basic types of values in Json: boolean, floating-point number, String, array, object, null. At this point you think of nesting, yes: A value can be an object, and the object can be expanded to continue nesting; A value can be an array, and an array is a series of basic types of values or objects ... So, using nesting can really represent a very complex data structure, but it's actually not that good to read ...

The Json array is represented in square brackets, the simplest example of which is only the base type:

["Baz", NULL, 1.0, 2]

The values within the array are separated by commas.

See an example of a complex point:

[  "name": "Zhangsan",   {    "age": +,    "phone": "13588888888",    "other": ["Xian", NULL, 1.0,]  } ]

The array contains simple string values and objects, which contain key-value pairs, arrays, ...

In Qt, Qjsonvalue represents the value in Json, it has isdouble ()/Isbool ()/IsNull ()/IsArray ()/IsObject ()/isstring () Six methods to determine the type of the value, then there is t Methods such as odouble ()/Tobool ()/ToInt ()/ToArray ()/Toobject ()/toString () are used to convert qjsonvalue to a specific type of value.

The Qjsonobject class represents an object whose find () method can find value based on key, and keys () can return a list of all keys, and it also overloads the "[]" operator, which accepts a string-formatted key as the subscript, allowing us to use QJSO as if using an array. Nobject.

The Qjsonarray class represents an array, which has a size ()/at ()/first ()/last () and so on, and, of course, it also overloads the "[]" operator (the Accept-shaped array subscript).

OK, so far, the basic knowledge is complete, to see our IP query to process the Json data bar:

{    "status": "0",    "T": "1401346439107",    "Data": [      {        "location": "Anhui Province Suzhou Telecom",        "Titlecont": " IP address Query ",        " ORIGIP ":" ",        " Origipquery ":" ",        " Showlamp ":" 1 ",        " Showlikeshare ": 1,        " Shareimage ": 1,        " extendedlocation ":" ",        " Originquery ":" ",        " TPLT ":" IP ","        ResourceID ":" 6006 ",        " Fetchkey ":" ",        " appinfo ":" "," role_id ": 0," disp_ Type ': 0      }    ]}

The key named "Data" in the root object is a set of arrays, and there is only one object in the array, and the value corresponding to the key named "Location" in the object is the attribution of the IP. Well, it's very simple to look at the code in this format:

    Qjsonparseerror err;    Qjsondocument JSON = Qjsondocument::fromjson (data, &err);
These two lines generate Qjsondocument objects based on the data. Then we'll find the value corresponding to the root object named "Data", see the code:

    Qjsonobject obj = Json.object ();    Qjsonobject::const_iterator it = obj.find ("Data");
Find the value corresponding to data, use ToArray () to Qjsonarray, use the first () method of Qjsonarray to take the initial element, use Toobject () to Qjsonobject, and then use the Find () method to " Location "looks for key and turns the result into a String. A long story, the code is more clear:
        Qjsonarray DataArray = It.value (). ToArray ();        Qjsonobject info = Dataarray.first (). Toobject ();        QString area = Info.find ("location"). Value (). toString ();        Emit finished (true, strIp, area);

All right, this example is all explained. Finally, look at the performance of the computer, Figure 3:

Figure 3 Computer operation

Copyright Foruok, reproduced Please specify the source (Http://blog.csdn.net/foruok).

My Qt on Android series articles:

    • Qt on Android: text-to-detail Hello world whole process
    • Introduction to the development of Qt 5.2 for Android under Windows
    • Qt for Android deployment process Analysis
    • QT on Android: output qt Debug information to Logcat
    • Qt on ANDROID:QT 5.3.0 released for Android improvement instructions
    • Qt on Android episode 1 (translation)
    • Qt on Android episode 2 (translation)
    • Qt on Android episode 3 (translation)
    • Qt on Android episode 4 (translation)
    • Qt for Android compiled pure C project
    • Windows under Qt for Android compiled Android C language executable program
    • Qt on Android:android SDK installation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.