位置情報の取得 と RuntimePermission 周りの備忘メモ

基本的な実装編

や * [Android] FusedLocationProviderApi を使って位置情報を取得 あたり

実装してて悩んだ処

LocationRequestの取得周期の最小値

  • LocationRequest で取得周期を決める
    • setIntervalの 最小値って 1000ミリ秒 *1

ぐらいが限界って話をどっかでみたけど公式値がでてこないんですよね。。

requestLocationUpdatesがタイミングによって動かないことがある

locationClient.requestLocationUpdates を呼ぶ前に

map.setMyLocationEnabled(true);

が有効になっていないと、listenerが動かない(汗

ネットワークが繋がっていないと動かない

機内モードとかで確認が可能です

  • GPSのみで有一動く
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

も結局のところ、mGoogleApiClient の onConnect (通信) が前提だからのようです*2

最初は、端末内のGooglePlay開発者サービスと接続するだけの認識だったんですが

Googleのサーバーと通信しにいっちゃってて、オフラインだと動かせない

というのが現状なのかなと*3


位置情報をOFFにしたり、初期の端末Onlyになっている状態を修正する

この方法だと、OKを押すと自動的に

  • 位置情報ON
  • 高精度設定

に変更されます

まあ、上記のページに記載されている通り 高精度にしないと

LocationServices.FusedLocationApi.requestLocationUpdates(locationClient, request, _locationListener);

がまともに動かないので

  • DeviceOnly
    • 端末の最後の位置情報の関数しか動かない
  • Battery saving
    • 基地局Wifiスポットの位置情報になるので、殆ど変化しない

は正直設定する意味があるのか辺りは悩ましい話なのかも


Android6の shouldShowRequestPermissionRational の話

自分も結構ハマりました・・。これ・・・。

  1. Permissionを拒否
  2. Permissionを拒否+次回から確認しないチェック
    1. ここで確認しないチェックを入れて拒否
    2. 二度と聞いてこなくなる
      1. => アプリの詳細画面の権限から変更を要求

直接Permission変更画面を呼べないので 設定画面を読んでやるしか無いというお話.

shouldShowRequestPermissionRationale は1個の権限しか指定できず。。

  • FINE_LOCATION + COARSE_LOCATION with PRIORITY_HIGH_ACCURACY
    • 位置情報をまともに取得するモード(GPSWiFi or 3G フル活用。
    • 数十mの位置精度らしい
    • 高い電池の使用量 と表示される
  • COARSE_LOCATION with PRIORITY_BALANCED_POWER_ACCURACY
    • buttery saveの場合の推奨設定?
    • 位置の精度が数km程度らしい。
    • WiFi測位(従来の NETWORK_PROVIDER)よりも悪いらしい
    • 低い電池の使用量 と表示される

とはなるようで、

リクエストとしては

  • FINE_LOCATION と COARSE_LOCATIONは必須。ただし同一位置情報グループなのでまとめてリクエスト
// 結果の受け取り
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch(requestCode) {
            case 1000://LOCATIONのコールバックID等
                // 使用が許可された
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                   Log.d("debug","checkSelfPermission true");
                   nextActivity();
                } else if (!ActivityCompat.shouldShowRequestPermissionRationale(this,permissions[0]))
                    Toast toast = Toast.makeText(this, "設定画面の権限を手動で変更してください", Toast.LENGTH_SHORT);
                    toast.show();
                    startApplicationManagementActivity();
                    finish();
                } else {
                    Toast toast = Toast.makeText(this, "アプリケーションを使うには権限を有効にする必要があります。", Toast.LENGTH_SHORT);
                    toast.show();
                    finish();
                }
                break;
        }
    }
 
    //アプリの設定画面を開く
    private void startApplicationManagementActivity() {
        String packageName = getPackage();
        Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
        intent.setData(Uri.parse("package:" + packageName));
        
        startActivity(intent);
    }

に書いている通り、直接権限画面まで開けないのは正直死んでるんだよなー

正直凄く片手落ちな気がしますし。。

関数パラメータ値のメモ

ココらへんは後で調べて追記する予定。

低い電池使用量ってのは魅力なんですよね。。(汗

LocationRequestのパラメータ設定

関数名 説明
setInterval (long millis) ミリ秒単位で位置情報更新の間隔を設定します。
setFastestInterval (long millis) ミリ秒単位で位置情報更新の正確な間隔を設定します。
setNumUpdates (int numUpdates) 位置情報の更新数を設定します。
setPriority (int priority) 位置情報取得要求の優先順位を設定します。

LocationRequest.setPriorityの設定値

関数名                説明
PRIORITY_BALANCED_POWER_ACCURACY 誤差約100m以内の精度
PRIORITY_HIGH_ACCURACY できる限り正確な位置
PRIORITY_LOW_POWER 誤差約10km以内の精度。電力消費を抑えられる。
PRIORITY_NO_POWER 消費電力なしで可能な限り最高の精度

RuntimePermissionテストの話

たしかに、端末によって

の階層位置がかなり深い/位置がわかりづらい ものがあるので、確かに必須かも

8/25 追記

上記 6系の実機で色々試してみたけど、結局うまく動かなかった。

何ででしょうね。。なんか設定があるのでしょうか。

revoke できないと言われるんですが。。*4

その他

位置情報にしないとBLEとかもダメらしい。

けっきょくGoogle様の新機能使うには

GooglePlay開発者サービスみたいに フルフルで使うしか無いのかー

というのが実感

*1:setFastestIntervalも合わせて同じ値を設定する必要ありと記載されているところもある

*2:オフラインだとここに到達しない

*3:DeviceOnlyの設定自体があんまり意味が無い気がする。

*4:permissionエラー辺り。ROOT取っていること前提?