Android の Camera2 API を使って カメラのプレビュー画面を表示する
の続きです。
下記を参考にした。
LocationManager
GPS を使って位置情報を取得する Android のクラス
参考 : Androidでの簡単な位置情報取得
EXIF
画像及び画像にカメラの機種や撮影時の条件情報や位置情報を埋め込むための規格
Exchangeable Image file Format (交換可能な画像ファイルフォーマット) の略
参考 : wikipedia : Exchangeable image file format
参考 : デジタルスチルカメラ用画像ファイルフォーマット規格: Exif 2.3
参考 : Exifファイルフォーマット
位置情報を取得する権限の設定
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
位置情報を取得する権限を取得する
ユーザが必要とするときに設定できるように
PreferenceFragment を使って設定画面を用意する
詳細は省略する
PreferenceFragment
Preference を設定するためのクラス
preference : PreferenceFragment
位置情報を取得する
// LocationManage を取得する
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// リスナーを登録して開始する
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 3, locationListener);
// リスナー
LocationListener mLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
//変数に格納して、後で使用する
mLocation = location;
}
};
位置情報付きの写真を撮る
まず、写真を撮ってJPEG形式でファイル保存する。
次に、ファイルに EXIF を追加する。
位置情報を EXIF 形式に変換する
これが一番の難物だった。
何をしなければならないのか理解するのに時間を要した。
位置情報の表記にはいろいろな形式がある。
一般的に使われているのは、10進度数(decimal degrees) と呼ばれるものです。
例えば経度は、イギリスのグリニッジを0度とし東西に180度ずつに分割した−180から180の実数です。
Android もこれに従っている。
規格 EXIF 2.3 では、下記のように定義されている。
緯度経度は、度,分,秒 を表す3 つの 有理数 RATIONAL によって表現する
また Androidのreferenceでは、下記のようになっている。
Type is rational.
Format is "num1/denom1,num2/denom2,num3/denom3".
これを最初に読んだときは、??? となった。
デジタルスチルカメラ用画像ファイルフォーマット規格: Exif 2.3
EXIFでは、緯度経度を 度分秒 で表記する60進度数(Sexagesimal Degrees) が採用されている。
有理数 RATIONAL とは、分子/分母 という文字列での表記
例えば、123 なら 123/1と、3.14 なら 314/100 と表記する。
北緯南緯と東経西経は数値とは別のEXIFタグがある。
文字列で "N" "S" "W "E" と表記する。
これは東西南北(East, West, South, North)の英略語なので、
すんなり理解できた。
横浜の緯度 139.64720 経度3535.4515374は、下記のように表記される。
E 139/1,38/1,49932/1000
N 35/1,27/1,5534/1000
プログラムの例
public String convert(double latitude) {
latitude = Math.abs(latitude);
int degree = (int) latitude;
latitude *= 60;
latitude -= (degree * 60.0d);
int minute = (int) latitude;
latitude *= 60;
latitude -= (minute * 60.0d);
int second = (int) (latitude*1000.0d);
StringBuilder sb = new StringBuilder(20);
sb.setLength(0);
sb.append(degree);
sb.append("/1,");
sb.append(minute);
sb.append("/1,");
sb.append(second);
sb.append("/1000");
return sb.toString();
}
public static String latitudeRef(double latitude) {
String str = (latitude<0.0d)?"S":"N";
return str;
}
参考 : stackoverflow : how-to-save-gps-coordinates-in-exif-data-on-android
ExifInterface
EXIFタグを読み書きするための Android のクラス
参考 : Y.A.M の 雑記帳 : Exif
// EXIF 情報を読み込む
File file;
ExifInterface exif = new ExifInterface( file.toString() );
// EXIF 情報に緯度経度情報を追加する
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, ref);
exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, lat);
// EXIF 情報を保存する
exif.saveAttributes();
位置情報を確認する
位置情報付きの写真ファイルを フォトアプリで閲覧する。
情報を見ると地図が表示される。
注意:
フォトアプリで位置情報を確認する時は、
ファイルの保存先は、
外部SDカードの領域(ExternalStorage)であること。
公式サンプル Camera2Basic の流れから
ExternalFilesDir に保存することが多い。
Camera2Basic
ExternalFilesDirでは、写真は表示されるが
位置情報は表示されない。
スクリーンショット
サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Camera216