AndroidからDropboxのcore APIを使って,dropboxから写真をダウンロードせずにジオタグと撮影時刻を取得する方法です.

Dropboxの写真から高速にジオタグを取得する

拙作のAndroidアプリ GPXフォトサーチ への機能追加の関係で,
  • Dropboxにアップしてある写真をダウンロードせずに,ジオタグ(GPS緯度経度)と撮影時刻を取得する

ということをやりましたので,その方法を説明します.

Android版Core APIの機能

用途的に, sync API より core API の方が適してそうですが, Android版のcore APIをダウンロードしても,それらしき機能はありませんでした.

Core APIの本体

それで,Core APIの本体(HTTPインターフェイス)を調べたところ,/metadata にそれらしき機能がありました.

リクエストパラメータのinclude_media_infoをtrueにすると, 対象が画像ファイルの場合はレスポンスにphoto_infoが含まれるとのことです.

そしてphoto_infoには,

  • lat_long : GPS緯度経度
  • time_taken : 撮影時刻

が含まれます.これは使えそうです!

ということで,Android版Core APIのソース(DropboxAPI.java)を元にして, このphoto_infoに対応した呼び出しメソッドとentityクラスを作ってみました.
(説明用なのでエラーチェックはかなり省いています.適宜入れてください)

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.DropboxAPI.Entry;
import com.dropbox.client2.RESTUtility;
import com.dropbox.client2.RESTUtility.RequestMethod;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxUnlinkedException;
import com.dropbox.client2.session.AppKeyPair;

public static PhotoEntry metadataWithPhotoInfo(DropboxAPI<AndroidAuthSession> api,
		String path, int fileLimit, String hash,
		boolean list, String rev) throws DropboxException {

	AndroidAuthSession session = api.getSession();

	String[] params = {
			"file_limit", String.valueOf(fileLimit),
			"hash", hash,
			"list", String.valueOf(list),
			"rev", rev,
			"locale", session.getLocale().toString(),
			"include_media_info", "true"
	};

	String url_path = "/metadata/" + session.getAccessType() + path;

	Map<String, Object> dirinfo =
			(Map<String, Object>) RESTUtility.request(RequestMethod.GET,
			session.getAPIServer(), url_path, DropboxAPI.VERSION, params, session);

	return new PhotoEntry(dirinfo);
}

public static class PhotoEntry extends Entry {
	public String takenTime;
	public Double lat;
	public Double lon;
	public List<PhotoEntry> contentsPhoto;

	public PhotoEntry(Map<String, Object> map) {
		super(map);

		Object json_photo_info = map.get("photo_info");
		if (json_photo_info != null && json_photo_info instanceof JSONObject) {
			takenTime = (String)((JSONObject)json_photo_info).get("time_taken");

			Object json_lat_long = ((JSONObject)json_photo_info).get("lat_long");
			if (json_lat_long != null && json_lat_long instanceof JSONArray) {
				lat = (Double)((JSONArray) json_lat_long).get(0);
				lon = (Double)((JSONArray) json_lat_long).get(1);
			}
		}

		Object json_contents = map.get("contents");
		if (json_contents != null && json_contents instanceof JSONArray) {
			contentsPhoto = new ArrayList<PhotoEntry>();
			for (Object entry: (JSONArray)json_contents) {
				if (entry instanceof Map) {
					contentsPhoto.add(new PhotoEntry((Map<String, Object>) entry));
				}
			}
		} else {
			contentsPhoto = null;
		}
	}
}
使い方は,Android用Core APIの DropboxAPIクラス のmetadata()メソッドとほぼ同じです.

戻り値がEntryではなく新クラスPhotoEntryになっており,今回の追加属性を取り出せます.

参考

kamolandをフォローしましょう


© 2017 KMIソフトウェア