Android x Google Play Services #3 Location API で位置情報を取得する

2013.06.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Fused location provider な位置情報取得 API

Location API を使うとアプリに位置情報の機能をつけることができます。Google Play Services の Location API の位置情報取得には以下のような特徴があります。

シンプルな API

高精度にするか電力効率を優先するか、好みに応じてカスタマイズすることができます。ざっくりとした位置だけ把握したい場合は GPS を使わないでおく、などといった使いかたができます。

すぐに利用できる

すぐに直近の位置情報を取得することができます。

電力効率が良い

位置情報を取得する場所やセンサー情報を判断し、一番電力消費が少ないベストな方法を自動で選択して取得してくれます。

幅広いニーズに対応

バックグラウンドで定期的に位置情報を取得する場合など、さまざまなニーズに対応することができます。

ということで今回は位置情報の取得 (Fused location provider) を試してみたいと思います!

位置情報を取得する

まず AndroidManifest.xml にパーミッションを追加します。GPS を使いたい場合は ACCESS_FINE_LOCATION を使い GPS を使いたくない場合は ACCESS_COARSE_LOCATION を指定します。ちなみに ACCESS_FINE_LOCATION を指定すると ACCESS_COARSE_LOCATION も自動で許可されます。

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

次に Activity.onCreate()LocationClient インスタンスを生成します。このクラスが直接扱うクラスになります。第一引数は Context で、第二引数は API の接続ステータスを返す GooglePlayServicesClient.ConnectionCallbacks をセットし、第三引数には接続失敗時のコールバックである GooglePlayServicesClient.OnConnectionFailedListener をセットします。

mLocationClient = new LocationClient(this, mConnectionCallbacks, mOnConnectionFailedListener);

GooglePlayServicesClient.ConnectionCallbacks は以下のように実装します。実装する必要があるのは接続時に呼び出される onConnected() メソッドと切断時に呼び出される onDisconnected() メソッドです。

@Override
public void onConnected(Bundle bundle) {
    Toast.makeText(self, "onConnected", Toast.LENGTH_LONG).show();
}
@Override
public void onDisconnected() {
    Toast.makeText(self, "onDisconnected", Toast.LENGTH_LONG).show();
}

GooglePlayServicesClient.OnConnectionFailedListeneronConnectionFailed() メソッドだけ実装します。

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Toast.makeText(self, "onConnectionFailed", Toast.LENGTH_LONG).show();
}

ここまでで LocationClient のインスタンス化ができました。あとは LocationClient.connect() で API に接続し、 LocationClient.getLastLocation() で位置情報を取得します。以下では onStart() で API に接続して onStop() で切断しています。

@Override
protected void onStart() {
    super.onStart();
    mLocationClient.connect();
}
@Override
protected void onStop() {
    super.onStop();
    mLocationClient.disconnect();
}
private void getCurrentLocation() {
    if (mLocationClient.isConnected()) {
        Location location = mLocationClient.getLastLocation();
        TextView tv = (TextView) findViewById(R.id.message);
        tv.setText(location.toString());
    } else {
        Toast.makeText(self, "not connected", Toast.LENGTH_LONG).show();
    }
}

ここまでのコードをすべてまとめると以下のような感じになります。なお、前回解説した Google Play Services の API が使えるか確認する実装は割愛しています。

LocationActivity.java

package jp.classmethod.android.sample.locationapi;

import android.app.Activity;
import android.location.Location;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;

public class LocationActivity extends Activity {

    private final LocationActivity self = this;
    private LocationClient mLocationClient;

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

        // LocationClient の生成
        mLocationClient = new LocationClient(this, mConnectionCallbacks, mOnConnectionFailedListener);

        // 現在地を取得するボタン
        findViewById(R.id.current_location_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getCurrentLocation();
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        // APIに接続
        mLocationClient.connect();
    }

    @Override
    protected void onStop() {
        super.onStop();
        // APIから切断
        mLocationClient.disconnect();
    }

    private void getCurrentLocation() {
        // 接続されているときだけ現在地を取得
        if (mLocationClient.isConnected()) {
            Location location = mLocationClient.getLastLocation();
            TextView tv = (TextView) findViewById(R.id.message);
            tv.setText(location.toString());
        } else {
            Toast.makeText(self, "not connected", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 接続時・切断時のコールバック.
     */
    private GooglePlayServicesClient.ConnectionCallbacks mConnectionCallbacks = new GooglePlayServicesClient.ConnectionCallbacks() {
        @Override
        public void onConnected(Bundle bundle) {
            Toast.makeText(self, "onConnected", Toast.LENGTH_LONG).show();
        }
        @Override
        public void onDisconnected() {
            Toast.makeText(self, "onDisconnected", Toast.LENGTH_LONG).show();
        }
    };

    /**
     * 接続失敗時のコールバック.
     */
    private GooglePlayServicesClient.OnConnectionFailedListener mOnConnectionFailedListener = new GooglePlayServicesClient.OnConnectionFailedListener() {
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {
            Toast.makeText(self, "onConnectionFailed", Toast.LENGTH_LONG).show();
        }
    };
    
}

実行すると以下のように現在地を取得することができます!

current_location

まとめ

ということで現在位置の取得を試してみました。高精度にするか、消費電力を抑えるかはアプリによって異なってくるのでベストな指定をしておきたいところですね。

参考