Android 3.0からUIスレッドではインターネットへの接続ができなくなった。
そこで、AsyncTaskLoaderを使って、Android 4.0.3でHTTP-Post通信を実行してみる。
HTTP通信には、HttpURLConnectionクラスを使用する。
処理を実現するためには、Androidアプリで下記の3つの部品を実装する。
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."]"
?>