JavaでAndroidアプリ 位置情報取得を取得する(後編)

位置情報の取得をプログラミングしていくよ

みなさん、こんにちは!

今年のGWは世間では10連休、「どこ行っても混むから」という大義名分で引きこもれる連休ラブなあらたまです。

さて今日は 前回に引き続きAndroidアプリ開発での位置情報についてお話ししたいと思います!

おさらい

前回では、 Androidアプリの位置情報の取得には「Google Location Service API」というものをつかうこと。

つかうときは下記の6つの手順で使うこと。

設定

  • マニフェストファイルに位置情報を利用することを追記
  • ビルドファイルの依存ライブラリを追加

プログラミング

  • 位置情報の利用が許可されているかチェック
  • LocationClientクラスのインスタンスを生成
  • 位置情報の取得方法を指定
  • 位置情報の追跡開始

そして、最初の「設定」の2手順についてお話しましたね。

今回はいよいよプログラミングを行っていきたいと思います。

位置情報の利用が許可されているかチェック

まずは権限のチェックから作りこんでいきましょう。
位置情報の使用をユーザーが許可してくれているかを確認します。

アクティビティファイルを開きます。

アクティビティに下記の青色部分を参考にプログラミングしてみてください。

package jp.artm.android.locationserviceapp;

// ... 省略 ...

import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 位置情報取得開始
        startUpdateLocation();
    }

    /**
     * 位置情報取得開始メソッド
     */
    private void startUpdateLocation() {
        // 位置情報取得権限の確認
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // 権限がない場合、許可ダイアログ表示
            String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
            ActivityCompat.requestPermissions(this, permissions, 2000);
            return;
        }

        // ここに位置情報の取得開始処理をあとで書きます。
    }

    /**
     * 許可ダイアログの結果受取
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if(requestCode == 2000 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 位置情報取得開始
            startUpdateLocation();
        }
    }
}

onCreateメソッド

アクティビティ生成時に呼び出されるメソッドです。
startUpdateLocationメソッドを呼び出しています。

startUpdateLocationメソッド

位置情報の利用がユーザーに許可されているかチェックをしています。
許可されていない場合は、requestPermissionsメソッドを使ってユーザーに許可を求めるダイアログを表示しています。

onRequestPermissionsResultメソッド

ユーザーに許可を求めるダイアログで、ユーザーが「許可」か「拒否」を選択した後に呼び出されます。
ユーザーに位置情報の利用が許可された場合はもう一度startUpdateLocationメソッドを呼び出しています。

Location Client インスタンスの生成

続いて位置情報を取得するためのクラスのインスタンスを生成します。

下記の赤色部分を参考にプログラミングしてみてください。

// ... 省略 ...

import com.google.android.gms.location.*;

public class MainActivity extends AppCompatActivity {

    private FusedLocationProviderClient fusedLocationClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // LocationClientクラスのインスタンスを生成
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        // 位置情報取得開始
        startUpdateLocation();
    }

    // ... 省略 ...

}

位置情報の取得方法を指定

続いて位置情報の取得間隔など、取得方法を指定します。
取得方法の指定にはLocation Requestクラスを使用します。

下記の赤色部分を参考にプログラミングしてみてください。

// ... 省略 ...

public class MainActivity extends AppCompatActivity {

    // ... 省略 ...

    /**
     * 位置情報取得開始メソッド
     */
    private void startUpdateLocation() {
        // 位置情報取得権限の確認
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // 権限がない場合、許可ダイアログ表示
            String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
            ActivityCompat.requestPermissions(this, permissions, 2000);
            return;
        }

        // 位置情報の取得方法を設定
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setInterval(10000);       // 位置情報更新間隔の希望
        locationRequest.setFastestInterval(5000); // 位置情報更新間隔の最速値
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // この位置情報要求の優先度

    }

    // ... 省略 ...

}

setInterval

位置情報の取得間隔の希望値です。
あくまで希望値なので、かならずしもこの値どおりになるわけではありません。

setFastestInterval

上記のとおりsetIntervalはあくまで希望値ですので、あまり早すぎる感覚で取得されたりすると アプリの動作が重くなったり、予想外の動作をしてしまう可能性もありますよね。

そのため、「これ以上早くは取得したくない」という指定がsetFastestIntervalです。

setPriority

どのくらい優先して位置情報を取得するか(電力消費を犠牲にしても詳細な位置情報を取得する、位置情報が荒くても良いので電力消費を少なくする、など) を指定します。

位置情報の追跡開始

いよいよ位置情報の取得を開始部分です。
下記の青色部分を参考にプログラミングしてみてください。

// ... 省略 ...

import android.location.Location;

// ... 省略 ...

public class MainActivity extends AppCompatActivity {

    // ... 省略 ...

    /**
     * 位置情報取得開始メソッド
     */
    private void startUpdateLocation() {
        // 位置情報取得権限の確認
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // 権限がない場合、許可ダイアログ表示
            String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
            ActivityCompat.requestPermissions(this, permissions, 2000);
            return;
        }

        // 位置情報の取得方法を設定
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setInterval(10000);       // 位置情報更新間隔の希望
        locationRequest.setFastestInterval(5000); // 位置情報更新間隔の最速値
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // この位置情報要求の優先度

        fusedLocationClient.requestLocationUpdates(locationRequest,  new MyLocationCallback(), null);
    }

    /**
     * 位置情報受取コールバッククラス
     */
    private class MyLocationCallback extends LocationCallback {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult == null) {
                return;
            }
            // 現在値を取得
            Location location = locationResult.getLastLocation();
        };
    }

    // ... 省略 ...
}

requestLocationUpdatesメソッド

Location ClientクラスのrequestLocationUpdatesメソッドで位置情報の取得を開始しています。

位置情報の監視が介されると、LocationRequestに応じた間隔で第二引数で渡したLocationCallbackクラスが呼び出されます。

取得した情報の表示

あとは動きがわかりやすいように、 取得した情報を画面に表示するようにしておきましょう。

下記の赤色部分を参考にプログラミングしてみてください。

// ... 省略 ...

public class MainActivity extends AppCompatActivity {

    // ... 省略 ...

    /**
     * 位置情報受取コールバッククラス
     */
    private class MyLocationCallback extends LocationCallback {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult == null) {
                return;
            }
            // 現在値を取得
            Location location = locationResult.getLastLocation();
            // 画面に表示
            TextView view = findViewById(R.id.text_view);
            view.setText("緯度:" + location.getLatitude() + " 経度:" + location.getLongitude());
        };
    }

    // ... 省略 ...

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"

    <!-- ... 省略 ... -->

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!-- ... 省略 ... -->

</android.support.constraint.ConstraintLayout>

これでプログラミングは完了です!

動かしてみる

それでは、動かしてみましょう!「▶」ボタンを押してアプリを起動してください。

位置情報が表示されました!

AVDでは位置情報を手動で自由に変えてアプリの動作を確認することができます。

「・・・」ボタンをクリックします。

「Latitude」が緯度、「Longitude」が経度です。
値を変更して「SEND」をクリックします。

画面に表示される位置情報もちゃんと変更後の値になりましたっ。