[Android ๊ธฐ์ดˆ] 17. ์‚ฌ์šฉ์ž ์œ„์น˜ ์–ป๊ธฐ
๋ฐ˜์‘ํ˜•

 

 

 

 

 

์œ„์น˜ ์ธ์‹ ์•ฑ ๋นŒ๋“œ  |  Sensors and location  |  Android Developers

์œ„์น˜ ์ธ์‹ ์•ฑ ๋นŒ๋“œ ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ณ ์œ ํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ์œ„์น˜ ์ธ์‹ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ ์‚ฌ์šฉ์ž๋Š” ์–ด๋””์—๋‚˜ ๊ธฐ๊ธฐ๋ฅผ ํœด๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์— ์œ„์น˜ ์ธ์‹ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋”์šฑ

developer.android.com

 

 

1) ์œ„์น˜ ์ ‘๊ทผ ๊ถŒํ•œ

 

์‚ฌ์šฉ์ž์˜ ์œ„์น˜๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•œ 3๊ฐ€์ง€ ๊ถŒํ•œ

  • android.permission.ACCESS_COARSE_LOCATION
    - ์™€์ดํŒŒ์ด๋‚˜ ๋ชจ๋ฐ”์ผ ๋ฐ์ดํ„ฐ(๋˜๋Š” ๋‘˜ ๋‹ค)๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ๊ธฐ์˜ ์œ„์น˜์— ์ ‘๊ทผํ•˜๋Š” ๊ถŒํ•œ
    - ๋„์‹œ์—์„œ 1๋ธ”๋ก ์ •๋„์˜ ์˜ค์ฐจ ์ˆ˜์ค€
  • android.permission.ACCESS_FINE_LOCATION
    - ์œ„์„ฑ, ์™€์ดํŒŒ์ด, ๋ชจ๋ฐ”์ผ ๋ฐ์ดํ„ฐ ๋“ฑ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์‚ฌ์šฉํ•ด ์ตœ๋Œ€ํ•œ ์ •ํ™•ํ•œ ์œ„์น˜์— ์ ‘๊ทผํ•˜๋Š” ๊ถŒํ•œ
  • android.permission.ACCESS_BACKGROUND_LOCATION
    - ์•ˆ๋“œ๋กœ์ด๋“œ 10(API ๋ ˆ๋ฒจ 29) ์ด์ƒ์—์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์—์„œ ์œ„์น˜์— ์ ‘๊ทผํ•˜๋Š” ๊ถŒํ•œ

 

์•ˆ๋“œ๋กœ์ด๋“œ ๊ถŒํ•œ ์„ค์ • ๋ฐ ํš๋“ ๋ฐฉ๋ฒ•

 

 

 

์œ„์น˜ ์ •๋ณด ์•ก์„ธ์Šค ๊ถŒํ•œ ์š”์ฒญ  |  Sensors and location  |  Android Developers

์ด ํŽ˜์ด์ง€๋Š” Cloud Translation API๋ฅผ ํ†ตํ•ด ๋ฒˆ์—ญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์œ„์น˜ ์ •๋ณด ์•ก์„ธ์Šค ๊ถŒํ•œ ์š”์ฒญ ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ •๋ฆฌํ•˜๊ธฐ ๋‚ด ํ™˜๊ฒฝ์„ค์ •์„ ๊ธฐ์ค€์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ถ„๋ฅ˜ํ•˜์„ธ์š”. ์‚ฌ์šฉ์ž ๊ฐœ์ธ ์ •๋ณด๋ฅผ ๋ณดํ˜ธ

developer.android.com

 

1. ๋งค๋‹ˆํŽ˜์ŠคํŠธ์— ๊ถŒํ•œ ์ถ”๊ฐ€

<manifest ... >
  <!-- Always include this permission -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <!-- Include only if your app benefits from precise location access. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
  • ์•ฑ์ด ์œ„์น˜ ์ •๋ณด์— ์ ‘๊ทผํ•˜๋ ค๋ฉด, ๋จผ์ € AndroidManifest.xml ํŒŒ์ผ์— ์œ„์น˜ ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•จ

 

2. ๊ถŒํ•œ ์š”์ฒญ

class MainActivity : AppCompatActivity() {

    companion object {
        private const val PERMISSION_REQUEST_ACCESS_FINE_LOCATION = 100
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        requestLocationPermission()
    }

    private fun requestLocationPermission() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // ๊ถŒํ•œ์ด ์—†์„ ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž์—๊ฒŒ ์š”์ฒญ
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                PERMISSION_REQUEST_ACCESS_FINE_LOCATION
            )
        } else {
            // ๊ถŒํ•œ์ด ์ด๋ฏธ ์žˆ์„ ๊ฒฝ์šฐ, ์œ„์น˜ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
            getLocation()
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        when (requestCode) {
            PERMISSION_REQUEST_ACCESS_FINE_LOCATION -> {
                if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                    // ๊ถŒํ•œ์ด ๋ถ€์—ฌ๋˜๋ฉด ์œ„์น˜ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
                    getLocation()
                } else {
                    // ๊ถŒํ•œ์ด ๊ฑฐ๋ถ€๋˜๋ฉด, ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๋ถˆ๊ฐ€
                }
                return
            }
        }
    }

    private fun getLocation
  • ๋Ÿฐํƒ€์ž„ ์‹œ, ์•ฑ์€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ถŒํ•œ์„ ์š”์ฒญํ•ด์•ผ ํ•จ
    ์•ˆ๋“œ๋กœ์ด๋“œ 6.0(API ๋ ˆ๋ฒจ 23) ์ด์ƒ์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๋™์•ˆ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๊ฑฐ๋‚˜ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ์Œ
  • ์œ„์˜ ์ฝ”๋“œ๋Š” ACCESS_FINE_LOCATION ๊ถŒํ•œ์„ ์š”์ฒญํ•˜๊ณ  ํš๋“ํ•˜๋Š” ์˜ˆ์ œ ์ฝ”๋“œ
  • ์œ„ ์ฝ”๋“œ์—์„œ requestLocationPermission ํ•จ์ˆ˜๋Š” ๋จผ์ € ์•ฑ์— ์œ„์น˜ ๊ถŒํ•œ์ด ์žˆ๋Š”์ง€ ํ™•์ธ
    ๊ถŒํ•œ์ด ์—†๋‹ค๋ฉด ActivityCompat.requestPermissions ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ถŒํ•œ์„ ์š”์ฒญํ•˜๊ณ ,
    ๊ฒฐ๊ณผ๋Š” onRequestPermissionsResult ์ฝœ๋ฐฑ ๋ฉ”์†Œ๋“œ์—์„œ ์ฒ˜๋ฆฌ
    ์‚ฌ์šฉ์ž๊ฐ€ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋ฉด getLocation ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์œ„์น˜ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

 

 

 

 

 

2) ํ”Œ๋žซํผ API์˜ ์œ„์น˜ ๋งค๋‹ˆ์ €

→  ์•ˆ๋“œ๋กœ์ด๋“œ ๋‹จ๋ง ๋‚ด๋ถ€์—์„œ ์œ„์น˜ ์ •๋ณด๋ฅผ ์–ป๋Š” ๋ฐฉ๋ฒ•

 

val manager = getSystemService(LOCATION_SERVICE) as LocationManager
  • ์‚ฌ์šฉ์ž์˜ ์œ„์น˜๋ฅผ ์–ป์„ ๋•Œ๋Š” LocationManager๋ผ๋Š” ์‹œ์Šคํ…œ ์„œ๋น„์Šค๋ฅผ ์ด์šฉ

 

var result = "All Providers : "
val providers = manager.allProviders
for (provider in providers) {
		result += " $provider. "
}
Log.d("maptest", result)  // All Providers : passive, gps, network..
  • ์œ„์น˜ ์ œ๊ณต์ž ์ง€์ •ํ•˜๊ธฐ
        - GPS: GPS ์œ„์„ฑ์„ ์ด์šฉ
        - Network: ์ด๋™ ํ†ต์‹ ๋ง์„ ์ด์šฉ
        - Wifi: ์™€์ดํŒŒ์ด๋ฅผ ์ด์šฉ
        - Passive: ๋‹ค๋ฅธ ์•ฑ์—์„œ ์ด์šฉํ•œ ๋งˆ์ง€๋ง‰ ์œ„์น˜ ์ •๋ณด๋ฅผ ์ด์šฉ
  • ํ˜„์žฌ ๊ธฐ๊ธฐ์— ์–ด๋–ค ์œ„์น˜ ์ œ๊ณต์ž๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด LocationManager์˜ allProviders ํ”„๋กœํผํ‹ฐ๋ฅผ ์ด์šฉ

 

result = "Enabled Providers : "
val enabledProviders = manager.getProviders(true)
for (provider in enabledProviders) {
		result += " $provider. "
}
Log.d("maptest", result)  // Enabled Providers : passive, gps, network..

- ์ง€๊ธˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์•Œ์•„๋ณด๋ ค๋ฉด getProviders() ํ•จ์ˆ˜๋ฅผ ์ด์šฉ

 

if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            val location: Location? = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
            location?.let{
                val latitude = location.latitude
                val longitude = location.longitude
                val accuracy = location.accuracy
                val time = location.time
                Log.d("map_test", "$latitude, $location, $accuracy, $time")
            }
        }
  • ์œ„์น˜์ •๋ณด์–ป๊ธฐ
        - LocationManager์˜ getLastKnownLocation() ํ•จ์ˆ˜๋ฅผ ์ด์šฉ
        - Location์€ ์œ„์น˜์˜ ์ •ํ™•๋„, ์œ„๋„, ๊ฒฝ๋„, ํš๋“ ์‹œ๊ฐ„ ๋“ฑ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จ
            - getAccuracy(): ์ •ํ™•๋„
            - getLatitude(): ์œ„๋„
            - getLongitude(): ๊ฒฝ๋„
            - getTime(): ํš๋“ ์‹œ๊ฐ„

 

val listener: LocationListener = object : LocationListener {
            override fun onLocationChanged(location: Location) {
                Log.d("map_test,","${location.latitude}, ${location.longitude}, ${location.accuracy}")
            }
        }
        manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10_000L, 10f, listener)
        // (.. ์ƒ๋žต ..) //
        manager.removeUpdates(listener)
  • ๊ณ„์† ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค๋ฉด LocationListener๋ฅผ ์ด์šฉ
        - onLocationChanged(): ์ƒˆ๋กœ์šด ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด ํ˜ธ์ถœ
        - onProviderEnabled(): ์œ„์น˜ ์ œ๊ณต์ž๊ฐ€ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ด๋ฉด ํ˜ธ์ถœ
        - onProviderDisabled(): ์œ„์น˜ ์ œ๊ณต์ž๊ฐ€ ์ด์šฉํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์ด๋ฉด ํ˜ธ์ถœ

 

 

 

 

3) ๊ตฌ๊ธ€ Play ์„œ๋น„์Šค์˜ ์œ„์น˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

→  ์‚ฌ์‹ค 2๋ฒˆ๋ณด๋‹ค ์ด๊ฒŒ ๋” ํŽธํ•˜๊ณ  ์ •ํ™•๋„๊ฐ€ ๋†’์Œ

 

// ๊ตฌ๊ธ€ play ์„œ๋น„์Šค ์‚ฌ์šฉ ์„ ์–ธ : Gradle ํŒŒ์ผ์— ์ž…๋ ฅ
implementation 'com.google.android.gms:play-services:12.0.1'
  • ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์ง€์ •ํ•  ๋•Œ ๊ณ ๋ คํ•  ์‚ฌํ•ญ
        - ์ „๋ ฅ์„ ์ ๊ฒŒ ์†Œ๋น„ํ•˜๋Š”๊ฐ€?
        - ์ •ํ™•๋„๋Š” ๋†’์€๊ฐ€?
        - API๊ฐ€ ๊ฐ„๋‹จํ•œ๊ฐ€?
        - ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š”๊ฐ€?
        - ๋Œ€๋ถ€๋ถ„ ์•ˆ๋“œ๋กœ์ด๋“œ ๊ธฐ๊ธฐ๋ฅผ ์ง€์›ํ•˜๋Š”๊ฐ€?
    ๋”ฐ๋ผ์„œ ๊ตฌ๊ธ€ํ”Œ๋ ˆ์ด์˜ ์œ„์น˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ
  • ๊ตฌ๊ธ€์—์„œ๋Š” ์ตœ์ ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก Fused Location Provider๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ œ๊ณต

 

// ๊ตฌ๊ธ€ api ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”

val connectionCallback = object: GoogleApiClient.ConnectionCallbacks{
            override fun onConnected(p0: Bundle?) {
                // ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๋•Œ
                // ์œ„์น˜ ํš๋“
            }

            override fun onConnectionSuspended(p0: Int) {
                // ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ๋•Œ
            }
        }
        val onConnectionFailCallback = object : GoogleApiClient.OnConnectionFailedListener{
            override fun onConnectionFailed(p0: ConnectionResult) {
                // ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ„์น˜ ์ œ๊ณต์ž๊ฐ€ ์—†์„ ๋•Œ
            }
        }
        val apiClient = GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(connectionCallback)
            .addOnConnectionFailedListener(onConnectionFailCallback)
            .build()
  • Fused Location Provider์—์„œ ํ•ต์‹ฌ ํด๋ž˜์Šค
        - FusedLocationProviderClient: ์œ„์น˜ ์ •๋ณด๋ฅผ ์–ป์Œ
        - GoogleApiClient: ์œ„์น˜ ์ œ๊ณต์ž ์ค€๋น„ ๋“ฑ ๋‹ค์–‘ํ•œ ์ฝœ๋ฐฑ์„ ์ œ๊ณต
  • GoogleApi Client์—์„œ๋Š” GoogleApiClient.ConnectionCallbacks์™€
    GoogleApiClient.OnConnection FailedListener ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋ฅผ ์ง€์ •
            

 

val providerClient = LocationServices.getFusedLocationProviderClient(this)
  • FusedLocationProviderClient ์ดˆ๊ธฐํ™”

 

apiClient.connect()
  • GoogleApiClient ๊ฐ์ฒด์— ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์š”์ฒญ

 

// ์œ„์น˜ ์ œ๊ณต์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ผ ๋•Œ
    override fun onConnected(p0: Bundle?) {
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) === PackageManager.PERMISSION_GRANTED){
            providerClient.lastLocation.addOnSuccessListener(
                this@MainActivity,
                object: OnSuccessListener<Location> {
                    override fun onSuccess(p0: Location?) {
                        p0?.let {
                            val latitude = p0.latitude
                            val longitude = p0.longitude
                            Log.d("map_test", "$latitude, $longitude")
                        }
                    }
                }
            )
            apiClient.disconnect()
        }
    }
  • onConnected() ํ•จ์ˆ˜์—์„œ FusedLocationProviderClient์˜ getLastLocation() ํ•จ์ˆ˜ ํ˜ธ์ถœ

 

 

๋ฐ˜์‘ํ˜•
 ๐Ÿ’ฌ C O M M E N T