AndroidでHTTP通信で受信(ダウンロード)するサンプル
Android 4以降対応のための非同期処理
Android 4以降は、ネットワーク処理はAsyncTaskクラスで非同期処理をすることになっている。 MainActivity内のonCreateで直接ネットワーク処理を行うとExceptionが発生する。
推奨される書き方(非同期処理)
import android.os.AsyncTask; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.os.Build; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Task task = new Task(); task.execute("http://www.example.com/index.html"); } private class Task extends AsyncTask<String, Void, String> { protected String doInBackground(String... urls) { // ネットワーク処理をここに記述する return("ネットワークからダウンロードした文字列"); } @Override protected void onPostExecute(String str_recv) { TextView text = (TextView) MainActivity.this.findViewById(ID_TEXTVIEW); text.setText(str_recv); return; } } }
AsynkTaskクラス派生の定義部分で<String, Void, String>
となっている部分は、<Params, Progress, Result>
という各引数の型を指定する部分
Params → protected Result doInBackground(Params args)
Progress → protected void onProgressUpdate(Progress args)
Result → protected void onPostExecute(Result arg)
という、それぞれの引数の型を指定するもので、最も重要なものは、非同期タスク doInBackground の戻り値が、PostExecuteの引数になることである。ここの変数の型は合わせないといけない。
通常は、ネットワークからの受信文字列を引き渡すため、「Result」は「String」になるのだが、Android DevelopersのサンプルではLong intとなっている。
Android 2.xでは、推奨される非同期処理を用いずに次の方法でも「一応」実行は可能。ただし、HTTPリクエスト処理が終了するまでGUIが固まるが…
推奨されない書き方(無理やり制限を回避)
import android.os.StrictMode; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.os.Build; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build()); // ネットワーク処理を直接こに記述する } }
HttpGetを使う場合の例
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.apache.http.*;
import org.apache.http.impl.client.*;
import org.apache.http.client.methods.*;
import org.apache.http.util.*;
public class MainActivity extends ActionBarActivity {
final int ID_TEXTVIEW = 0x1001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
setContentView(layout);
// HTTP受信したデータ(文字列)を表示する部分
TextView text = new TextView(this);
text.setId(ID_TEXTVIEW);
text.setText("しばらくお待ちください");
text.setTextSize((int)(text.getTextSize()*1.3));
layout.addView(text);
Task task = new Task();
task.execute("http://www.example.com/index.html");
}
private class Task extends AsyncTask<String, Void, String> {
protected String doInBackground(String... urls) {
String str_recv = ""; // HTTP受信した文字列を格納する
try{
HttpGet hg = new HttpGet(urls[0]);
DefaultHttpClient dhclient = new DefaultHttpClient();
HttpResponse res = dhclient.execute(hg);
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
str_recv = EntityUtils.toString(res.getEntity());
}
else{
str_recv = "HTTP応答が200ではないため受信失敗";
}
} catch (Exception e) {
str_recv = "HTTP接続に失敗";
}
return(str_recv);
}
@Override
protected void onPostExecute(String str_recv)
{
TextView text = (TextView) MainActivity.this.findViewById(ID_TEXTVIEW);
text.setText(str_recv);
return;
}
}
}
java.net.URL を使う場合
AsyncTask クラス拡張部分の doInBackground のところだけを抜き出して書く。(他の部分は、HttpGetと同じ)
import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; 〜 〜 〜 protected String doInBackground(String... urls) { String str_recv = ""; // HTTP受信した文字列を格納する BufferedReader bf = null; try{ URL url = new URL(urls[0]); URLConnection url_conn = url.openConnection(); // タイムアウト(ミリ秒)の設定 url_conn.setReadTimeout(6000); Object content = url_conn.getContent(); if (content instanceof InputStream) { bf = new BufferedReader(new InputStreamReader( (InputStream)content) ); // 1行毎に読み込んだ文字列を連結する String line; while ((line = bf.readLine()) != null) { str_recv += (line + "\n"); } } else{ str_recv = content.toString(); } } catch (Exception e) { str_recv = "HTTP接続に失敗 : " + e.getLocalizedMessage(); } finally { if(bf != null){ try{ bf.close(); } catch (Exception e) { } } } return(str_recv); }