inavi_map_flutter 1.0.0
inavi_map_flutter: ^1.0.0 copied to clipboard
Flutter plugin for iNavi Maps SDK — map display, camera, markers on Android and iOS.
Changelog #
1.0.0 #
첫 공개 릴리스 / Initial public release.
Added #
InaviMapsViewPlatformView를 통한 Android·iOS 네이티브 지도 렌더링. / Native map rendering viaInaviMapsViewon Android and iOS.- 이벤트 기반 인증 결과 스트림
InaviMapsSdk.instance.onInit(AuthSuccess/AuthFailure/MapReady). / Event-driven auth result stream. - 카메라 제어 —
animateCamera·moveCamera·getCameraPosition·getVisibleBounds· bounds fit · 공통 Easing. / Camera controls with shared easing. - 선언형 도형 API — 마커 · 폴리라인 · 폴리곤 · 원 · InfoWindow · 클러스터 · 경로(Route). / Declarative shape APIs.
- 지도 이벤트 — 클릭 · 롱클릭 · 더블클릭 · 카메라 이동/정지 · 마커/도형/클러스터 탭. / Map interaction events.
- 사용자 위치 추적(
UserTrackingMode)과 현위치 아이콘 커스터마이징·onLocationTap. / User location tracking and location icon customization. - 좌표계 변환(WGS84 · KATEC · UTM-K · TM · GRS80)과 화면↔지도 좌표 Projection. / Coordinate conversion and screen/map projection.
- 지도 옵션 — 제스처 4종 · UI 컨트롤 · 실내지도 · 라벨 다국어(
MapLanguage) · 커스텀 스타일(MapStyle) · Pick POIs. / Map options.
Platform Support #
- Android 6.0 (API 23) 이상. / Android 6.0 (API 23) and later.
- iOS 15.0 이상. / iOS 15.0 and later.
Notes #
- 사용 전 Android manifest metadata 또는 iOS
Info.plist에 iNavi APP KEY를 설정해야 합니다. / An iNavi app key must be configured before use. - Android SDK 아티팩트는
https://repo.inavi.com/artifactory/maps에서 해석됩니다. / Android artifacts resolve from the iNavi Maven repository. - iOS SDK 아티팩트는 CocoaPods trunk의
inavi-maps-sdk로 해석됩니다. / iOS artifacts resolve via theinavi-maps-sdkCocoaPods dependency. - Native SDK 의존성 버전:
0.22.0(Android · iOS). / Native SDK dependency version 0.22.0.
개발 상세 이력 (Detailed development notes)
커스텀 지도 스타일 (Map Custom Style, 2026-06-05) #
MapStyle—index: int,styleName: String,styleId: String필드를 가진 커스텀 지도 스타일 모델 신규.index는savedCustomMapStyles배열 내 위치(native 역참조에 사용). / New model for custom map styles from Map Studio.InaviMapsController.getCustomMapStyles()— Map Studio로 배포된 커스텀 지도 스타일 목록을 반환. 인증 완료 전 또는 배포된 스타일이 없으면 빈 목록 반환. AndroidInaviMapSdk.savedCustomMapStyles· iOSINVMapSdk.savedCustomMapStylesindex 기반 접근. / Returns available custom map styles for the current AppKey.InaviMapsController.setCustomMapStyle(MapStyle?)— 커스텀 지도 스타일을 적용.null전달 시 기본 스타일로 복원. / Applies a custom map style; null resets to the default style.- Example
MapCustomStyleScreen추가 (지도 옵션 > Map Custom Style) — 기본 스타일 진입 시 마커 3개(빨강·파랑·초록) + 폴리라인 표출, 커스텀 스타일 전환 시 제거, 기본 스타일 복귀 시 재표출. 스타일 선택 드롭다운은 화면 하단 바(bottomNavigationBar)에 배치. 배포된 스타일 없으면 SnackBar 안내. / Adds Map Custom Style demo screen under 지도 옵션 category. Default style shows 3 markers and a polyline; switching to a custom style clears them, returning to default restores them. Style selector is in the bottom bar.
Pick POIs (2026-06-05) #
InaviMapsController.pickPois(Offset, {touchRadius})— 지도 탭 지점 주변의 POI(관심지점) 목록을 반환.PoiInfo {name, poiId, position}모델 신규. AndroidinaviMap.pickPois(RectF)density 보정, iOSmapView.pickPois(CGRect)무보정. / Returns POIs near a tapped screen point. NewPoiInfomodel (name,poiId,position). Android applies density scaling; iOS uses logical pts directly.PoiInfo—name: String,poiId: String,position: Coordinate필드를 가진 POI 정보 모델. / New data class holding POI name, ID, and WGS-84 position.- Example
PickPoisScreen추가 (기타 > Pick POIs) — 탭 지점에 반투명 빨간 사각형 오버레이, POI 조회 결과 SnackBar 표시, 각 POI에 빨간 마커 배치, 카메라 이동 시 초기화. / Adds a Pick POIs demo screen under the 기타 category.
폴리라인 점선 간격 density 보정 (Polyline pattern, 2026-06-05) #
- Android 점선 간격 수정 — Android 가 폴리라인
pattern(dash/gap 길이)에 화면 density 를 적용하지 않아 고해상도 기기에서 iOS 보다 점선이 density 배 촘촘하게 표출되던 문제를 수정.width와 동일하게pattern각 값에 density 를 곱해 logical px → physical px 로 변환한다. / Fixes Android polyline dash pattern appearing denser than iOS; pattern lengths are now scaled by display density (logical px → physical px), consistent with stroke width.
지도 라벨 다국어 표기·SDK 0.22.0 업그레이드 (Map Language, 2026-06-05) #
- SDK 0.22.0 업그레이드 — Android
com.inavi.mapsdk:inavi-maps-sdk:0.22.0· iOSinavi-maps-sdk ~> 0.22.0으로 업데이트. / Upgraded native SDK dependency to 0.22.0 on both platforms. MapLanguageenum 추가 —ko·en·ja·zh4개 언어 코드를 타입 안전하게 래핑.MapLanguage.fromCode로 SDK 반환값을 역매핑하며 미지원 코드는ko로 폴백. / Adds aMapLanguageenum wrapping the four supported language codes; unknown codes fall back toko.InaviMapsController.setLanguage(MapLanguage)— 지도 라벨 표기 언어를 실행 중 변경. AndroidInaviMap.language, iOSInaviMapView.language에 코드 문자열을 직접 전달. / Sets the map label language at runtime.InaviMapsController.getLanguage()— 현재 라벨 표기 언어를MapLanguage로 반환. / Returns the current map label language.- Example
MapLanguageScreen추가 (지도 옵션 > Map Language) — 4개 언어 칩 선택 시 즉시 지도 라벨이 전환됨.onMapCreated직후 현재 언어 동기화. / Adds a Map Language demo screen with 4 language chips.
현위치 아이콘 커스터마이징·탭 이벤트 (LocationIcon·onLocationTap, 2026-06-05) #
LocationIcon커스터마이징 —LocationOptions.icon(scale·circleRadius·circleColor·imageTracking·imageTrackingCompass·image)을 Android/iOS 네이티브에 실제 적용.null이미지 지정 시 SDK 기본 이미지로 자동 복귀(LocationIcon.DEFAULT_IMAGE*/INV_LOCATION_ICON_IMAGE*). / Location icon customization (scale,circleRadius,circleColor, per-mode images) is now applied natively on both platforms. Setting an image tonullresets to the SDK default image.onLocationTap— 현위치 점 탭 시 콜백이 실제 발화됨 (AndroidLocationIcon.setOnClickListener, iOSINVLocationIcon.touchEvent). / Tapping the location dot now fires theonLocationTapcallback on both platforms.- iOS
circleRadius보정 — iOS SDK 는circleRadius를 pt 단위로 처리하므로 플러그인이radius ÷ UIScreen.main.scale로 Dart logical px → pt 변환을 수행한다(Android 는 SDK 가scale자동 반영 안 하여circleRadius × scale수동 계산). / iOS plugin dividescircleRadiusbyUIScreen.main.scale(logical px → pt); Android multiplies by scale manually since the Android SDK does not auto-apply it. - Example
LocationIconScreen추가 (위치 > Location Icon) — scale·circleRadius·circleColor 슬라이더/칩 + Custom Image 토글 + 현위치 탭 스낵바. / Adds aLocation Icondemo screen under the Location category.
실내지도 (IndoorMap, 2026-06-04) #
MapOptions.indoorMapEnabled(기본true) 추가 — PlatformView 생성 시 실내지도 표출 여부를 1회 적용한다(런타임 변경은setIndoorMapEnabled). / Adds an initial indoor-map toggle.InaviMapsController.setIndoorMapEnabled(bool)/isIndoorMapEnabled()— 실내지도 표출을 런타임에 켜고 끈다. AndroidInaviMap.enabledIndoorMap, iOSInaviMapView.isIndoorMapEnabled(둘 다 SDK 기본true). / Toggles indoor map at runtime.InaviMapsController.onIndoorChanged→Stream<IndoorChangeEvent>— 실내 영역 진입/이탈/층 변경 이벤트.IndoorChangeEvent {placeId, floors, currentFloorIndex}(이탈 시placeId == null,isInsidegetter 제공),floors는IndoorFloor {name, index}목록. AndroidsetOnIndoorChangedListener, iOSINVMapViewDelegate.didChangeIndoor사용. / Indoor enter/exit/floor-change events.InaviMapsController.setIndoorFloor(IndoorFloor)— 층 전환.onIndoorChanged가 제공한floors의 항목을 그대로 전달하면 해당 층으로 전환된다. native 가 viewId 별로 floors 를 캐시하고index로 매칭하므로 이름이 같은 층도 정확히 구분된다. / Switches the active indoor floor by its list index.- 진행 이벤트는 기존
event/map채널 + 신규indoor.changed타입(ChannelKeys3-way, 채널 신설 없음)으로 발신.route.progress와 동일 구조. - Example
IndoorMapScreen신규 (기타/ IndoorMap) —실내지도 활성화스위치 + 실내 영역 진입 시 층 휠 피커(CupertinoPicker)로 층 전환. NativeIndoorActivity/IndoorMapController미러링(초기 카메라 코엑스 인근(37.49380, 127.11573)zoom 16, placeId 변경 시 피커 표시/숨김; 같은 장소 내 층 변경은 fling 모멘텀 피드백 루프 방지를 위해 피커 동기화 제외). 이로써기타카테고리가 Native 메뉴와 한층 더 정합. - 단위 테스트 추가 —
IndoorFloor/IndoorChangeEvent직렬화·진입/이탈·floorsnull 방어 ·MapOptions.indoorMapEnabled· 컨트롤러 3 메서드 채널 인자/true폴백 · Example 레이아웃 회귀(피커 표시 게이트 포함).
경로 (InvRoute, 2026-06-04) #
Route·RouteLink모델 추가 — 지도 위에 경로를 그리는 셰이프.RouteLink(coords, lineColor?, strokeColor?)로 구간(링크)별 좌표열·색상을 지정하고,Route(routeId, links, lineWidth, strokeWidth, globalZIndex?, patternImage?, patternMargin?, patternScale?, passRatio, passLineColor?, passStrokeColor?, onProgress?)로 경로를 구성한다.links가 비었거나 링크의coords가 2개 미만이면ArgumentError로 fail-fast(SDK 의InvalidLatLngException사전 방지). / AddsRoute/RouteLinkshapes mirroring the SDKInvRoute.InaviMapsController.updateRoutes(Set<Route>)— 경로 집합을 지도와 동기화(추가/갱신/제거 리컨실).patternImage로AssetMarkerIcon사용 시 해상도별 variant 가 선택된다.InaviMapsController.setRoutePassRatio(routeId, passRatio)— 경로 진행률(0.0~1.0, clamp)을 런타임에 변경. 전체 리컨실 없이 단일 경로만 갱신하므로 애니메이션에 적합.- 진행률 변경 이벤트 —
Route.onProgress콜백 및InaviMapsController.onRouteProgress스트림으로 진행 위치(Coordinate)·각도·지나온 거리(RouteProgressEvent)를 수신. 이를 활용해 경로를 따라 움직이는 마커를 그릴 수 있다.onProgress가 설정된 경로에만 네이티브가 리스너를 등록한다(hasProgressListener). AndroidsetOnRouteChangeListener, iOSINVRouteDelegate사용. /route.progressevents expose position/angle/distance for a marker moving along the route. patternImage는 기존MarkerIcon(asset/bytes/builtIn) 을 재사용 — 방향 화살표 등 패턴을 경로 위에 일정 간격(patternMargin)·배율(patternScale)로 반복 표출.lineWidth/strokeWidth/patternMargin은 logical px(Android dp·iOS pt) — Android 는 density 보정, iOS 는 pt 직접 사용.Marker.isIconFlat추가(기본false, 3-way) —true면 아이콘이 지도 평면에 눕혀져 지도 회전/기울기에 따라 함께 회전하고rotation이 지도 기준 방위각으로 해석된다(경로 진행 방향 마커 등). AndroidInvMarker.isIconFlat· iOSINVMarker.isIconFlat. / AddsMarker.isIconFlat(defaultfalse) for map-flat icons.- 마커 갱신 성능·정확성 수정 —
updateMarkers가 매 호출마다 아이콘을 재디코드·재할당하던 것을 아이콘 스펙(종류/색/에셋/배율/바이트)이 바뀐 경우에만 재할당하도록 변경. 경로 진행 마커처럼 마커를 빠르게(고빈도) 갱신할 때 asset 아이콘이 텍스처 재업로드로 인해 비표시 상태에 머물던 버그를 해결하고, 불필요한 디코드/업로드를 제거한다(양 플랫폼). /updateMarkersnow reassigns a marker's icon only when its spec changes — fixes asset-icon markers vanishing under rapid updates and avoids redundant texture uploads. - Example
RouteScreen를 NativeInvRouteActivity와 동일하게 정비 — 카메라가 진행 위치를 추적,마커 표출·플랫 마커체크박스(미표출 시 플랫 비활성), 데모 마커/화살표 패턴 에셋·LINKS·스타일 반영. - Example
RouteScreen신규 (셰이프/ InvRoute) — 링크별 색상(빨강·초록·파랑) 경로 + 별 패턴 이미지 + 진행률 슬라이더/재생 버튼으로 경로를 따라 움직이는 마커 시연 (가이드 미러링). 이로써 셰이프 카테고리가 Native 메뉴와 완전히 정합. - 단위 테스트 추가 —
Route/RouteLink직렬화(링크별 색 ARGB·null-aware·patternImage위임·검증) ·RouteProgressEvent디코드 ·updateRoutes/setRoutePassRatio채널 인자·passRatioclamp.
마커 예제 화면 정비 + getVisibleBounds · isTransitionEnabled (2026-06-02) #
InaviMapsController.getVisibleBounds() → LatLngBounds?추가 — 현재 지도에 보이는 영역 경계 반환. AndroidInaviMap.getVisibleBounds(), iOSInaviMapView.contentBounds사용. / Returns the current visible map bounds.Marker.isTransitionEnabled추가 — 마커 표출 상태 변경(겹침 해소 등) 시 Fade 전환 애니메이션 적용 여부. SDK 기본값과 동일하게false(iOSINVMarker.isTransitionEnabled기본NO). 3-way 직렬화. / Controls fade transition on display-state change; defaults tofalseto match the SDK.- InvMarker 화면 — 5종 마커로 주요 속성 시연: Yellow 반투명(
alpha 0.5), Green 타이틀 파란색(titleColor), Blue 타이틀 크기 16(titleSize), Gray → 별 모양 asset 마커(iconScale 2.0,anchor (0.5,0.5))로 변경. 별 asset 1x/2x/3x 추가. - InvMarker Overlap 화면 — 50개 마커를
getVisibleBounds()기반 현재 가시 영역에 랜덤 배치 + 5색 순환 + Fade 애니메이션(isTransitionEnabled) 토글 + 마커 재생성 버튼 추가. - InfoWindow 화면 — Native 방식(단일 InfoWindow 재사용)으로 변경: 마커 탭 → 마커 부착 +
"마커 : RED/BLUE", 지도 탭 → 좌표로 이동 + 좌표 표시, InfoWindow 탭 → 닫기. iOS 핸들러가 좌표 재사용 시 이전 marker 참조를 해제하도록 수정(Android 와 대칭). - 마커 탭 이벤트 소비 동작 변경 — 마커 탭 시 마커 클릭 리스너(
onMarkerTap)만 발생하고 지도 클릭 리스너(onMapTapped)로는 더 이상 전파되지 않도록 수정(Android·iOS 네이티브 리스너가 탭을 소비). 기존에는 두 이벤트가 동시에 발생했으므로, 마커 탭과 지도 탭을 함께 구독하던 앱은 동작을 확인할 것. / Marker taps are now consumed by the marker listener and no longer propagate to the map click listener on both platforms.
셰이프 전역 Z-Index · 마커 겹침 정책 (2026-06-02) #
- Global Z-Index —
Marker/Polyline/Polygon/Circle에int? globalZIndex추가. 셰이프 종류·지도 심볼/배경 대비 표출 우선순위를 제어한다.null(기본)이면 SDK 기본값(마커 1000 · 폴리곤/폴리라인/원 -1000) 유지, 값 지정 시setGlobalZIndex. 직렬화는 null-aware(미지정 시 키 생략) — 양 플랫폼 핸들러는 값이 있을 때만 적용. - InvMarker Overlap —
Marker에allowOverlapTitle(isAllowOverlapTitle)·allowOverlapSymbols(isAllowOverlapSymbols) 추가 (기존allowOverlap=isAllowOverlapMarkers유지). 3종 모두 SDK 기본true. 마커 겹침 시 아이콘/타이틀/심벌 표출 정책을 개별 제어. - Example
GlobalZIndexScreen(원+폴리라인 우선순위 토글) ·MarkerOverlapScreen(촘촘한 마커 + 3종 토글) 신규 (셰이프) — NativeGlobalZIndexActivity/InvMarkerOverlapActivity미러링. 셰이프 카테고리가 Native 메뉴(InvMarker Overlap·Global Z-Index 포함)와 정합.
지도 제한 · 심볼 배율 + Example 메뉴 설명 (2026-06-02) #
- Map Restriction —
InaviMapsController.setMapRestriction({bounds, minZoom, maxZoom})/clearMapRestriction()추가. 카메라 이동 가능 영역(LatLngBounds)과 줌 범위를 제한한다. AndroidinaviMap.constraintBounds/setMinZoom/setMaxZoom, iOSmapView.constraintBounds/minimumZoomLevel/maximumZoomLevel사용. 해제 시 Android 는InvConstants.BOUNDS_KOREA/MINIMUM_ZOOM/MAXIMUM_ZOOM, iOS 는 전국 영역 좌표 + 기본 줌 범위(1~21)로 복원. 전달한 인자만 적용(나머지 유지). - Map Symbol Scale —
InaviMapsController.setSymbolScale(double)/getSymbolScale()+MapOptions.symbolScale초기 옵션(기본 1.0) 추가. 지도 라벨·POI 심볼 배율 조절. Android·iOSsymbolScaleproperty. 0 이하 값은 0.1 로 clamp. - Example
MapRestrictionScreen·MapSymbolScaleScreen신규 (지도 옵션) — NativeMapRestrictionActivity/MapSymbolScaleActivity미러링. 이로써 지도 옵션 카테고리는 Map Custom Style(인증 확장 필요)만 남고 Native 메뉴와 정합. - Example 메뉴에 영문 타이틀 + 한국어 설명(subtitle) 추가 —
FeatureEntry.description필드 신설, 각 항목 설명을 Native Demostrings.xml한국어 표기로 통일(예: Map Type / 지도 타입, Map Restriction / 지도 제한).FeatureListScreen타일이subtitle로 설명 표출 — Native Demo 메뉴와 동일한 2단 표기. - 폴리라인 점선↔실선 토글 Android 회귀 수정 — Android
InvPolyline.setPattern()빈 배열 호출이IllegalArgumentException("pattern must be greater than 2")을 던져 ① 실선 폴리라인 추가 실패(Map Restriction 경계 박스 미표출) ② 점선→실선 미전환을 유발하던 버그. 수정: 빈 패턴은setPattern미호출(실선 = SDK 기본), 점선→실선 전환은 폴리라인 재생성으로 처리. 이전 "M4 회귀 수정"의 가정("빈 배열 전달 시 SDK 가 실선 처리")이 Android 에서 틀렸던 점 정정 (iOS 는patternproperty 가 빈 배열을 허용해 정상).
지도 유형 (Map Type, 2026-06-02) #
MapTypeenum 신규 —normal(0) ·hybrid(1) ·satellite(2) ·normalWithHillshade(3) ·hybridWithHillshade(4) ·satelliteWithHillshade(5). 선언 순서(index)가 양 플랫폼 네이티브 ordinal(AndroidInaviMap.MapType/ iOSINVMapType)과 1:1 로 일치하며 그대로 직렬화된다.MapOptions.mapType필드 추가 (기본값MapType.normal) — PlatformView 생성 시 초기 유형으로 1회 적용.toMap()반환 타입이Map<String, bool>→Map<String, Object>로 확장됨.InaviMapsController.setMapType(MapType)/getMapType() → MapType추가 — 다른MapOptions항목과 달리 SDK 가 런타임 변경을 정식 지원하므로 PlatformView 재생성 없이 실행 중 유형 전환 가능. AndroidinaviMap.mapType· iOSmapView.mapType사용.- Example
MapTypeScreen신규 (지도 옵션) — 6종 유형을 칩으로 전환하며setMapType런타임 변경 시연 (NativeMapTypeActivity미러링). - 단위 테스트 추가 —
MapTypeindex 매핑 ·MapOptions.mapType직렬화/copyWith/동등성 ·setMapType/getMapType채널 메서드명·인자·역매핑·폴백.
Example 메뉴 Native Demo 1:1 미러링 + 신규 화면 2종 (2026-06-02) #
example/lib/features.dart메뉴를 본 SDK Android Native iNavi Maps Demo 기준으로 재정렬 — 카테고리 순서·이름(지도 · 셰이프 · 클러스터링 · 카메라 · 지도 옵션 · 클릭 이벤트 · 위치 · 기타) 및 항목 라벨을 Native 영문 표기(InvMarker · InvPolyline · Camera Move · Projection …)로 통일. 기존 자매 플러그인 미러링에서 Native 미러링으로 전환 (마스터 계획 §9.1).클릭 이벤트카테고리 신설 — Map Click · Shape Click 을 지도/셰이프 카테고리에서 분리.- Example
MapPaddingScreen신규 (지도 옵션) —InaviMapsController.setPadding으로 25/25/100/100 패딩 토글 + 패딩 영역 오버레이 시각화 + 중심 재정렬 (NativeMapPaddingActivity미러링). - Example
CameraUpdateBuilderScreen신규 (카메라) — Target/Zoom/Tilt/Bearing 토글 선택 후getCameraPosition으로 현재 값을 읽어 델타를 더한CameraUpdate.newCameraPosition으로 이동 (NativeCameraUpdateBuilderActivity의 composite builder 동등 재현, 신규 네이티브 API 없이 구현). - 본 플러그인이 아직 미지원하는 Native 항목(InvRoute · Global Z-Index · Map Custom Style · Map Restriction · Map Symbol Scale · InvMarker Overlap · Location Icon · IndoorMap · Pick POIs)은 메뉴에서 제외 — 신규 네이티브 API 필요 (마스터 계획 §9.1.1 표로 분리). (Map Type 은 이후 구현되어 메뉴에 추가됨)
M7 — 좌표계 변환 + Projection (2026-06-01) #
CoordinateSystemTypeenum 신규 —katec(0) ·tm(1) ·utmk(2) ·grs80(3). ordinal 이 채널로 직렬화되므로 순서 고정.CoordinatePoint {x, y}모델 신규 — 투영 좌표계 변환 결과(KATEC/TM/UTM-K 는 미터 easting/northing, GRS80 은 경도/위도).InaviMapsController.convertFromWgs84({latitude, longitude, to}) → CoordinatePoint추가 — WGS-84 → KATEC/UTM-K/TM/GRS80 단방향 변환. Native Demo (CoordinatesConversionActivity) 미러링이며 역방향(toLatLng/convertToWgs84)은 노출하지 않는다. 위경도 범위([-90,90]/[-180,180]) 초과 시ArgumentError.InaviMapsController.latLngToScreenLocation(Coordinate) → Offset?/screenLocationToLatLng(Offset) → Coordinate?추가 — 화면 좌표(논리 px) ↔ 지도 좌표 양방향 Projection. SDKprojection.getPointFromLatLng/getLatLngFromPoint(Android) ·projection.point(from:)/latlng(from:)(iOS) 사용.- density/scale 처리 — Android 는 SDK PointF 가 physical px 이므로
*density(screen→map) //density(map→screen) 보정, iOS 는 CGPoint 가 logical point(== Flutter 논리 px)이므로 보정 없음. 기존 M3 클릭 이벤트 핸들러와 동일 컨벤션. - Example
CoordinatesConversionScreen·ProjectionScreen추가 (기타카테고리) — Native Demo 미러링: 지도 중앙 crosshair 의 WGS84 좌표 실시간 표시 + 4좌표계 변환 다이얼로그 / 화면 좌표 ↔ 지도 좌표 실시간 표시. - 단위 테스트 12건 추가 (누계 83) —
CoordinatePoint직렬화 ·CoordinateSystemTypeordinal · 3개 컨트롤러 메서드의 채널 메서드명/인자/범위 검증.
M6 — 지도 옵션 (제스처 + UI 컨트롤, 2026-06-01) #
MapOptionsDart 모델 신규 — 9 필드 (scrollGesturesEnabled·zoomGesturesEnabled·tiltGesturesEnabled·rotateGesturesEnabled·compassVisible·scaleBarVisible·zoomControlVisible·locationButtonVisible·logoClickEnabled).InaviMapsView.mapOptions파라미터 추가 — PlatformView 생성 시 native 에 1회 전달되어 적용. runtime mutation 미지원 (본 SDK 한계) — 재적용이 필요하면 widgetkey를 바꿔 PlatformView 재생성.- 본 SDK 실제 API 기준으로 자매 플러그인의
logoVisible대신logoClickEnabled채택 — AndroidUiSettings.setLogoClickEnabled, iOSInaviMapView.isLogoClickEnabled. 비활성화 시 호스트 앱이 별도 라이선스/법적 고지 페이지를 직접 제공해야 한다 (SDK 약관 §책무). - Example
MapOptionsScreen추가 — 9 토글 + 변경 시 PlatformView 재생성 패턴 데모.
M4 폴리라인 점선↔실선 토글 회귀 수정 (2026-06-01) #
updatePolylines핸들러의if (pattern.size >= 2)(Android) /if a.pattern.count >= 2(iOS) 가드가 빈 배열을 무시하여, 캐시된 polyline 인스턴스의 점선 패턴이 reset 되지 않던 버그 수정. 가드 제거 후 빈 배열도 그대로 SDK 에 전달 → SDK 가 패턴 해제(실선) 로 처리. 자매 플러그인 패턴 미러링.- 폴리라인 데모 화면 (
example/lib/screens/shape/polyline_screen.dart) 의 토글 FAB 아이콘을Icons.more_horiz(점선 — ● ● ●) /Icons.horizontal_rule(실선 — ━) 로 변경하여 점선/실선 시각적 의미 명확화.
Android PlatformView 렌더링 모드 변경 (ADR-0004, 2026-06-01) #
InaviMapsView의 Android 분기를 단순AndroidView(Virtual Display) 에서PlatformViewLink+AndroidViewSurface+PlatformViewsService.initExpensiveAndroidView(= TLHC, Texture Layer Hybrid Composition) 로 변경. iOS 측은 변경 없음.- 동기 — iOS 와 달리 Android 에서는 지도 회전 시 SDK 가 자동 표출하는 compass overlay 가 보이지 않던 증상 보고. 원인은 SDK 기본값(양 플랫폼 모두 표출 ON)이 아니라 PlatformView 합성 모드 — Virtual Display 는 SDK 가 동적으로 추가하는 child view (compass · logo · scale bar · info-window popup 등) 를 보존하지 않는다. 자매
inavi-global-map-sdk-flutter-plugin의 동일 패턴 미러링. - 부가 효과 — 향후 SDK overlay UI 변경에 대해 합성 누락 위험 제거. 호스트 Activity 는 그대로
FlutterActivity사용 (추가 제약 없음). - 사용자 API 변경 없음 —
gestureRecognizers파라미터는 그대로AndroidViewSurface로 위임.
UserTrackingMode.none 의미 통일 (2026-06-01) #
UserTrackingMode.none(ordinal 0) 의 의미를 "위치 점 숨김 + 추적 완전 비활성화" 로 명확화. 기존 Dart doc 은 "위치 점 보임 + 카메라 추적 안 함" 이라고 적혀 있었으나 Android 실제 동작은 위치 점 숨김이었고, iOS 는.noTracking로 매핑되어 위치 점이 보이는 비대칭 상태였다.- iOS
MethodChannelHandler.displayUserTrackingMode에서 ordinal 0 →.none매핑으로 변경 (Android 와 대칭). 카메라 추적 없이 위치 점만 표시하려면UserTrackingMode.noTracking사용.
iOS MapReady 이벤트 race condition 수정 (2026-06-01) #
InaviMapsView가initState()에서InaviMapsSdk.onInit스트림을 미리 구독하고,_onPlatformViewCreated이전에 도착한MapReady이벤트를_bufferedReady에 보관해 viewId 확정 후 처리하도록 변경. 두 번째 이후 지도 화면 진입 시 iOSPlatformView.init()에서 즉시 발신되는map.ready이벤트가 Dart 구독 등록 전에 도착해 손실되던 문제 해결 →onMapCreated콜백 미수신 /_controller == null→ 모든 기능 무반응 증상 제거.
M5 — 사용자 위치 (sibling-port Phase D, 부분 이식) #
리뷰 반영 (2026-05-28, docs/reviews/2026-05-28-m5-user-location-review.md):
-
P1 수정 —
location.permissionDeniedenvelope 을ListenerBridge.initSink(event/init) 대신ListenerBridge.sendMapEvent(viewId, ...)(event/map) 로 발신. DartInaviMapsEventDispatcher는 event/map 만 구독하므로 기존 코드로는controller.onLocationPermissionDeniedStream 에 도달하지 못하던 라우팅 버그를 해결. Android/iOS 양쪽 동일 변경. -
P2 수정 — PlatformView dispose 시 위치 cache 정리 hook 추가.
ListenerBridge에addViewDisposeCallback((Int) -> Unit)등록점을 두고,unregisterMap(viewId)가 등록된 콜백을 fanout.MethodChannelHandler가attach()시 위치 cache(locationEnabledViewIds/locationModeCache/lastKnownLocations/locationProviders) 정리 콜백을 등록 → view 재생성이 잦은 화면에서의 메모리 leak 가능성 제거. iOSListenerBridge.lastKnownLocations도unregisterMap에서 함께 정리. -
iOS 권한 다이얼로그 미표출 버그 수정 —
example/ios/Podfilepost_install블록에GCC_PREPROCESSOR_DEFINITIONS << 'PERMISSION_LOCATION=1'매크로 추가.permission_handleriOS 구현이 컴파일 타임 매크로로 권한 종류를 활성화하기 때문에, 누락 시Permission.locationWhenInUse.request()가 no-op 으로 컴파일되어 다이얼로그가 표출되지 않던 문제 해결. 자매inavi_global_map_flutter의 Podfile 패턴 미러링. -
LocationOptions/LocationIcon/UserTrackingModeDart 모델 신규 — 자매 플러그인inavi_global_map_flutter의 동일 구조를 본 컨벤션(InaviMaps*)으로 이식 -
InaviMapsController에 위치 API 추가 —updateLocationOptions(LocationOptions?),setTrackingMode(UserTrackingMode),getTrackingMode(),getCurrentLocation(), StreamonLocationTap/onLocationPermissionDenied -
InaviMapsView에locationOptions파라미터 추가 —didUpdateWidget에서updateLocationOptions자동 호출,LocationOptions.onLocationTap콜백은 View 가 책임 -
InaviMapsEventDispatcher에locationTap/locationPermissionDeniedStream 분기 +removeView정리 -
채널 키 3-way 동기화 —
location.tap/location.permissionDenied(Dart + Android + iOS) -
Android —
MethodChannelHandler에FusedLocationProvider(com.inavi.mapsdk.maps.FusedLocationProvider) +inaviMap.locationProvider+userTrackingModeproperty 패턴 적용.hasLocationPermission가드 +addOnLocationChangedListener캐시.Plugin에서activityProvider주입 -
iOS —
MethodChannelHandler에mapView.userTrackingModeproperty +displayUserTrackingMode(fromOrdinal:)헬퍼(.none→.noTracking승격),CLLocationManager().authorizationStatus권한 체크.InaviMapViewProxy에mapView(_:didUpdateUserLocation:)delegate 추가 (위치 캐시) -
Example 앱 —
permission_handler ^11.0.0의존성 추가(ADR-0013),LocationPermissionMixin신규(Permission.locationWhenInUse래핑),UserTrackingModeScreen신규(4 추적 모드 ChoiceChip + 권한 요청 버튼 +onLocationPermissionDeniedSnackBar) -
단위 테스트 추가 —
UserTrackingModeordinal(1),LocationIcontoMap/copyWith/equality/inequality(5),LocationOptionstoMap/equality/copyWith(5) — 총 11건 추가, 누계 66개 통과 -
본 SDK 한계 메모 — Maps SDK 0.21.1 은 자매 Global Maps SDK 의
LocationIcon(image/circleRadius/circleColor 등) 커스터마이징 API 를 미문서화 상태로 제공 안 함. DartLocationIcon옵션은 받아 두지만 native 측에서 적용되지 않으며, 향후 SDK 업데이트 시 확장 지점이 된다 —LocationIconScreen화면 미구현 (follow-up) -
본 SDK 한계 메모 —
onLocationTap(위치 점 탭 콜백) 도 본 SDK 미지원. Stream 자체는 channel 인프라로 보존하되 native 가 발신할 일이 없다 (follow-up: SDK 업데이트 시 활성화)
M4 — 마커/도형/클러스터 (sibling-port Phase C) #
- 도형 모델 —
Polyline/Polygon/Circle/LineCap/LineJoin+InaviMapsController.updatePolylines/updatePolygons/updateCirclesAPI - 마커 —
Marker/MarkerIcon(AssetMarkerIcon/BuiltInMarkerIcon) /BuiltInMarkerColor모델 +updateMarkersAPI +onMarkerTapStream - InfoWindow —
InfoWindow모델 +updateInfoWindowsAPI +onInfoWindowTapStream - Clustering —
ClusterItem/ClusterOptions/ClusterTapEvent/ClusterItemTapEvent모델 +setClusterItems/clearClusterItemsAPI +onClusterTap/onClusterItemTapStream asset_manifest_cache.dart신규 —AssetMarkerIconresolution-aware variant 로드 (ensureLoaded게이트)- 채널 키 3-way 동기화 —
shape.click/marker.tap/infoWindow.click/cluster.tap/clusterItem.tap - Android —
ListenerBridge.kt/MethodChannelHandler.kt에 도형·마커·InfoWindow·Cluster 핸들러 추가 (InvMarker/InvPolyline/InvPolygon/InvCircle/InvInfoWindow/ClusterManager) - iOS —
MethodChannelHandler.swift동등 구현 (INVMarker/INVPolyline/INVPolygon/INVCircle/INVInfoWindow/INVClusterManager) - Example 앱 화면 8종 신규 — 도형 시연(Polyline/Polygon/Circle), 마커 시연(Marker/MarkerOverlap), InfoWindow, Clustering, 도형 클릭 이벤트
- 단위 테스트 추가 — 모델 직렬화/역직렬화 round-trip
M3 — 지도 클릭 이벤트 (sibling-port Phase B) #
MapClickEvent모델 신규 —coordinate(Coordinate)+screenPoint(Offset)+fromMapfactoryInaviMapsController에onMapClick/onMapLongClick/onMapDoubleClickStream getter 추가InaviMapsEventDispatcher에 click stream 분기 (map.click/map.longClick/map.doubleClick)- Android
ListenerBridge.kt—mapClickListener/mapLongClickListener/mapDoubleClickListenerfactory 추가 (physical px → logical px 변환) - Android
InaviMapsPlatformView.kt—setOnMapClickListener/setOnMapLongClickListener/setOnMapDoubleClickListener등록 +dispose시 null 해제 - iOS
ListenerBridge.swiftproxy —didTapMapView/didLongTapMapView/didDoubleTapMapViewdelegate 메서드 추가 (INVMapViewDelegate) - 채널 키 3-way 동기화 —
typeMapClick/typeMapLongClick/typeMapDoubleClick(Dart + Android + iOS) - Example 앱
MapClickEventScreen신규 — 탭/길게 탭/두 번 탭 토글 칩 + SnackBar 시연 - 단위 테스트 추가 —
MapClickEvent.fromMap(4건)
M2-R2 — fitBounds + LatLngBounds (sibling-port 첫 적용) #
CameraUpdate.fitBounds(LatLngBounds, padding)factory +LatLngBounds모델 신규 (자매 플러그인inavi_global_map_flutter의 동일 구조 이식)- Android
MethodChannelHandler.kt에 fitBounds case 추가 —com.inavi.mapsdk.geometry.LatLngBounds+ density 기반 padding px 변환 - iOS
MethodChannelHandler.swift에 fitBounds case 추가 —INVLatLngBounds+UIEdgeInsetsper-side padding 보존 - Example 앱
CameraFitBoundsScreen신규 — 강남역↔청주 두 위치 viewport fit 토글 (FAB) - 단위 테스트 추가 —
LatLngBounds(3건),CameraUpdate.fitBounds toMap(1건)
Example — Native SDK 데모 미러링 메뉴 시스템 (Example app menu) #
- Example 앱에 Native SDK 데모 미러링 메뉴 시스템 도입 —
FeatureListScreen+FeatureEntry(카테고리 그룹 + 타일 네비게이션) - Example 화면 분리 —
InaviMapViewScreen(지도 표출, 강남역 기본),CameraMoveScreen(두 위치 왕복 + 4종 애니메이션),CameraEventsScreen(실시간 위치/Zoom/Tilt/Bearing + 이동/취소 FAB) - 공유 데모 상수 —
m1_demo_data.dart(강남역 / 청주 좌표 + 기본 카메라 위치) main.dart단순화 —MaterialApp+FeatureListScreen진입점,AuthFailure다이얼로그 라우팅- FitBounds / CameraUpdateBuilder 화면은
CameraUpdateSDK 확장(M2-R2 / M2-R3) 완료 후 추가 예정
M2 — 카메라 제어 (Camera control) #
InaviMapsController(per-view 컨트롤러) —InaviMapsView.onMapCreated콜백으로 전달animateCamera(CameraUpdate, duration, animation)/moveCamera(CameraUpdate)getCameraPosition()/cancelTransitions()setPadding(EdgeInsets)— Android는 dp→px 변환, iOS는 logical pt 그대로 (contentInset)onCameraMove/onCameraIdle이벤트 Stream — viewId별 broadcast
- Public 모델 —
Coordinate,CameraPosition,CameraUpdate(sealed),CameraAnimation,CameraMoveReasonKindCameraAnimation4값:none, linear, easing, flyCameraUpdatefactory:newCameraPosition,targetTo,targetAndZoom,zoomTo,zoomBy,zoomIn,zoomOutCameraMoveReasonKind5값:unknown, gesture, api, control, locationChanged
InaviMapsView.onMapCreated콜백 — 네이티브map.ready도달 이후에만 호출 (ADR-0001)- 채널 키 추가 —
event/mapenvelope 의type디스크리미네이터camera.move/camera.idle(3-way 동기화) - Android —
MethodChannelHandler.kt분리 +ListenerBridge에 카메라 listener factory + SDK reason int → Dart ordinal 정규화 switch - iOS —
MethodChannelHandler.swift분리 +InaviMapViewProxy: INVMapViewDelegateper-view 프록시 +regionIsChangingWithReason:/mapViewDidBecomeIdle:라우팅 + reason 정규화 switch - Codec 헬퍼 — Android
DtoCodec.kt(MethodCall.argMap()), iOSDtoCodec.swift(argMap(_:)) - ADR-0001 (
onMapCreatedpostmap.ready) · ADR-0003 (camera reason 명시 매핑) · ADR-0005 (camera animation 공통 Easing 표면) — ADR-0005는 ADR-0003의CameraAnimation5값 정책 supersede
M1 — 지도 표시 (Map display) #
- 빈 지도 PlatformView 표출 — Android
InvMapView(FrameLayout) 직접 호스팅 +DefaultLifecycleObserver위임, iOSInaviMapView(UIView) 직접 노출 InaviMapsSdk싱글톤 진입점 — broadcastStream<InitEvent> onInit노출InaviMapsViewStatefulWidget — AndroidAndroidView/ iOSUiKitViewInitEventsealed class —AuthSuccess/AuthFailure(errorCode, errorMessage)/MapReady(viewId)- SDK 인증 콜백 라우팅 — Android
InaviMapSdk.authFailureCallback/authSuccessCallback, iOSINVMapSdk.delegate(INVMapSdkDelegate) ListenerBridge(Androidobject/ iOSsingleton) — SDK 콜백 →EventChannel메인 스레드 보장 + 큐잉EventChannelHandler—com.inavi.maps/event/init,com.inavi.maps/event/map라우터- Example 앱 —
InaviMapsView+ Status 라벨로 인증·map.ready 시각화
0.0.1 — 2026-05-27 #
M0 Scaffold (initial) #
- 프로젝트 스캐폴딩 (
flutter create --template=plugin --platforms=android,ios) - Android 패키지
com.inavi.maps.flutter정리 - Android Maven repo (
https://repo.inavi.com/artifactory/maps) 및 SDK 의존성 (com.inavi.mapsdk:inavi-maps-sdk:0.21.1) 연결 - iOS Pod 의존성 (
inavi-maps-sdk~> 0.21.0) 연결 - 채널 키 3-way 동기화 (Dart / Kotlin / Swift) —
com.inavi.maps/prefix - Example 앱에 AppKey 메타데이터 (Android
AndroidManifest.xml/ iOSInfo.plist) 자리 마련 - 자매 플러그인
inavi_global_map_flutter컨벤션 미러링 docs/plans/flutter-plugin-development-plan.md— 마스터 플랜 작성