Flutter에서 네이버 지도를 열 수 있게 해주는 플러그인입니다.
Flutter 프로젝트에서 네이버 지도를 표시하는 플러그인은 Android와 iOS를 지원합니다.
설치하기 위해서
플러그인은 네이버 클라우드 플랫폼 – 지도 안드로이드와 iOS 환경에서 제공하는 지도 서비스를 표시해주는 플러그인입니다.
- 네이버 클라우드 플랫폼에서 콘솔의 AI/애플리케이션 서비스 > AI/NAVER API > 애플리케이션에서 애플리케이션을 등록합니다.
- 등록된 어플리케이션을 선택하고 Client ID 값을 확인하여 변경 화면에서 Maps가 선택되어 있는지 확인합니다.
pubspec.yaml에 플러그인 종속성 작성
dependencies:
naver_map_plugin: ^0.9.6
경고
- 카드에서 제공하는 기본 컨트롤러가 잘 안되네요(이유를 모르겠습니다)
- 안드로이드에서는 현재 위치 버튼만 정상적으로 동작
참고(안드로이드)
- 한국인
- 네이버에서 제공하는 SDK의 경우 기본적으로 GLSurfaceView를 사용하여 Android에서 지도를 표시합니다.
네이버 지도 SDK 바이너리의 부정확한 원인으로 인해 핫 리로드 시 앱 크래시가 발생합니다.
다시 로드하지 않는 릴리스 버전에서는 더 나은 성능의 GLSurfaceView를 사용하고 그렇지 않으면 즉석에서 다시 로드할 수 있는 TextureView를 사용하십시오.
- 네이버에서 제공하는 SDK의 경우 기본적으로 GLSurfaceView를 사용하여 Android에서 지도를 표시합니다.
- 영어
- NaverMap SDK는 기본적으로 GLSurfaceView를 사용하여 Android에서 지도 보기를 지웁니다.
핫 리로드는 불명확한 이유로 Naver Map SDK 바이너리에서 앱 충돌을 일으킵니다.
게시된 버전을 생성할 때 이 플러그인은 더 나은 성능을 위해 GLSurfaceView를 사용하고 그렇지 않으면 TextureView를 사용하여 핫 리로드를 노출합니다.
- NaverMap SDK는 기본적으로 GLSurfaceView를 사용하여 Android에서 지도 보기를 지웁니다.
안드로이드 시작하기
네이버 클라우드 플랫폼 – 안드로이드 시작 가이드
AndroidManifest.xml에 지정됨
<manifest>
<application>
<meta-data
android:name="com.naver.maps.map.CLIENT_ID"
android:value="YOUR_CLIENT_ID_HERE" />
</application>
</manifest>
내비게이션 지도에서 현재 위치 조회 기능을 사용하려면 AndroidManifest.xml에 권한을 부여해야 합니다.
<manifest>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
</manifest>
또한 Android API Level 23(M) 이상에서는 동적 권한이 필요합니다.
다음은 동적 권한을 요청하는 샘플 코드입니다.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) !
= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String(){Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
}
iOS 시작하기
네이버 클라우드 플랫폼 – iOS 시작 가이드
대용량 파일을 받기 위해 자식-lfs 설치가 필요합니다.
$ brew install git-lfs
그리고 git-lfs를 사용하기 위해 다음 명령어를 입력합니다.
lfs가 활성화되지 않은 경우 포드 간에 종속성이 다운로드되지 않습니다.
$ git lfs install
info.plist에 지정됨
<dict>
<key>NMFClientId</key>
<string>YOUR_CLIENT_ID_HERE</string>
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
내비게이션 지도에서 현재 위치에 대한 검색 기능을 사용하려면 info.plist에 권한을 지정합니다.
<dict>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>(USAGE PERPOSE)</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>(USAGE PERPOSE)</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>(USAGE PERPOSE)</string>
</dict>
이후 AppDelfate에서 위치 권한을 획득하는 예시입니다.
if (CLLocationManager.locationServicesEnabled()) {
switch CLLocationManager.authorizationStatus() {
case .denied, .notDetermined, .restricted:
self.manager.requestAlwaysAuthorization()
break
default:
break
}
}
샘플 코드
import 'package:flutter/material.dart';
import 'package:naver_map_plugin_example/base_map.dart';
import 'package:naver_map_plugin_example/circle_map.dart';
import 'package:naver_map_plugin_example/padding_test.dart';
import 'package:naver_map_plugin_example/marker_map_page.dart';
import 'package:naver_map_plugin_example/path_map.dart';
import 'package:naver_map_plugin_example/polygon_map.dart';
import 'package:naver_map_plugin_example/text_field_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
List<String> menuText = (
'기본 지도 예제',
'마커 예제',
'패스 예제',
'원형 오버레이 예제',
'컨트롤러 테스트',
'폴리곤 예제',
'GLSurface Thread collision test',
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: menuText
.map((text) => GestureDetector(
onTap: () => _onTapMenuItem(text),
child: Container(
margin: EdgeInsets.symmetric(vertical: 8),
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
border: Border.all(color: Colors.indigo),
),
child: Text(
text,
style: TextStyle(
color: Colors.indigo,
fontSize: 12,
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
),
))
.toList(),
),
),
);
}
_onTapMenuItem(String text) {
final index = menuText.indexOf(text);
switch (index) {
case 0:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BaseMapPage(),
));
break;
case 1:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MarkerMapPage(),
));
break;
case 2:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PathMapPage(),
));
break;
case 3:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CircleMapPage(),
));
break;
case 4:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PaddingTest(),
));
break;
case 5:
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PolygonMap(),
));
break;
case 6:
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => TextFieldPage(),
));
}
}
}
원천: https://pub.dev/packages/naver_map_plugin