2014年2月4日火曜日

androidからAsyncTaskLoaderでHTTP-Post通信をする

Android 3.0からUIスレッドではインターネットへの接続ができなくなった。

そこで、AsyncTaskLoaderを使って、Android 4.0.3でHTTP-Post通信を実行してみる。
HTTP通信には、HttpURLConnectionクラスを使用する。

処理を実現するためには、Androidアプリで下記の3つの部品を実装する。

  • UI処理
  • 通信データ
  • バックグラウンド処理

Androidアプリのマニフェストファイルにインターネット接続のパーミッションを追加すること。

また、サーバ側でも何らかの応答を返す処理を実装する必要がある。

UI処理

アプリケーション実行時に呼び出されるアクティビティ。
ここで通信データを生成し、バックグラウンド処理に渡す。

package net.kuttya.httppostsample2;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;

public class MainActivity extends FragmentActivity implements LoaderCallbacks {

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

// サーバにデータ送信(初期化)
TransData sendData = new TransData();
Bundle args = new Bundle();
sendData.data = "test";
args.putSerializable("data", sendData);
getSupportLoaderManager().initLoader(0, args, this);
}

public Loader onCreateLoader(int id, Bundle args) {
if( null != args ) {
TransData sendData = (TransData) args.getSerializable("data");

return new HttpAccesser(this, sendData);
}
return null;
}

public void onLoadFinished(Loader loader, TransData recvData) {
// AsyncTaskLoaderの処理が終了したら呼び出される
if(null == recvData) {
return;
}
else {

}
}

public void onLoaderReset(Loader arg0) {
// AsyncTaskLoaderが破棄されるときに呼び出される
}
}

通信データ


実際に使用する通信データはメッセージ種別など様々な情報が含まれていると思うが、ここでは簡略化して文字列のみを送受信することにする。

package net.kuttya.httppostsample2;

import java.io.Serializable;

public class TransData implements Serializable {
private static final long serialVersionUID = 1L;

public String data;
}

バックグラウンド処理


ここでHTTP-Post通信を実行する。

package net.kuttya.httppostsample2;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;

public class HttpAccesser extends AsyncTaskLoader {
private final static String SERVER_URL = "http://www.sample.com/index.php";
private final static String ENCODE = "UTF-8";

private TransData mSendData = null; // 送信データ
private HttpURLConnection mHttpConnection = null; // HTTP通信

public HttpAccesser(Context context, TransData sendData) {
super(context);

this.mSendData = sendData;
}

public TransData loadInBackground() {
// ここに非同期処理で実施したい処理を記載する
TransData recvData = null;

recvData = send(mSendData);

return recvData;
}

public void onCanceled(Boolean data) {
// キャンセル処理
}

protected void onStartLoading() {
// 開始処理
forceLoad();
}

public TransData send(TransData sendData) {
OutputStream out = null; // HTTPリクエスト送信用ストリーム
InputStream in = null; // HTTPレスポンス取得用ストリーム
BufferedReader reader = null; // レスポンスデータ出力用バッファ
int retByte = 0;
boolean ret = false;
byte[] sendMessage = null;
byte[] recvMessage = null;
TransData recvData = null;

// 接続初期化
ret = initConnection();
if(false == ret) {
return null;
}

try {
// 送信データ生成
sendMessage = new byte[255];
System.arraycopy(mSendData.data.getBytes(), 0, sendMessage, 0, mSendData.data.length());

// 接続
mHttpConnection.connect();

// データを出力
out = new BufferedOutputStream(mHttpConnection.getOutputStream());
out.write(sendMessage);
out.flush();

// レスポンスを取得
in = new BufferedInputStream(mHttpConnection.getInputStream());
recvMessage = new byte[1024];
retByte = in.read(recvMessage);
if(0 > retByte) {
return null;
}

// 受信データ解析
recvData = new TransData();
ret = analyzeRecvData(recvMessage, recvData);
if(false == ret) {
return null;
}
} catch(Exception e) {
e.printStackTrace();
recvData = null;
} finally {
try {
if(reader != null) {
reader.close();
}
if(in != null) {
in.close();
}
if(out != null) {
out.close();
}
if(mHttpConnection != null) {
mHttpConnection.disconnect();
}
} catch(Exception e) {
recvData = null;
}
}

return recvData;
}

private boolean initConnection() {
// URL指定
URL url;
try {
url = new URL(SERVER_URL);

// HttpURLConnectionインスタンス作成
mHttpConnection = (HttpURLConnection)url.openConnection();

// POST設定
mHttpConnection.setRequestMethod("POST");

// HTTPヘッダの「Content-Type」を「application/octet-stream」に設定
mHttpConnection.setRequestProperty("Content-Type","application/octet-stream");

// URL 接続を使用して入出力を行う
mHttpConnection.setDoInput(true);
mHttpConnection.setDoOutput(true);

// キャッシュは使用しない
mHttpConnection.setUseCaches(false);
} catch (Exception e) {
e.printStackTrace();
return false;
}
finally {
if(mHttpConnection != null) {
mHttpConnection.disconnect();
}
}
return true;
}

private boolean analyzeRecvData(byte[] recvMessage, TransData recvData) {
try {
if(null == recvData)
{
return false;
}

recvData.data = new String(recvMessage, ENCODE);
}
catch(Exception e) {
e.printStackTrace();
return false;
}

return true;
}

}

マニフェストファイルにパーミッション追加


下記のパーミッションを追加する。



サーバ処理


サーバ側はPHPで実装する。
HTTPリクエストを取得し、受信したデータを送り返す。

<?php
// 受信データ格納
$data = file_get_contents("php://input");

echo "POST DATA RECEIVED. data[".$data."]"

?>

0 件のコメント:

コメントを投稿