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);
}