[ Android Studio ][ HTTP ] サーバクライアント通信２（未完） 

引き続きAndroidでのサーバクライアント通信について書いていく。
特にHTTPに絞って書いていきたい。
未完ではあるがサンプル等参考にして頂けたらと思う。



##HTTP
サーバ-クライアント間でデータの送受信を行うためのプロトコル。
クライアントがリクエストを送り、サーバがレスポンスを返す形式が基本。
リクエスト、レスポンスは**ヘッダ**と**ボディ部**で構成されている。

通信メソッドには
　・クライアントからサーバにデータ送信を求める（**POST**）
　・クライアントがサーバからデータ取得を求める（**GET**）
などがある。

参考URL：http://e-words.jp/w/HTTP.html

現在、私はデータ取得を目的としているのでGETのサンプルを使って話していく。

##実装
サンプルを記事の下にupしているのでそちらを見て頂きたい。
流れは
　クリックイベントでgetメソッドを呼び出し、通信できればサーバから値を取得し返す
といったものである。

サーバとの接続には基本的にtry catchを用いる。

~~~
　　　　　　 try {
                //接続処理
            } catch {
                //例外処理
            } fially {
                //切断処理
            }
~~~

get()中の以下のコードでGETのHTTPメソッドを指定している。

~~~
            httpConn.setRequestMethod("GET");
~~~

URLへの接続はget()中の以下のコードで行い、

~~~
            URL url = new URL(endpoint);　　　　　　　　　　//endpointはURLを引数で渡したもの
            httpConn = (HttpURLConnection) url.openConnection();
            httpConn.connect();
~~~

finally句にある以下のコードで切断する。

~~~
                httpConn.disconnect();
~~~

レスポンスのデータ読み取りに使うInputStreamなどのclose処理もfinally句で行う。

参考URL：https://qiita.com/riversun/items/5f78d47a3d95f857d34f

##接続エラー
サンプルを実行してみると
「Cleartext HTTP traffic not permitted」
というエラーが出た。
どうやらHTTP通信が許可されていないようなので、
https://stackoverflow.com/questions/45940861/android-8-cleartext-http-traffic-not-permitted
こちらの記事を参考に解決を試みる。


そのために
①AndroidManifest.xmlに以下の2行目、5行目のコード

~~~
<manifest ...>
    <uses-permission android:name="android.permission.INTERNET" />　//2行目
    <application
        ...
        android:networkSecurityConfig="@xml/network_security_config"　//5行目
        ...>
        ...
    </application>
</manifest>
~~~

を追加する。

②res/xml/network_security_config.xmlを作成し、
以下のコードをnetwork_security_config.xmlに追加する。

~~~
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">Your URL(ex: 127.0.0.1)</domain>
    </domain-config>
</network-security-config>
~~~

の2つを行う。

これで実行してみると許可はされたようだが、他のエラーが発生…

##NetworkOnMainThreadException
これは「Android3.0からメインスレッド(UIスレッド)からの通信が禁止された」
ことにより発生する。
つまりメインスレッド以外で通信しなければならない。

##まとめ
次回はNetworkOnMainThreadExceptionを解決する方法を調査したい。
以上。


##サンプル

~~~
package com.example;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import java.util.HashMap;
import java.util.Map;


public class MainActivity extends AppCompatActivity {
    String string = "aaaaaaa";
    Map<String,String> headers=new HashMap<String,String>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText editTextResponse = findViewById(R.id.editTextResponse);
        Button button = (Button)findViewById(R.id.buttonGet);
        button.setOnClickListener((View view) -> {
            try {
                String resultStr = get("http://IP adress/searchman/servlet/hello", "UTF-8", null);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }


    public static String get(String endpoint, String encoding, Map<String, String> headers) throws IOException {

        final int TIMEOUT_MILLIS = 0;

        final StringBuffer sb = new StringBuffer("");

        HttpURLConnection httpConn = null;
        BufferedReader br = null;
        InputStream is = null;
        InputStreamReader isr = null;

        try {
            URL url = new URL(endpoint);
            httpConn = (HttpURLConnection) url.openConnection();
            httpConn.setConnectTimeout(TIMEOUT_MILLIS);
            httpConn.setReadTimeout(TIMEOUT_MILLIS);
            httpConn.setRequestMethod("GET");
            httpConn.setUseCaches(false);
            httpConn.setDoOutput(false);
            httpConn.setDoInput(true);

            if (headers != null) {
                for (String key : headers.keySet()) {
                    httpConn.setRequestProperty(key, headers.get(key));
                }
            }
            httpConn.connect();

            final int responseCode = httpConn.getResponseCode();

            if (responseCode == HttpURLConnection.HTTP_OK) {

                is = httpConn.getInputStream();
                isr = new InputStreamReader(is, encoding);
                br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
            } else {
                // If responseCode is not HTTP_OK
            }

        } catch (IOException e) {
            throw e;
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                }
            }
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException e) {
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            if (httpConn != null) {
                httpConn.disconnect();
            }
        }
        return sb.toString();
    }
}

~~~