Android Development: using network technology

Posted by Xiphoid8 on Wed, 19 Jan 2022 20:20:10 +0100

Personal notes sorting

Using network technology

Accessing the network using Http

Using HttpURLConnection

// new a Url object
URL url = new URL("http://www.baidu.com");
// new HttpURLConnection new connection
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// You can set the request mode GET/POST
connection.setRequestMethod("GET");
// Set connection timeout milliseconds
connection.setConnectTimeout(8000);
// Set read timeout milliseconds
connection.setReadTimeout(8000);

// If it is POST, get the output stream
OutputStream os = connection.getOutputStream();
// Pass in post parameter
os.write("username=Zhang San&age=20".getBytes());

// Get input stream
InputStream in = connection.getInputStream();

// Perform byte stream reading related operations

// Close flow
in.close();
os.close();
// Close connection
connection.disconnect();

Using OkHttp

Import dependency

Edit app / build Gradle, add dependency

dependencies {
    compile 'com.squareup.okhttp3:okhttp:3.10.0'
}
use
// Create an instance of OkHttpClient
OkHttpClient client = new OkHttpClient();
// Create a (empty) Request object:
Request request = new Request.Builder().build();
// Or set the url in Builder
Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .build();

// After that, we call the newCall() method of OkHttpClient to create a Call object and call its execute() method to send the request and get the data returned by the server.
Response response = client.newCall(request).execute();

// Get the specific content returned by the Response
String responseData = response.body().string();

// If it is POST, we need to build a Request Body object to store the parameters to be submitted
RequestBody requestBody = new FormBody.Builder()
        .add("username", "admin")
        .add("password", "123456")
        .build();
// Request. The post() method is invoked in Builder and the RequestBody object is passed in.
Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .post(requestBody)
        .build();
// Just call the execute() method to send the request and get the data returned by the server.
get synchronization request
// Create OkHttpClient object
OkHttpClient client = new OkHttpClient.Builder()
    .cache() // Set cache directory (with default)
    .connectTimeout()	// Set connection timeout (with default)
    .cookieJar()	// Read and save cookie s (need to implement by yourself)
    .build();
// Create Request object
Request request = new Request.Builder()
    .url(address)
    .build();
// Send request and get response
Call call = client.newCall(request);
// To send a synchronization request, you need to manually create a sub thread
new Thread(){
    public void run(){
        Response response = call.execute();//Wait for the server to respond (blocking during waiting)
        // Judge whether the response state is normal
        if(response.isSuccessful()){
            // Get the content (text) of the server response
            String str = response.body().string();
        }
    }
}
get asynchronous request
//Send asynchronous get request
private void getAsync(){
    //2. Create request object
    Request request = new Request.Builder()
            .url(Constant.BASE_URL +
                    "LoginServlet?username=Zhang San&password=123")
            .build();
    //3. Send request and get response
    Call call = okHttpClient.newCall(request);
    //Asynchronous requests, no need to manually create child threads
    call.enqueue(new Callback(){
        @Override
        public void onFailure(Call call, IOException e) {
            //Execute on request failure
            e.printStackTrace();
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            //Execute when request is successful
            Log.e("onResponse",Thread.currentThread().getName());
            Log.e("asynchronous get Result of request",response.body().string());
            //The execution is in a child thread, and the user interface cannot be modified directly
            //It can be implemented with the help of Handler

            //How to obtain the data of network files when realizing the file download function
//                InputStream is = response.body().byteStream();
//                FileOutputStream fos = new FileOutputStream(
//                        getExternalFilesDir(null).getAbsolutePath() + "/a.jpg");
        }
    });
    Log.e("okhttp","Asynchronous request sent");
}

Asynchronous post: send text

MIME reference manual (w3school.com.cn)

//Asynchronous post request to send text data
private void postAsync(){
    //2. Create request body object
    RequestBody requestBody = RequestBody.create(
            MediaType.parse("text/plain;charset=utf-8"),	// Select the corresponding MIME according to the upload type
            "username=Zhang San&password=123");
    //3. Create request object
    Request request = new Request.Builder()
            .url(Constant.BASE_URL + "LoginServlet")
            .post(requestBody)//Set the request method to POST
            .build();
    //4. Send request and get response
    Call call = okHttpClient.newCall(request);
    //Asynchronous requests, no need to manually create child threads
    call.enqueue(new Callback(){
        @Override
        public void onFailure(Call call, IOException e) {
            //Execute on request failure
            e.printStackTrace();
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            //Execute when request is successful
            Log.e("onResponse",Thread.currentThread().getName());
            Log.e("asynchronous get Result of request",response.body().string());
            //The execution is in a child thread, and the user interface cannot be modified directly
            //It can be implemented with the help of Handler
        }
    });
}
Asynchronous post: send form
//2. Create request body object
FormBody formBody = new FormBody.Builder()
        .add("username","Zhang San")
        .add("password","123")
        .build();

//3. Create request object
Request request = new Request.Builder()
        .url(Constant.BASE_URL + "LoginServlet")
        .post(formBody)//Set the request method to POST
        .build();
post local select file upload
//File upload
private void uploadFile(){
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, 1);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1 && resultCode == RESULT_OK){
        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(data.getData(),
                null,null,null,null);
        if (cursor.moveToFirst()){
            String imagePath = cursor.getString(cursor.getColumnIndex("_data"));
            //Create request body object
            File file = new File(imagePath);
            RequestBody requestBody = RequestBody.create(
                    MediaType.parse("application/octet-stream"),
                    file);
            //Create request object
            Request request = new Request.Builder()
                    .url(Constant.BASE_URL + "UploadServlet")
                    .post(requestBody)
                    .build();
            Call call = okHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    Log.e("Results of uploading files",response.body().string());
                }
            });
        }
    }
}
post download remote
@Override
public void onResponse(Call call, Response r) throws IOException{
    InputStream is = response.body().byteStream();
    File file = new File(Environment.getExternalStorageDirectory(), 
                        "test.txt");
    FileOutputStream fos = new FileOutputStream(file);
    int len = 0;
    byte[] buf = new byte[128];
    while ((len = is.read(buf)) != -1){
        fos.write(buf, 0, len);
    }
}

Parsing XML formatted data

Pull parsing method

Parsed xml

<apps>
    <app>
        <id>1</id>
        <name>Google Maps</name>
        <version>1.0</version>
    </app>
    <app>

        <id>2</id>
        <name>Chrome</name>
        <version>2.1</version>
    </app>
    <app>
        <id>3</id>
        <name>Google Play</name>
        <version>2.3</version>
    </app>
</apps>

java code

private void parseXMLWithPull(String xmlData) {
    try {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        // Creating an xmlPull parser
        // XmlPullParser parser = Xml.newPullParser();
        XmlPullParser xmlPullParser = factory.newPullParser();
        // Initialize parser
        xmlPullParser.setInput(new StringReader(xmlData));
        // Event type currently read
        int eventType = xmlPullParser.getEventType();
        String id = "";
        String name = "";
        String version = "";
        // If it is not read to the end of the document
        while (eventType != XmlPullParser.END_DOCUMENT) {
            // Gets the name of the current node
            String nodeName = xmlPullParser.getName();
            switch (eventType) {
                // Start label
                case XmlPullParser.START_TAG: {
                    if ("id".equals(nodeName)) {
                        id = xmlPullParser.nextText();
                    } else if ("name".equals(nodeName)) {
                        name = xmlPullParser.nextText();
                    } else if ("version".equals(nodeName)) {
                        version = xmlPullParser.nextText();
                    }
                    break;
                }
                // End tag
                case XmlPullParser.END_TAG: {
                    if ("app".equals(nodeName)) {
                        Log.d("MainActivity", "id is " + id);
                        Log.d("MainActivity", "name is " + name);
                        Log.d("MainActivity", "version is " + version);
                    }
                    break;
                }
                default:
                    break;
            }
            eventType = xmlPullParser.next();

        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  1. First, get an instance of XmlPullParserFactory
  2. Get the XmlPullParser object with this instance
  3. Then you call the setInput() method of XmlPullParser to set the XML data returned by the server, and you can start parsing.
  4. The parsing process is also very simple. You can get the current parsing event through getEventType()
  5. Then continuously parse in a while loop. If the current parsing event is not equal to xmlpullparser END_ Document, indicating that the parsing work has not been completed. After calling the next() method, you can get the next parsing event.
  6. In the while loop, we get the name of the current node through the getName() method. If we find that the node name is equal to id, name or version, we call the nextText() method to obtain the specific content in the node. Every time an app node is parsed, we print the obtained content.

SAX parsing method

Template

public class MyHandler extends DefaultHandler {
    @Override
    public void startDocument() throws SAXException {
        // The startDocument() method is called when XML parsing starts
    }
    @Override
    public void startElement(String uri, String localName, String qName, Attributes
        attributes) throws SAXException {
        // The startElement() method is called when a node is parsed
    }
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        // The characters() method is called when getting the content in the node
    }
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        // The endElement() method will be called when a node is resolved
    }

    @Override
    public void endDocument() throws SAXException {
        // The endDocument() method is called when the entire XML parsing is complete
    }
}

Parse the above XML

public class ContentHandler extends DefaultHandler {
    private String nodeName;
    private StringBuilder id;
    private StringBuilder name;
    private StringBuilder version;
    @Override
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        name = new StringBuilder();

        version = new StringBuilder();
    }
    @Override
    public void startElement(String uri, String localName, String qName, Attributes
        attributes) throws SAXException {
        // Record current node name
        nodeName = localName;
    }
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        // Determine which StringBuilder object to add the content to according to the current node name
        if ("id".equals(nodeName)) {
            id.append(ch, start, length);
        } else if ("name".equals(nodeName)) {
            name.append(ch, start, length);
        } else if ("version".equals(nodeName)) {
            version.append(ch, start, length);
        }
    }
    @Override

    public void endElement(String uri, String localName, String qName) throws
        SAXException {
        if ("app".equals(localName)) {
            Log.d("ContentHandler", "id is " + id.toString().trim());
            Log.d("ContentHandler", "name is " + name.toString().trim());
            Log.d("ContentHandler", "version is " + version.toString().trim());
            // Finally, empty the StringBuilder
            id.setLength(0);
            name.setLength(0);
            version.setLength(0);
        }
    }
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}

call

private void parseXMLWithSAX(String xmlData) {
    try {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        XMLReader xmlReader = factory.newSAXParser().getXMLReader();
        ContentHandler handler = new ContentHandler();
        // Set the instance of ContentHandler to XMLReader
        xmlReader.setContentHandler(handler);
        // Start parsing
        xmlReader.parse(new InputSource(new StringReader(xmlData)));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Parsing JSON format data

Test Json data

[{"id":"5","version":"5.5","name":"Clash of Clans"},
{"id":"6","version":"7.0","name":"Boom Beach"},
{"id":"7","version":"3.5","name":"Clash Royale"}]

Using JSONObject

Convert to Json string
// JSONObject to json string
JSONObject jsonObject = new JSONObject();
jsonObject.put(String name,Object value);
jsonObject.put(String name,Object value);

String jsonStr = jsonObject.toString();

// If it is an array, write a loop to generate JSONObject, and then use the put method of JSONArray object
Read JSON string
private void parseJSONWithJSONObject(String jsonData) {
    try {
        // Read in JSON array string and create a new JSONArray object
        JSONArray jsonArray = new JSONArray(jsonData);
        for (int i = 0; i < jsonArray.length(); i++) {
            // Get json object
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            // Obtain corresponding data
            String id = jsonObject.getString("id");
            String name = jsonObject.getString("name");
            String version = jsonObject.getString("version");
            Log.d("MainActivity", "id is " + id);
            Log.d("MainActivity", "name is " + name);
            Log.d("MainActivity", "version is " + version);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Use Gson

Add dependency

Edit app / build Gradle file, added in the dependencies closure

compile 'com.google.code.gson:gson:2.8.5'
use
Builder sets the Gson property
Gson gson = new GsonBuilder()
    .serializeNulls()	// Allow null export
    .setPrettyPrinting()	// Format s
    .setDateFormat("yyyy-MM-dd")	// Format date output
    .create();	// Generate the configured Gson object
Object to json string
Gson gson = new Gson();
String jsonStr = gson.toJson(Object);
String direct parsing object
jsonData = """{"name":"Tom","age":20}"""

Gson gson = new Gson();
Person person = gson.fromJson(jsonData, Person.class);
Json string is an array of objects
List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Person>>() {}.getType());

Network programming practice

Define an Http tool class

public class HttpUtil {
    // Send Http GET request
    public static String sendHttpRequest(String address) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(address);

            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(8000);
            connection.setReadTimeout(8000);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            InputStream in = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return response.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
    

    /**
     * Encapsulated post request
     *
     * @param uri        url
     * @param parameters Request parameters
     * @return post request
     */
    public static String sendPost(String uri, Map<String, String> parameters) {
        StringBuffer postUrlSB = new StringBuffer(serverUrl + uri);
        if (parameters != null) {
            postUrlSB.append("?");
            Set<Map.Entry<String, String>> entries = parameters.entrySet();
            int count = 1;
            int size = parameters.size();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (count++ < size) {
                    postUrlSB.append(key).append("=").append(value).append("&");
                } else {
                    postUrlSB.append(key).append("=").append(value);
                }
            }
        }
        String postUrl = postUrlSB.toString();
        URL url = null;
        HttpURLConnection connection = null;
        String meg = null;
        try {
            url = new URL(postUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-type", "text/plain;charset=UTF-8");
            InputStream is = connection.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            meg = br.readLine();
            br.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return meg;
    }

}

Open the child thread to receive the return value

Java callback mechanism

1. Define an HttpCallbackListener interface
public interface HttpCallbackListener {
    void onFinish(String response);

    void onError(Exception e);
}
  • The onFinish() method is called when the server successfully responds to our request: the parameters in the onFinish() method represent the data returned by the server.
  • onError() means that when an error occurs during network operation, the parameters in the onError() method are called to record the details of the error.
2. Modify the original HttpUtil class
public class HttpUtil {
    public static void sendHttpRequest(final String address, final
        HttpCallbackListener listener) {
        new Thread(new Runnable() {
            @Override

            public void run() {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL(address);
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    connection.setDoInput(true);
                    connection.setDoOutput(true);
                    InputStream in = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader
                       (in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                    if (listener != null) {
                        // Callback onFinish() method
                        listener.onFinish(response.toString());
                    }
                } catch (Exception e) {

                    if (listener != null) {
                        // Callback onError() method
                        listener.onError(e);
                    }
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }
}

We first add an HttpCallbackListener parameter to the sendHttpRequest() method

A sub thread is opened inside the method, and then the sub thread performs specific network operations.

Data cannot be returned through the return statement in the child thread, so here we pass the data responded by the server into the onFinish() method of HttpCallbackListener. If an exception occurs, we pass the reason of the exception into the onError() method.
Now the sendHttpRequest() method receives two parameters, so we need to pass in the instance of HttpCallbackListener when calling it

HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
    @Override
    public void onFinish(String response) {
        // Here, the specific logic is executed according to the returned content
    }
    @Override
    public void onError(Exception e) {
        // The exception is handled here
    }
});

Using OkHttp

use

public class HttpUtil {
    ...
    public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(address)
                .build();
        client.newCall(request).enqueue(callback);
    }
}

okhttp3.Callback: a callback interface built in OkHttp library

HttpUtil.sendOkHttpRequest("http://www.baidu.com", new okhttp3.Callback() {
@Override
    public void onResponse(Call call, Response response) throws IOException {
        // Get the specific content returned by the server
        String responseData = response.body().string();
    }
    @Override
    public void onFailure(Call call, IOException e) {
        // Exceptions are handled here
    }
});

Topics: Java Android Apache