GPS(2)
パーミションチェック
この状態で一通りコーディングができたようにみえますが、このままでは動作しません。アプリにGPS機能を使用する許可(パーミション)が与えられていません。それを設定します。これは、AndroidManifest.xmlに以下の1行を<application>タグの上に記述してください。
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
これで問題ないように見えますが、Android Studio上で、ソースコードのonCreate()を参照すると、以下のように赤波線が表示されエラーとなっています。
赤い電球をクリックすると、「Add permission check」とアドバイスが出てきます。
これをクリックすると、以下のようにソースコードが追加されます。
APIレベル23以降では、Androidのパーミションの方針が変更になり、AndroidManifest.xmlに記述するだけではだめで、パーミションが必要な処理の前にアプリユーザに許可を取っているかどうかのチェックを行うことになっています。許可が取れていない場合は、ユーザに許可してもらうようにダイアログを出す、という仕組みです。今回、赤い電球をクリックして追加されたソースコードは、そのパーミションチェックのためのものです。
では、改めて、パーミションチェックコードを記述しましょう。これは、リスト3の(4)と(5)の間、つまり、requestLocationUpdates()の前に、以下のコードを追記してください。なお、赤い電球をクリックして追加されたソースコードと少し違いますので、注意してください。
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // (1)
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION}; // (2)
ActivityCompat.requestPermissions(this, permissions, 1000); // (3)
return; // (4)
}
まず、(1)のifの判定の中ですが、ActivityCompatクラスのcheckSelfPermission()メソッドを実行しています。このメソッドは、パーミションの状態を数値で返してくれるメソッドです。第1引数としてコンテキストを、第2引数として判定するパーミション名の文字列を指定しますが、これは、Manifest.permissionの定数で指定します。
このメソッドの戻り値は、PackageManagerクラスの定数を使って、許可されていればPERMISSION_GRANTED、そうでなければPERMISSION_DENIEDが返ってきますので、この定数を使って判定しています。
もし、許可が下りていないなら、ユーザに許可を求めるダイアログを出す必要があります。これが(3)で、ActivityCompatクラスのrequestPermissions()メソッドを使います。引数は3個で、第1引数はコンテキストです。
第2引数は、許可を求めるパーミション名の文字列配列です。これを生成しているのが(2)です。(1)同様、Manifest.permissionの定数を使用します。
第3引数は、リクエストコードと呼ばれ、任意の数値を指定します。この数値の使い方は、後述します。
なお、GPS利用の許可が下りていなければ、これ以上の処理は行えないので、returnを記述し、onCreate()メソッドを終了します。これが(4)です。
このように、許可が下りているかのチェックを行い、下りていない場合、requestPermissions()を実行することで、以下のようなダイアログが表示されることになります。
パーミションの付与後
この表示されたダイアログに対して、ユーザが「許可」あるいは「許可しない」を選択します。その時に呼び出されるメソッドがonRequestPermissionsResult()です。今度はこれを記述しておく必要があります。以下のソースコードを追記してください。
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if(requestCode == 1000 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // (1)
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); // (2)
GPSLocationListener locationListener = new GPSLocationListener(); // (3)
if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // (4)
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); // (5)
}
}
まず、このメソッドには3個の引数があります。第1引数がリクエストコードで、先ほどリスト5のrequestPermissions()メソッドの第3引数で指定した値がそのまま渡されます。Activity中の複数箇所でrequestPermissions()を実行する場合、どの場合でもこのonRequestPermissionsResult()メソッドが実行されます。その際、どのrequestPermissions()からの返答なのかを分岐させるためのコードとして、このリクエストコードが利用されます。
第2引数は、同様にrequestPermissions()の第2引数で渡したパーミション文字列配列がそのまま渡されます。
第3引数は、それぞれのパーミションリクエストに対して、ユーザが許可したのかどうかが格納されたint配列です。それぞれのパーミションリクエストに対して、checkSelfPermission()メソッドの戻り値同様、PackageManagerクラスの定数を使って、許可されていればPERMISSION_GRANTED、そうでなければPERMISSION_DENIEDが格納されています。
これらの引数を使って、GPSの許可が下りたかどうかの判定を行っているのが(1)です。
許可された場合の処理が(2)~(5)です。このうち、(2)、(3)、(5)はリスト3の(3)~(5)と同じなので、解説は不要でしょう。ただ、ここでも(5)を記述すると、Android Studio上にパーミションチェック不足のエラーが表示されます。そこで、(4)のifブロックを記述しておきます。ただし、許可が下りていない場合はこれ以上何もできないので、単にreturnと記述しておきます。
