ラベル GPS の投稿を表示しています。 すべての投稿を表示
ラベル GPS の投稿を表示しています。 すべての投稿を表示

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アプリを旅行先で使ってみたいと思う。

2008-07-13

写真の場所をGPSで計測して登録

GPS機能を使って写真の場所を計測できるようにしたい。
方法としては以下が考えられる。

1.測地情報を写真に設定し、写真を登録する。
2.測地情報を取得し、その測地情報と写真を登録する。

1についてはPicasa webで測地情報を表示してくれるので、わざわざ何することはない。(ただしPicasa webの設定変更は必要)
2については写真ごとに位置情報を設定しないでいいので、同じ場所で何度も写真を取る場合に効率が良く、こちらを実装してみようと思う。
ただiアプリでGPS機能を使うにはトラステッドiアプリでなければ使えないためiモードとの連携が必要。本当のところドコモには、ユーザー責任を確認のうえ、一般に使える機能として開放してほしい。

iモードからGPSを利用するサービスについては以下を参照

http://www.nttdocomo.co.jp/service/imode/make/content/gps/index.html

次はiモードから位置情報を取得するxhtml


<?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;" />
<a href="/setGeoLocation.do" lcs>現在地をGPSで計測</a>
<hr style="border-style: solid; border-color: #6AA7DB;" />
</div>
</body>
</html>



測地系はgoogleも、ドコモも、世界測地系(wgs84)で同じなのだが、ドコモでは、度は10進法でdd(00~90)、分と秒は60進法でmm、ssとそれぞれ表記し、秒の小数点以下の数値は10進法で三桁表記、googleは少数で表現している。このため、利用するには変換が必要。
以下がJavaによる変換のための関数の例。


private Double setLocation(String loc) {

StringTokenizer st = new StringTokenizer(loc, ".");

double d = Double.parseDouble(st.nextToken());
int sign = d > 0 ? 1 : -1;

d += (Double.parseDouble(st.nextToken())/60.0
+ Double.parseDouble(st.nextToken())/3600.0
+ Double.parseDouble(st.nextToken())/3600000.0)*sign;

return Double.valueOf(d);
}


次回はiアプリを修正して、測地情報を登録できるようにしよう。