LoginSignup
2
1

More than 3 years have passed since last update.

Android の Camera2 API と LocationManager を使って 位置情報付きの写真を撮る

Last updated at Posted at 2019-07-06

Android の Camera2 API を使って カメラのプレビュー画面を表示する
の続きです。

下記を参考にした。

LocationManager

GPS を使って位置情報を取得する Android のクラス

reference : LocationManager

参考 : Androidでの簡単な位置情報取得

EXIF

画像及び画像にカメラの機種や撮影時の条件情報や位置情報を埋め込むための規格

Exchangeable Image file Format (交換可能な画像ファイルフォーマット) の略

参考 : wikipedia : Exchangeable image file format

参考 : デジタルスチルカメラ用画像ファイルフォーマット規格: Exif 2.3

参考 : Exifファイルフォーマット

位置情報を取得する権限の設定

AndroidManifest.xml
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

位置情報を取得する権限を取得する

ユーザが必要とするときに設定できるように
PreferenceFragment を使って設定画面を用意する

詳細は省略する

PreferenceFragment

Preference を設定するためのクラス

preference : PreferenceFragment

例 : カメラアプリの設定画面
camera_settibg_location.png

位置情報を取得する

    // 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

reference : TAG_GPS_LATITUDE

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 のクラス

reference : ExifInterface

参考 : 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では、写真は表示されるが
位置情報は表示されない。

スクリーンショット

フォトアプリで位置情報付きの写真の情報を見たとき。
camera216_location.png

サンプルコードをgithub に公開した。
https://github.com/ohwada/Android_Samples/tree/master/Camera216

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1