Skip to content

Commit 09d6bd0

Browse files
authored
[Merge PR] Update Internal LocationTracking System with New API (#322)
2 parents 9260858 + 60b6ba6 commit 09d6bd0

File tree

58 files changed

+1610
-199
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1610
-199
lines changed

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/FlutterNaverMapPlugin.kt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package dev.note11.flutter_naver_map.flutter_naver_map
22

33
import android.app.Activity
44
import android.content.Context
5-
import android.os.Build
65
import dev.note11.flutter_naver_map.flutter_naver_map.sdk.SdkInitializer
6+
import dev.note11.flutter_naver_map.flutter_naver_map.util.location.NDefaultMyLocationTracker
77
import dev.note11.flutter_naver_map.flutter_naver_map.view.NaverMapViewFactory
88
import io.flutter.embedding.engine.plugins.FlutterPlugin
99
import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterAssets
@@ -14,6 +14,7 @@ import io.flutter.plugin.common.MethodChannel
1414
internal class FlutterNaverMapPlugin : FlutterPlugin, ActivityAware {
1515
private lateinit var pluginBinding: FlutterPlugin.FlutterPluginBinding
1616
private lateinit var sdkInitializer: SdkInitializer
17+
private lateinit var defaultMyLocationTracker: NDefaultMyLocationTracker
1718
private val context: Context get() = pluginBinding.applicationContext
1819

1920
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
@@ -27,6 +28,11 @@ internal class FlutterNaverMapPlugin : FlutterPlugin, ActivityAware {
2728
sdkInitializer = SdkInitializer(context, sdkChannel)
2829
}
2930

31+
private fun initializeDefaultMyLocationTracker(activity: Activity) {
32+
defaultMyLocationTracker =
33+
NDefaultMyLocationTracker(pluginBinding.binaryMessenger, activity)
34+
}
35+
3036
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) = Unit
3137

3238
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
@@ -36,13 +42,17 @@ internal class FlutterNaverMapPlugin : FlutterPlugin, ActivityAware {
3642
pluginBinding.platformViewRegistry.registerViewFactory(
3743
MAP_VIEW_TYPE_ID, naverMapViewFactory
3844
)
45+
initializeDefaultMyLocationTracker(activity)
3946
}
4047

4148
override fun onDetachedFromActivityForConfigChanges() = Unit
4249

4350
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) = Unit
4451

45-
override fun onDetachedFromActivity() = Unit
52+
override fun onDetachedFromActivity() {
53+
sdkInitializer.dispose()
54+
if (::defaultMyLocationTracker.isInitialized) defaultMyLocationTracker.dispose()
55+
}
4656

4757
companion object {
4858
private const val SDK_CHANNEL_NAME = "flutter_naver_map_sdk"

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/applier/ApplyUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ internal object ApplyUtil {
4545
"consumeSymbolTapEvents" to { { /** @see NaverMapView.setMapTapListener method */ } },
4646
"scaleBarEnable" to { { /* removed*/ } },
4747
"indoorLevelPickerEnable" to { it::setIndoorLevelPickerEnable },
48-
"locationButtonEnable" to { it::setLocationButtonEnable },
48+
"locationButtonEnable" to { { /* removed*/ } },
4949
"logoClickEnable" to { { /* removed*/ } },
5050
"logoAlign" to { it::setLogoAlign },
5151
"logoMargin" to { it::setLogoMargin },

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/applier/option/NaverMapApplierImpl.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,6 @@ class NaverMapApplierImpl(
110110
naverMap.uiSettings.isIndoorLevelPickerEnabled = rawEnable.asBoolean()
111111
}
112112

113-
override fun setLocationButtonEnable(rawEnable: Any) {
114-
naverMap.uiSettings.isLocationButtonEnabled = rawEnable.asBoolean()
115-
}
116-
117113
override fun setLogoAlign(rawAlign: Any) {
118114
naverMap.uiSettings.logoGravity = rawAlign.asLogoAlign()
119115
}

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/applier/option/NaverMapOptionApplier.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ internal interface NaverMapOptionApplier {
2323
fun setZoomGesturesFriction(rawFriction: Any)
2424
fun setRotationGesturesFriction(rawFriction: Any)
2525
fun setIndoorLevelPickerEnable(rawEnable: Any)
26-
fun setLocationButtonEnable(rawEnable: Any)
2726
fun setLogoAlign(rawAlign: Any)
2827
fun setLogoMargin(rawEdgeInsets: Any)
2928
fun setContentPadding(rawEdgeInsets: Any)

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/applier/option/NaverMapOptionApplierImpl.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,6 @@ class NaverMapOptionApplierImpl(
113113
options.indoorLevelPickerEnabled(rawEnable.asBoolean())
114114
}
115115

116-
override fun setLocationButtonEnable(rawEnable: Any) {
117-
options.locationButtonEnabled(rawEnable.asBoolean())
118-
}
119-
120116
override fun setLogoAlign(rawAlign: Any) {
121117
options.logoGravity(rawAlign.asLogoAlign())
122118
}

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/model/map/NaverMapViewOptions.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ internal data class NaverMapViewOptions(
5555
zoomControlEnabled(false)
5656
scaleBarEnabled(false)
5757
logoClickEnabled(false)
58+
locationButtonEnabled(false)
5859
}
5960

6061
val applier = NaverMapOptionApplierImpl(options)

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/sdk/SdkInitializer.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ internal class SdkInitializer(
1818
channel.setMethodCallHandler(::handle)
1919
}
2020

21+
fun dispose() {
22+
channel.setMethodCallHandler(null)
23+
}
24+
2125
private fun handle(call: MethodCall, result: MethodChannel.Result) {
2226
if (call.method == "initializeNcp") {
2327
initializeWithNcp(

android/src/main/kotlin/dev/note11/flutter_naver_map/flutter_naver_map/util/NLocationSource.kt

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package dev.note11.flutter_naver_map.flutter_naver_map.util.location
2+
3+
import android.Manifest
4+
import android.app.Activity
5+
import android.content.Context
6+
import android.content.pm.PackageManager
7+
import android.hardware.SensorManager
8+
import androidx.annotation.RequiresPermission
9+
import androidx.core.app.ActivityCompat
10+
import androidx.core.content.ContextCompat
11+
import com.google.android.gms.location.FusedLocationProviderClient
12+
import com.google.android.gms.location.LocationServices
13+
import com.google.android.gms.location.Priority
14+
import com.google.android.gms.tasks.CancellationTokenSource
15+
import com.naver.maps.geometry.LatLng
16+
import dev.note11.flutter_naver_map.flutter_naver_map.converter.MapTypeConverter.toMessageable
17+
import io.flutter.plugin.common.BinaryMessenger
18+
import io.flutter.plugin.common.EventChannel
19+
import io.flutter.plugin.common.MethodChannel
20+
import io.flutter.plugin.common.PluginRegistry
21+
22+
class NDefaultMyLocationTracker(messenger: BinaryMessenger, val activity: Activity) :
23+
NDefaultMyLocationTrackerHandler, PluginRegistry.RequestPermissionsResultListener {
24+
private val methodChannel = MethodChannel(messenger, "NDefaultMyLocationTracker")
25+
private val locationEventChannel =
26+
EventChannel(messenger, "NDefaultMyLocationTracker.locationStream")
27+
private val headingEventChannel =
28+
EventChannel(messenger, "NDefaultMyLocationTracker.headingStream")
29+
30+
private val locationStreamHandler =
31+
NDefaultMyLocationTrackerLocationStreamHandler(
32+
fusedLocationProviderClientFactory = { fusedLocationProviderClient },
33+
onLocationChangedCallback = { headingStreamHandler.onLocationChanged(it) },
34+
)
35+
private val headingStreamHandler =
36+
NDefaultMyLocationTrackerHeadingStreamHandler(sensorManagerFactory = {
37+
activity.getSystemService(Context.SENSOR_SERVICE) as SensorManager
38+
})
39+
40+
private val fusedLocationProviderClient: FusedLocationProviderClient by lazy {
41+
LocationServices.getFusedLocationProviderClient(activity)
42+
}
43+
private var cancellationTokenSources: MutableMap<Int, CancellationTokenSource> = mutableMapOf()
44+
private var permissionHandlerCallback: ((result: NDefaultMyLocationTrackerPermissionStatus) -> Unit)? =
45+
null
46+
47+
init {
48+
methodChannel.setMethodCallHandler(::handle)
49+
locationEventChannel.setStreamHandler(locationStreamHandler)
50+
headingEventChannel.setStreamHandler(headingStreamHandler)
51+
}
52+
53+
fun dispose() {
54+
methodChannel.setMethodCallHandler(null)
55+
locationEventChannel.setStreamHandler(null)
56+
headingEventChannel.setStreamHandler(null)
57+
}
58+
59+
override fun requestLocationPermission(result: MethodChannel.Result) {
60+
val hasPermission =
61+
ContextCompat.checkSelfPermission(
62+
activity,
63+
Manifest.permission.ACCESS_FINE_LOCATION
64+
) == PackageManager.PERMISSION_GRANTED
65+
66+
if (hasPermission) {
67+
result.success(NDefaultMyLocationTrackerPermissionStatus.Granted.toMessageable())
68+
return
69+
}
70+
71+
permissionHandlerCallback = { permissionResult ->
72+
result.success(permissionResult.toMessageable())
73+
}
74+
75+
ActivityCompat.requestPermissions(
76+
activity,
77+
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
78+
LOCATION_PERMISSION_REQUEST_CODE
79+
)
80+
}
81+
82+
override fun onRequestPermissionsResult(
83+
requestCode: Int,
84+
permissions: Array<out String?>,
85+
grantResults: IntArray
86+
): Boolean {
87+
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
88+
val callback = permissionHandlerCallback ?: return false
89+
val status: NDefaultMyLocationTrackerPermissionStatus =
90+
when (grantResults.firstOrNull()) {
91+
PackageManager.PERMISSION_GRANTED -> NDefaultMyLocationTrackerPermissionStatus.Granted
92+
PackageManager.PERMISSION_DENIED -> {
93+
if (ActivityCompat.shouldShowRequestPermissionRationale(
94+
activity,
95+
Manifest.permission.ACCESS_FINE_LOCATION
96+
)
97+
) {
98+
NDefaultMyLocationTrackerPermissionStatus.Denied
99+
} else {
100+
NDefaultMyLocationTrackerPermissionStatus.DeniedForever
101+
}
102+
}
103+
104+
else -> NDefaultMyLocationTrackerPermissionStatus.Denied
105+
}
106+
callback.invoke(status)
107+
return true
108+
}
109+
return false
110+
}
111+
112+
@RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
113+
override fun getCurrentPositionOnce(result: MethodChannel.Result) {
114+
val cancellationTokenSource = CancellationTokenSource()
115+
val tokenHash = cancellationTokenSource.token.hashCode()
116+
cancellationTokenSources[tokenHash] = cancellationTokenSource
117+
118+
fusedLocationProviderClient.getCurrentLocation(
119+
Priority.PRIORITY_HIGH_ACCURACY, cancellationTokenSource.token
120+
)
121+
.addOnSuccessListener { location ->
122+
if (location != null) {
123+
location.run { result.success(LatLng(latitude, longitude).toMessageable()) }
124+
} else {
125+
result.error("LocationError", "Location is null", null)
126+
}
127+
cancellationTokenSources.remove(tokenHash)
128+
}.addOnFailureListener {
129+
result.error("LocationError", it.message, null)
130+
cancellationTokenSources.remove(tokenHash)
131+
}.addOnCanceledListener {
132+
cancellationTokenSources.remove(tokenHash)
133+
}
134+
}
135+
136+
override fun cancelAllWaitingGetCurrentPositionOnceTask() {
137+
cancellationTokenSources.forEach {
138+
it.value.cancel()
139+
}
140+
}
141+
142+
143+
companion object {
144+
const val LOCATION_PERMISSION_REQUEST_CODE = 706
145+
}
146+
}
147+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package dev.note11.flutter_naver_map.flutter_naver_map.util.location
2+
3+
import io.flutter.plugin.common.MethodCall
4+
import io.flutter.plugin.common.MethodChannel
5+
6+
internal interface NDefaultMyLocationTrackerHandler {
7+
fun handle(call: MethodCall, result: MethodChannel.Result) = when (call.method) {
8+
"requestLocationPermission" -> requestLocationPermission(result)
9+
"getCurrentPositionOnce" -> getCurrentPositionOnce(result)
10+
"cancelAllWaitingGetCurrentPositionOnceTask" -> cancelAllWaitingGetCurrentPositionOnceTask()
11+
else -> result.notImplemented()
12+
}
13+
14+
fun requestLocationPermission(result: MethodChannel.Result)
15+
16+
fun getCurrentPositionOnce(result: MethodChannel.Result)
17+
18+
fun cancelAllWaitingGetCurrentPositionOnceTask()
19+
}

0 commit comments

Comments
 (0)