2008-07-26

ブラウザからiアプリを起動

前回、iモードからGPSで計測した位置情報を取得した。
今回は、この情報を引数にブラウザからiアプリを起動しする。
iアプリ起動のためのHTMLは下記のようにを記述する。


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//i-mode group (ja)//DTD XHTML i-XHTML(Locale/Ver.=ja/2.1) 1.0//EN" "i-xhtml_4ja_10.dtd">
<html>
<head>
<title>iPicasa</title>
</head>
<body>
<div style="text-align: center">
<hr style="border-style: solid; border-color: #6AA7DB;" />
<object declare="declare" id="iPicasa.launch" data="JamのURL" type="application/x-jam" >
<param name="lat" value="緯度" />
<param name="lon" value="経度" />
</object>
<a ista="#iPicasa.launch" href="#" >iPicasaを起動</a>
<hr style="border-style: solid; border-color: #6AA7DB;" />
</div>
</body>
</html>


これを次のようにiアプリのソースに記述して、起動時に情報をする。

if (getLaunchType() == IApplication.LAUNCHED_FROM_BROWSER) {
lat = getParameter("lat");
lon = getParameter("lon");
}


これで画像のアップロード時に位置情報を付加することができる。

今回はあわせてiアプリのPOSTの制限である80Kバイトを超えてアップロードできるように以下のようにソースを修正した。iアプリのHTTPヘッダーに状態情報を付加し、プロキシーサーバーで結合してアップロードするようにした。その際、気をつけなくてはいけないのはiアプリでは独自のHTTPリクエストヘッダーを追加できないということ。例えばx-uploadというHTTPヘッダーを追加することはできない。そこでHTTPリクエストヘッダーのContent-Typeに独自に情報を付加することにした。


private void uploadPhoto() throws Exception {
try {
ImageStore imageStore;
try {
imageStore = ImageStore.getEntry(photoId);
} catch (StoreException e) {
throw new Exception("画像を選択してください");
}

waiting.start();

String[] contentType = {"Content-Type", ""};
String[][] requestPropertys = {contentType};


InputStream in = imageStore.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte buff[] = new byte[1024];
int len;
while((len = in.read(buff)) != -1) {
if (out.size() + len > 80 * 1024) {
contentType[1] = "application/x-www-form-urlencoded; upload-status=continue";
String response = new String(post(proxyUrl+"/uploadPhoto.do", requestPropertys, out.toByteArray()));
if (!"OK".equals(response)) {
throw new Exception("アップロードに失敗しました");
}
out.close();
out = new ByteArrayOutputStream();
}
out.write(buff, 0, len);
}

if (out.size() > 0) {
contentType[1] = "application/x-www-form-urlencoded; upload-status=end";
String response = new String(post(proxyUrl+"/uploadPhoto.do", requestPropertys, out.toByteArray()));
if (!"OK".equals(response)) {
throw new Exception("アップロードに失敗しました");
}
out.close();
}
in.close();

} finally {
waiting.end();
}

repaint();
}

synchronized private byte [] post(String url, String[][] requestPropertys, byte [] data)
throws IOException {

HttpConnection conn = null;
OutputStream os = null;
InputStream is = null;
try {
conn = (HttpConnection)(Connector.open(url, Connector.READ_WRITE, true));
conn.setRequestMethod(HttpConnection.POST);

if (requestPropertys != null) {
for (int i=0; i < requestPropertys.length; i++) {
String[] requestProperty = requestPropertys[i];
conn.setRequestProperty(requestProperty[0], requestProperty[1]);
}
}

os = conn.openOutputStream();
os.write(data);
os.close();

conn.connect();

is = conn.openInputStream();

ByteArrayOutputStream response = new ByteArrayOutputStream();
byte buff[] = new byte[1024];
int len;
while((len = is.read(buff)) != -1) {
response.write(buff, 0, len);
}
is.close();

return response.toByteArray();

} finally {
try{
if (os != null) os.close();
if (is != null) is.close();
if (conn != null) conn.close();
} catch (IOException ioe) {}
}
}


今度は実際のこのiアプリを旅行先で使ってみたいと思う。