引き続きHTTP通信でデータを取得する方法を述べていく。
前回は「NetworkOnMainThreadException」がでたところで記事を終えたので、
その解決法について述べる。
##NetworkOnMainThreadException
Android3.0から
メインスレッド(UIスレッド)からの通信が禁止されたため起こるエラー。
簡単に言うと、
HTTP通信を非同期処理で行わなければならない。
##非同期処理実装の流れ
まず、
非同期処理用クラス( AsyncTaskを継承 )を新たに作成する。
オーバーライドしたdoInBackground()へURLを渡し、HTTP通信を行う。
doInBackground()の返り値はonPostExecute()の引数に渡され、
そこでHTTP接続後の処理を行う。
*具体的な処理は一番下ののサンプルを見て頂きたい。
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を呼び出すだけである。
@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がなければ何も起こらないので注意していただきたい。
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);
}
}