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. Can be performed on a computer and on an 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 All Foruok, reproduced please specify the source (Http://blog.csdn.net/foruok).

This sample is used for HTTP download, layout manager, edit box, button, Json parsing and other knowledge, we will explain. 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 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 "QT on Android: Text Specific explanation Hello World process." The name of the project is called Ipquery, after creating the project, open the project file, add the network module for the QT variable, because we want to use when we query the IP. As you can see in the following code:

QT       + + core GUI network
Project template for us to generate widget.h/widget.cpp, change the code, first 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 very easy, 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 demo sample, set the IP edit box with the stretch factor of 1, set the stretch factor for the invisible 4th row to 1, because our applet's control is not full of the entire phone screen, so set up on the phone after the display will be more normal.

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 done, let's take a look at the Ipquery class I've implemented. We have 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;}; #endif


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 reference BOK indicating success, 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 (also capable of connecting qnetworkreply readyread ()/downloadprogress ()/error ()/finished () and other signals for more specific download control)

As for the HTTP header settings, Qnetworkrequest provides the SetHeader () method to set common headers such as User-agent/content-type, which are not defined by Qt, and you need to call Setrawheader () method to set, specifically please refer to the HTTP protocol, here no longer elaborate.

Well, now look at what the onreplyfinished () function did:

    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 and see the character encoding, assuming that GBK or GB2312 is converted to Utf-8 (qjsondocument format is required when parsing)
    6. Parsing Json Data

According to the above explanation of the code, everything should be very easy to understand. 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

For more specific instructions, see the API documentation for the Qtextcodec class.

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, which is now well-established, officially supported, and more practical.

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

Our demo sample 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, and can be used to query the data you are interested in using the methods of these classes.

Do a simple science, explain the Json format.

JSON refers to the JavaScript Object notation (JavaScript object Notation), is a lightweight text data interchange format, with self-descriptive narrative, 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, the simplest example of a demo:

{"IP": "36.57.177.187"}
As you can see, a pair of curly braces represents an object, with a colon cut between key and value, and a comma cut between key-value pairs. An object can have more than one key-value pair. The following is a sample of two demos:

{    "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 the array is a series of basic types of values or objects ... So, using nesting is really a very complex data structure, but it's actually not that good to read ...

The Json array in square brackets indicates that the simplest demo sample has only the basic type:

["Baz", NULL, 1.0, 2]

The values within the array are cut with commas.

Look at a demo example of a complex point:

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

The array includes simple string values, as well as objects, including 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 subscript, allowing us to use the QJSO as 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 basics are complete, so let's look at the Json data we'll be working with for IP queries:

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

The key named "Data" within the root object is a set of arrays, and the array has only one object, and the corresponding value of the key named "Location" in the object is the attribution of the IP. Well, it's easy 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 look for the root object named "Data" key corresponding value, see the code:

    Qjsonobject obj = Json.object ();    Qjsonobject::const_iterator it = obj.find ("Data");
Find the corresponding value of 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 explicit:
        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 demo sample is all done. Finally, look at the performance on the computer, Figure 3:

Figure 3 Computer execution

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


My Qt on Android series articles:

    • Qt on Android: text-specific explanation 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 announced 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 Cproject
    • Windows under Qt for Android compiled Android C language executable program
    • Qt on Android:android SDK installation

Qt on android:http download and JSON parsing

Related Article

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.