FusedLocationProviderApiで位置情報を取得してGoogle Location Web ApiでJsonを取る分かりやすいまとめ

#FusedLoacationProviderApiで位置情報を取得してGoogle Location Web ApiでJsonを取る

Activityに処理の起点を実装
位置情報を取得できたら
https://maps.googleapis.com/maps/api/place/search/json
をコールして周辺のスポットを取得する
jsonの中身をダイアログに表示。

以上のサンプルです。

FusedLoacationProviderApiのリスナー実装でソースの見通しがわかりづらくなるので、
別クラスに分離しました。

##Acitivityの実装

```java:メンバー変数の定義
public class MainActivity extends AppCompatActivity  {
    int PLACE_PICKER_REQUEST = 1;
    private final int REQUEST_PERMISSION = 10;
    private Handler mHandler;
    private OneShotLocationManager mLocationManager;
    private String mJsonData = "";
```

```java:onCreateでの処理
(前略)
        mHandler = new Handler();
        mLocationManager = new OneShotLocationManager(getApplicationContext()) {
            @Override
            public void onStopApi(int lastResponseCode) {
                if(lastResponseCode != OneShotLocationManager.RES_SUCCESS)
                    if (mLocationManager.getLocation() == null){
                    return;
                }

                //通信スレッド生成
                (new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Location location = mLocationManager.getLocation();

                        if(location == null){
                            return;
                        }

                        double lat = location.getLatitude();
                        double lng = location.getLongitude();

                        StringBuilder urlStrBuilder = new StringBuilder("https://maps.googleapis.com/maps/api/place/search/json");
                        urlStrBuilder.append("?location=" + lat + "," + lng);
                        urlStrBuilder.append("&sensor=true&rankby=distance&key="+getString(R.string.google_maps_key));

                        URL url = null;
                        try {
                            url = new URL(urlStrBuilder.toString());
                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                            return;
                        }

                        // APIを叩いてJSONをダウンロード
                        HttpURLConnection connection = null;
                        try {
                            connection = (HttpURLConnection) url.openConnection();
                            connection.setRequestMethod("GET");
                            connection.connect();

                            BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream());

                            int bytesRead = -1;
                            byte[] buffer = new byte[1024];

                            mJsonData = "";

                            while ((bytesRead = inputStream.read(buffer)) != -1) {
                                mJsonData += new String(buffer);
                            }
                            inputStream.close();

                            mHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    new AlertDialog.Builder(MainActivity.this)
                                            .setTitle("title")
                                            .setMessage(
                                                    mJsonData)
                                            .setPositiveButton("OK", null)
                                            .show();
                                }
                            });


                        } catch (IOException e) {
                            e.printStackTrace();
                        }


                    }
                })).start();
            }
        };

       //ボタン押下で位置情報を取得開始する。
       Button btnPlaceApiWeb = (Button) findViewById(R.id.btn_place_web);
        btnPlaceApiWeb.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //パーミッションチェック
                if(Build.VERSION.SDK_INT >= 23){
                    if(!mLocationManager.checkLocationPermission()){
                        requestLocationPermission();
                        return;
                    }
                }
                //API呼ぶ
                if(OneShotLocationManager.RES_SUCCESS != mLocationManager.startApi()){
                    if(mLocationManager.getLastResponseCode() == OneShotLocationManager.RES_PERMISSION){
                        requestLocationPermission();
                        return;
                    }
                }
            }
        });
```

```java:イベントハンドリング周りとパーミッションの要求処理

    // 許可を求める
    private void requestLocationPermission() {
        if (!ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
            Toast toast = Toast.makeText(this, "ロケーションを許可しないと実行できません。", Toast.LENGTH_SHORT);
            toast.show();
        }

        ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION);
    }

    // 結果の受け取り
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == REQUEST_PERMISSION) {
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Toast toast = Toast.makeText(this, "ロケーションを許可しないと実行できません。", Toast.LENGTH_SHORT);
                toast.show();
            }
        }
    }



    @Override
    protected void onStart() {
        super.onStart();

    }

    @Override
    protected void onStop() {
        super.onStop();
        mLocationManager.stopApi();

    }
```

##実装するリスナー等をまとめたクラス

これをActivityに書くサンプルが多すぎてわけわからんとなるので、別クラスにまとめる

```java:OneShotLocationManager.java
package com.example.y_hoshi.maptest.mng;

import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 位置情報を１度だけ取得する
 * 関連のAPIのリスナーわかりやすく分離して実装したクラス
 * UIスレッドでインスタンスを作る。
 * Created by y_hoshi on 2016/10/28.
 */

abstract public class OneShotLocationManager implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener, LocationListener {
    public static final int RES_CONNECTION_FAILD = -2;
    public static final int RES_PERMISSION = -1;
    public static final int RES_SUCCESS = 0;

    private int lastResponseCode = 0;
    public int getLastResponseCode(){return lastResponseCode;};

    Context mContext;
    private final int REQUEST_PERMISSION = 10;
    private GoogleApiClient mGoogleApiClient;

    private FusedLocationProviderApi fusedLocationProviderApi;

    private LocationRequest locationRequest;
    private Location location;
    public Location getLocation(){return location;};
    private long lastLocationTime = 0;
    private Handler mHandler;

    //通信が終わった時の通知用
    protected abstract void onStopApi(int lastResponseCode);

    public OneShotLocationManager(Context context) {
        mContext = context;
        mHandler = new Handler();

        locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(1000);
        locationRequest.setFastestInterval(16);

        fusedLocationProviderApi = LocationServices.FusedLocationApi;

        mGoogleApiClient = new GoogleApiClient.Builder(mContext)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        if (ActivityCompat.checkSelfPermission(mContext,android. Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Location currentLocation = fusedLocationProviderApi.getLastLocation(mGoogleApiClient);

        if (currentLocation != null && currentLocation.getTime() > 20000) {
            location = currentLocation;

            String log = "onConnected ---------- \n";
            log += "lat=" + String.valueOf(location.getLatitude()) + "\n";
            log += "lon=" + String.valueOf(location.getLongitude()) + "\n";
            log += "accuracy=" + String.valueOf(location.getAccuracy()) + "\n";
            log += "altitude=" + String.valueOf(location.getAltitude()) + "\n";
            log += "time=" + String.valueOf(location.getTime()) + "\n";
            log += "speed=" + String.valueOf(location.getSpeed()) + "\n";
            log += "bearing=" + String.valueOf(location.getBearing()) + "\n";
            Log.d("location", log);


        } else {
            try {
                fusedLocationProviderApi.requestLocationUpdates(mGoogleApiClient, locationRequest, (LocationListener) this);
                Executors.newScheduledThreadPool(1).schedule(new Runnable() {
                    @Override
                    public void run() {
                        fusedLocationProviderApi.removeLocationUpdates(mGoogleApiClient,(LocationListener) OneShotLocationManager.this);
                    }
                }, 60000, TimeUnit.MILLISECONDS);


            } catch (Exception e) {
                e.printStackTrace();
                lastResponseCode = RES_PERMISSION;
                onStopApi(getLastResponseCode());
                return;
            }
        }

        if (currentLocation == null){
            return;
        }

        lastResponseCode = RES_SUCCESS;
        stopApi();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d("locationMng", "onConnectionSuspended------------- \n" + "i=" + i + "\n");

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.d("locationMng", "onConnectionFaild------------- \n" + "errorCode=" + connectionResult.getErrorCode() + "\n");
        lastResponseCode = RES_CONNECTION_FAILD;
        onStopApi(lastResponseCode);
    }

    @Override
    public void onLocationChanged(Location location) {
        lastLocationTime = RES_CONNECTION_FAILD;
        lastLocationTime = location.getTime() - lastLocationTime;

        String log = "onLocationChanged-------------------- \n";
        log += "lat=" + String.valueOf(location.getLatitude()) + "\n";
        log += "lon=" + String.valueOf(location.getLongitude()) + "\n";
        log += "accuracy=" + String.valueOf(location.getAccuracy()) + "\n";
        log += "altitude=" + String.valueOf(location.getAltitude()) + "\n";
        log += "time=" + String.valueOf(location.getTime()) + "\n";
        log += "speed=" + String.valueOf(location.getSpeed()) + "\n";
        log += "bearing=" + String.valueOf(location.getBearing()) + "\n";
        log += "lastLocationTime= " + String.valueOf(lastLocationTime) + " msec \n";
        Log.d("locationMng", log);
    }

    public int startApi(){
        Log.d("locationMng", "start-------------");
        if(!checkLocationPermission()){
            lastResponseCode = RES_PERMISSION;
            return lastResponseCode;
        }

        mGoogleApiClient.connect();
        lastResponseCode = RES_SUCCESS;
        return RES_SUCCESS;
    }

    public void stopApi(){
        mGoogleApiClient.disconnect();
        onStopApi(getLastResponseCode());
        return;
    }

    /**
     * 必要なパーミッションのチェックをして拒否しているならパーミッションをリクエストする
     */
    public boolean checkLocationPermission() {

        int permissionCheck = ActivityCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION);
        //許可されていない
        if (permissionCheck != PackageManager.PERMISSION_GRANTED){
            return false;
        }

        return true;
    }


}
```