Android4でインターネット、Webにあるファイルを取得する (HTTPによるファイル取得) - Android

こちらの記事でHTTPによるファイル取得のコードを紹介しましたが、先のコードではAndroid4では"android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork"エラーが発生し動作しません。これは,Android4ではメインスレッドからネットワークにアクセスする処理を実行できなくなったためです。
Android4ではHTTPでファイルを取得する場合はメインスレッドではなくサブスレッドで取得する必要があります。この記事ではサブスレッドを用いた非同期でのHTTPを用いたファイル取得のコードを紹介します。

プロジェクトの作成

Android アプリケーションプロジェクトを作成します。
[New Android Application]ダイアログボックスが表示されますので、以下を設定します。
  • Application Name: "HttpFileGet"
  • Project Name: "HttpFileGet"
  • Package Name: "com.iPentec.httpfileget"
  • Minimum Required SDK: "API 8: Android 2.2 (Froyo)"
  • Target SDK: "API 17: Android 4.2 (Jelly Bean)"
  • Compile With: "API 17: Android 4.2 (Jelly Bean)"
  • Theme: "Holo Light with Dark Action Bar"

パーミッションの設定

AndroidManifest.xmlファイルを編集し、Uses-Permissionに"android.permission.INTERNET"パーミッションを追加します。編集手順はこちらの記事を参照してください。

UI

以下のUIを作成します。フォームにボタンを1つ、TextViewを1つ配置します。


Buttonの"On Click"プロパティを"button1_click"に設定します。

コード

以下のコードを記述します。

MainActivity.java

package com.iPentec.httpfileget;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

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

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }

  public void button1_click(View view){
    String url = "http://www.ipentec.com/default.aspx";
    AsyncHttpRequest task = new AsyncHttpRequest(this);
    task.owner = this;
    task.execute(url);
  }
}
解説
追記部分はボタンがクリックされた際に呼び出される下記メソッドです。
  public void button1_click(View view){
    String url = "http://www.ipentec.com/default.aspx";
    AsyncHttpRequest task = new AsyncHttpRequest(this);
    task.owner = this;
    task.execute(url);
  }

  AsyncHttpRequest task = new AsyncHttpRequest(this);
にてAsyncTaskを継承したカスタムAsyncTaskクラスであるAsyncHttpRequestのインスタンスを作成します。コンストラクタにはAsyncHttpRequestのオーナーとなるアクティビティを与えます。(今回の場合はthis)

execute()メソッドを呼び出しAsyncTaskの非同期処理を開始します。
    task.execute(url);

AsyncHttpRequest .java

AsyncHttpRequestという名称でクラスを追加します。追加したjavaファイルに下記のコードを記述します。
package com.iPentec.httpfileget;

import android.net.Uri;
import android.os.AsyncTask;
import android.app.Activity;
import android.widget.TextView;
import org.apache.http.*;
import org.apache.http.util.*;
import org.apache.http.impl.client.*;
import org.apache.http.client.methods.*;


public class AsyncHttpRequest extends AsyncTask<String, Void, String> {
  public Activity owner;
  private String ReceiveStr;
  
  public AsyncHttpRequest(Activity activity) {
      owner = activity;
  }

  @Override
  protected String doInBackground(String... url) {
    try {
      HttpGet httpGet = new HttpGet(url[0]);
      
      DefaultHttpClient httpClient = new DefaultHttpClient();
      httpGet.setHeader("Connection", "Keep-Alive");
  
      HttpResponse response = httpClient.execute(httpGet);
      int status = response.getStatusLine().getStatusCode();
      if (status != HttpStatus.SC_OK) {
        throw new Exception("");
      } else {
        ReceiveStr = EntityUtils.toString(response.getEntity(), "UTF-8");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "";
  }

  @Override
  protected void onPostExecute(String result) {
      TextView textView2 = (TextView) owner.findViewById(R.id.textView2);
      textView2.setText(ReceiveStr);
  }

}
解説
コンストラクタ
コンストラクタでは与えられたオーナーのアクティビティをクラス変数に保持します。
  public AsyncHttpRequest(Activity activity) {
      owner = activity;
  }
doInBackgoundメソッド
バックグラウンド(サブスレッド)で処理されるコードです。
  @Override
  protected String doInBackground(String... url) {
    try {
      HttpGet httpGet = new HttpGet(url[0]);
      
      DefaultHttpClient httpClient = new DefaultHttpClient();
      httpGet.setHeader("Connection", "Keep-Alive");
  
      HttpResponse response = httpClient.execute(httpGet);
      int status = response.getStatusLine().getStatusCode();
      if (status != HttpStatus.SC_OK) {
        throw new Exception("");
      } else {
        ReceiveStr = EntityUtils.toString(response.getEntity(), "UTF-8");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "";
  }

  HttpGet httpGet = new HttpGet(url[0]);
  httpGet.setHeader("Connection", "Keep-Alive");
  DefaultHttpClient httpClient = new DefaultHttpClient();
  HttpResponse response = httpClient.execute(httpGet);
HttpGetクラスのインスタンスを作成します。作成後ヘッダを設定します。DefaultHttpClientのインスタンスを作成しexecuteメソッドを呼び出し、Httpでのドキュメント取得をします。executeメソッドの第一引数にHttpGetのインスタンスを与えます。

  int status = response.getStatusLine().getStatusCode();
  if (status != HttpStatus.SC_OK) {
    throw new Exception("");
  } else {
    ReceiveStr = EntityUtils.toString(response.getEntity(), "UTF-8");
  }
HttpResponse オブジェクトのgetStatusLine().getStatusCode()メソッドを呼び出しサーバーからのステータスコードを取得します。ステータスコードがOKの場合、HttpResponse オブジェクトのgetEntity()メソッドを呼び出しHttpコンテンツを取得します。取得した情報はReceiveStrクラス変数に保持します。

onPostExecute メソッド
  @Override
  protected void onPostExecute(String result) {
      TextView textView2 = (TextView) owner.findViewById(R.id.textView2);
      textView2.setText(ReceiveStr);
  }
onPostExecuteメソッドは非同期処理の終了時にメインスレッドから呼び出されます。textViewオブジェクトを取得し、doInBackgoundメソッドで取得したHTTPコンテンツをTextViewに表示します。

実行結果

プロジェクトを実行します。下図の画面が表示されます。


ボタンをタップします。HTTPで接続し取得したドキュメントがTextViewに表示されます。

著者
iPentecのプログラマー、最近はAIの積極的な活用にも取り組み中。
とっても恥ずかしがり。
最終更新日: 2024-01-04
作成日: 2013-03-28
iPentec all rights reserverd.