[Note] http communication related (okhttp3)

connect

Communication is inevitable as long as you run the app on your smartphone or tablet. This time I will summarize http communication. It seems that there are various libraries, but this time I used Okhttp3.

Import from gradle

First, make Okhttp3 available in the app. Therefore, add it to build.gradle (module: app). Choose the version you like. Don't forget to sync after adding.

build.gradle


dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:2.0.2'
    implementation 'com.squareup.okhttp3:okhttp:4.8.0'  //← Add this one line
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Added to manifests

Android doesn't seem to allow app communication by default, so play with AndroidManifests.xml. This time, in addition to INTERNET, I will add ACCESS_NETWORK_STATE, which was necessary to check whether the terminal is connected to the network.

AndroidManifests.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="sample.pack">

<!--Add the bottom two lines-->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:usesCleartextTraffic="true">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

Okhttp3 When the application communicates with the latest version of Android, it seems that an error will occur unless asynchronous processing is performed. To be honest, for beginners, this area was crazy, so the reason for the selection was that I happened to work with Okhttp when I was playing around with it. I will put the finished product on it for the time being.

HttpConnector.java


package sample.pack;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

//Communication related to Web API
public class HttpConnector  {
    //Destination url
    private String urlStr  = "";
    //Response string
    private String respStr = "";
    //JSONArray for response
    private JSONArray respJsonArr = null;
    //For standby processing
    private int Roop_Count;
    private int Timeout_Sec;
    private CountDownLatch countDownLatch;

    //setter and getter
    public String geturlStr(){
        return urlStr;
    }
    public void seturlStr(String urlStr){
        this.urlStr = urlStr;
    }
    //setter and getter(Supports asynchronous processing for response)
    public String getrespStr() throws InterruptedException {
        countDownLatch.await(Timeout_Sec, TimeUnit.SECONDS);
        return respStr;
    }
    public void setrespStr(String respStr){
        countDownLatch.countDown();
        this.respStr = respStr;
    }
    public JSONArray getrespJsonArr()  throws InterruptedException {
        countDownLatch.await(Timeout_Sec, TimeUnit.SECONDS);
        return respJsonArr;
    }
    public void setrespJsonArr(JSONArray respJsonArr){
        countDownLatch.countDown();
        this.respJsonArr = respJsonArr;
    }

    //constructor
    HttpConnector(int Roop_Count, int Timeout_Sec){
        this.Roop_Count = Roop_Count;
        this.Timeout_Sec = Timeout_Sec;
        this.countDownLatch = new CountDownLatch(Roop_Count);
    }

    //Check if the terminal is connected to the network
    public boolean checkConnection(Context context){
        ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkCapabilities info = cm.getNetworkCapabilities(cm.getActiveNetwork());
        return info != null;
    }

    //GET execution
    public void doGet(String urlStr) {
        Request request = new Request.Builder()
                .url(urlStr)
                .get()
                .build();
        conectHttp(request);
    }

    //POST execution
    public void doPost(String url, String postdata) {
        RequestBody body = RequestBody.create(postdata, MediaType.get("application/json; charset=Shift_JIS"));
        final Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        conectHttp(request);
    }

    //Send Request and receive Response
    private void conectHttp(Request request) {
        OkHttpClient client = new OkHttpClient();
        client.newCall(request).enqueue(new Callback() {
            //When communication fails
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
                setrespStr("");
                setrespJsonArr(null);
                Log.d("Status","Failure");
            }
            //If communication is successful
            @Override
            public void onResponse(Call call, Response response) {
                try {
                    setrespStr(response.body().string());
                } catch (IOException | NullPointerException e) {
                    e.printStackTrace();
                    Log.d("Status","Empty");
                    setrespStr("");
                }
                try {
                    setrespJsonArr(new JSONArray(respStr));
                } catch (JSONException e) {
                    e.printStackTrace();
                    Log.d("Status","Empty");
                    setrespJsonArr(null);
                }
            }
        });
    }
}

To be honest, it's a completely unconvincing code, so I'm reluctant, but with my current ability, this was the limit ... To use it, new it, pass the url, and receive the result as a String or JSONArray as a getter. Since it is an asynchronous process, even if you call getter immediately after calling doGet, DoPost, the value is not set, so it does not work as expected. So I used CountDownLatch to get the getter await out when the value was set in the setter. I try to set the number of loops and the timeout time in the constructor, but I feel that it is not very smart around here.

I'm using getters in the first place because I couldn't return the value from onResponse. I thought I'd give up on commonality, but it seems to be used frequently, so it looks like this. By the way, the contents of get and post are almost the same.

checkConnection () literally checks if the terminal is connected to the network. We use this to switch the app online / offline.

Recommended Posts

[Note] http communication related (okhttp3)
[Note] SQLite related
Memo when HTTP communication with Java (OkHttp)