Android
Kotlin

GoogleMapsみたいにダイアログから位置情報を直接ONしたい

目的

位置情報OFF時、OSの位置情報設定画面に遷移させるのではなく、GoogleMapsみたいにダイアログを表示してアプリから位置情報を直接ONできるようにしたい

対応内容

参考にさせていただいたサイトを元に以下のユーティリティクラスを作成しました。

ユーティリティクラス
/**
 * 位置情報ユーティリティ
 */
object LocationUtils {

  private val TAG = LocationUtils::class.simpleName!!
  val REQUEST_LOCATION = 20

  /**
   * 位置情報ON/OFFの確認
   *
   * @param activity アクティビティ
   */
  fun checkLocation(activity: FragmentActivity) {
    val locationManager = activity.getSystemService(LOCATION_SERVICE) as LocationManager
    if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
      // 位置情報がOFFの場合、位置情報を許可するダイアログを表示
      requestLocation(activity)
    }
  }

  /**
   * 位置情報ON/OFFの確認
   *
   * @param activity アクティビティ
   */
  private fun requestLocation(activity: FragmentActivity) {
    val locationRequest = LocationRequest.create()
    locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
    val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
    // 位置情報OFFの場合、常に許可ダイアログを開くようにする
    builder.setAlwaysShow(true)
    val task = LocationServices.getSettingsClient(activity).checkLocationSettings(builder.build())
    task.addOnCompleteListener {
      try {
        // 位置情報がON、何もしない
        val response = task.getResult(ApiException::class.java)
        Log.d(TAG, response.toString())
      } catch (exception: ApiException) {
        when (exception.statusCode) {
          LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
            // 位置情報がOFF、位置情報許可ダイアログを表示
            val resolvable = exception as ResolvableApiException
            resolvable.startResolutionForResult(activity, REQUEST_LOCATION)
          } catch (sendIntentException: SendIntentException) {
            Log.d(TAG, sendIntentException.message)
          } catch (classCastException: ClassCastException) {
            Log.d(TAG, classCastException.message)
          }
          LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
            // 位置情報が無効?
          }
          else -> {
            // その他
          }
        }
      }
    }
  }

  /**
   * 位置情報許可/不許可の結果確認
   *
   * @param requestCode requestCode
   * @param resultCode resultCode
   * @param intent intent
   * @return true:許可 false:不許可
   */
  fun isRequestLocationonResult(requestCode: Int, resultCode: Int, intent: Intent): Boolean {
    var result = false
    when (requestCode) {
      REQUEST_LOCATION ->
        when (resultCode) {
          Activity.RESULT_OK -> {
            result = true
          }
          Activity.RESULT_CANCELED -> {
          }
          else -> {
          }
        }
    }
    return result
  }
}
利用例(hogeActivity)
  private fun initLocation() {
    LocationUtils.checkLocation(this)
  }

  /**
   * onActivityResult
   *
   * @param requestCode requestCode
   * @param resultCode resultCode
   * @param intent intent
   */
  override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent) {
    when (requestCode) {
      LocationUtils.REQUEST_CODE -> if (!LocationUtils.isRequestLocationResult(requestCode, resultCode, intent)) {
        // TODO
      } else -> {
        super.onActivityResult(requestCode, resultCode, intent)
      }
    }
  }

参考

【Android】インテントからLocationを有効にする(和歌山トイレマップで遊んでみる 4)