[ Android Studio ] [ HTTP ] 非同期処理　サーバクライアント通信3

引き続きHTTP通信でデータを取得する方法を述べていく。

前回は「NetworkOnMainThreadException」がでたところで記事を終えたので、
その解決法について述べる。

##NetworkOnMainThreadException
Android3.0から
メインスレッド(UIスレッド)からの通信が禁止されたため起こるエラー。

簡単に言うと、
HTTP通信を**非同期処理**で行わなければならない。

##非同期処理実装の流れ

まず、
非同期処理用クラス（ AsyncTaskを継承 ）を新たに作成する。
オーバーライドしたdoInBackground()へURLを渡し、HTTP通信を行う。
doInBackground()の返り値はonPostExecute()の引数に渡され、
そこでHTTP接続後の処理を行う。
＊具体的な処理は一番下ののサンプルを見て頂きたい。

~~~MyAsync.java
public class MyAsync extends AsyncTask<String, Void, String> {
    private Activity mActivity;
    MainActivity mainActivity = new MainActivity();

    public MyAsync(Activity activity) {
        mActivity = activity;
    }
    public interface ResponseListener {
        void onResponseDataReceived(String responseData);
    }

    //引数paramsにURLを渡す
    @Override
    protected String doInBackground(String... params) {
        //HTTP通信処理
        //サーバから取得したデータをString型変数に格納
        return String型変数; //onPostExecuteの引数に渡す
    }

    @Override
    public void onPostExecute(String string) {
        //Text表示処理
    }
}
~~~

呼び出し側は以下の通りにして、非同期処理を実行する。
onCreate内でMyAsyncを呼び出すだけである。

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

        new MyAsync(this).execute("URL"); //非同期処理呼び出し
    }
~~~

これでエラーを解消することができた。
参考URL：http://shiro-16.hatenablog.com/entry/2014/03/25/004856

##まとめ
かなり時間がかかったが、何とかHTTP通信を成功させることができた。
サーバクライアント通信について3つの記事を書いてきたが、
以下がポイントである。

①**HTTP通信は非同期処理が必要**。（Android 3.0以降）
　忘れるとNetworkOnMainThreadExceptionで怒られる。
②**HTTP通信を許可するための記述の追加が必要**。
　忘れるとCleartext HTTP traffic not permittedで怒られる。
　こちらを参考にしてください。
　https://qiita.com/QiitaD/items/ba4124d791c39a82783a

以上のことを気を付けて頂きたい。

##サンプル（AsyncTask.java）
このサンプルはTextViewにより、サーバから取得したXMLソースコードを表示するものである。
レイアウトファイルに表示用のTextViewがなければ何も起こらないので注意していただきたい。

~~~java
public class MyAsync extends AsyncTask<String, Void, String> {
    private Activity mActivity;

    public MyAsync(Activity activity) {
        mActivity = activity;
    }
    public interface ResponseListener {
        void onResponseDataReceived(String responseData);
    }

    @Override
    protected String doInBackground(String... params) {

        HttpURLConnection connection = null;
        StringBuilder src = new StringBuilder();
        try {
            URL url = new URL(params[0]);
            connection = (HttpURLConnection) url.openConnection();   //HTTP通信処理開始

            connection.setRequestMethod("GET");
            connection.addRequestProperty("User-agent", "Android");
            connection.addRequestProperty("Accept-Language", Locale.getDefault().toString());
            connection.setInstanceFollowRedirects(false); 
            connection.setDoInput(true);                  
            connection.setDoOutput(false);
            connection.setConnectTimeout(20000);          
            connection.setReadTimeout(30000);
        
            //データ取得
            InputStream is = connection.getInputStream();
            while (true) {
                byte[] line = new byte[1024];
                int size = is.read(line);
                if (size <= 0)
                    break;
                src.append(new String(line, "utf-8"));
            }

            if (is != null){
                is.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            connection.disconnect(); //HTTP通信終了
        }
        return new String(src);  //取得データを返す
    }

    //引数に渡されたデータをTextViewで表示
    public void onPostExecute(String string) {
        TextView textView = (TextView) mActivity.findViewById(R.id.response);
        textView.setText(string);
    }
}

~~~