반응형

네이버지도를 플러터에서 띄울 수 있는 플러그인입니다.

Plug-in which shows naver map on flutter project support Android and iOS.

Install 

해당 플러그인은 Naver Cloud PlatForm - map 에서 제공하는 map서비스를 Android와 iOS 환경에서 보여주는 플러그인입니다.

  • Naver cloud platform 에서 콘솔의 AI·Application Service > AI·NAVER API > Application에서 애플리케이션을 등록합니다.
  • 등록한 애플리케이션을 선택해 Client ID값을 확인하고 변경 화면에서 Maps가 선택되어 있는지 확인한다.

pubspec.yaml에 plug in dependencies에 작성

dependencies:
  naver_map_plugin: ^0.9.6

Warning 

  • 지도에서 제공하는 기본 컨트롤러가 잘 작동하지 않는 문제 (이유를 찾지 못하고 있음)
  • android는 현 위치 버튼만 정상 작동

NOTICE (Android) 

  • 한국어
    • 네이버에서 제공하는 SDK의 경우 안드로이드에서 지도를 표시하기 위해 기본값으로 GLSurfaceView를 사용한다. hot reload시에 naver map SDK의 binary에서 정확하지 않은 이유로 app crash가 발생한다. reload하지 않는 release version 에서는 성능이 더 좋은 GLSurfaceView를 사용하고, 아닌 경우 hot reload가 가능한 TextureView를 사용한다.
  • English
    • NaverMap SDK use GLSurfaceView as default to flush map view in Android. At hot reload, App crash occurs in binary file of naver map SDK caused by unclear reason. if you build released version, this plug-in use GLSurfaceView for better performance, otherwise TextureView is used to make hot-reload available.

ANDROID GETTING START 

AndroidManifest.xml에 지정

<manifest>
    <application>
        <meta-data
            android:name="com.naver.maps.map.CLIENT_ID"
            android:value="YOUR_CLIENT_ID_HERE" />
    </application>
</manifest>

naver map에서 현위치탐색 기능을 사용하기 위해서는 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 GETTING START 

대용량 파일을 받기 위해 git-lfs 설치가 필요합니다.

$ brew install git-lfs

그리고 git-lfs을 사용하기 위해 다음의 커맨드를 입력해주세요. lfs 사용 설정이 안될 경우 pod를 통한 dependency가 다운로드 되지않습니다.

$ 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>

naver map에서 현위치탐색 기능을 사용하기 위해서는 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>

이후 AppDelefate에서 위치 사용권한을 획득하는 예제.

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

 

반응형

반응형

Flutter SDK 다운로드


  • 명시적이고 간편한 경로에 압축을 해제합니다.(예: c:\src\flutter)

 

Flutter 기본 환경변수 PATH 설정


  • C:\src\flutter 기준

 

Windows 명령 프롬프트에서 flutter --version 실행해보자.

  • Flutter 3.0.1 표시되면 기본 PATH가 잘 설정된 것이다.

 

Flutter 개발 환경 준비(for Android)


Windows 명령 프롬프트에서 flutter doctor 실행해보자.

  • 모든 개발 환경 준비가 잘 되어 있다면 "No issues found!" 메시지를 확인 할 수 있다.
  • 준비되지 않은 체크 리스트는 해결 방법이 친절하게 제시되니 참고해서 해결하도록 하자

 

Flutter Doctor 이슈 해결방법


Android toolchain - Some Android licenses not accepted

  • Android 라이선스만 동의하면 쉽게 해결된다.
    • flutter doctor --android-licenses 그대로 타이핑하자.


 

반응형

반응형

Flutter 전체 구성을 진단하는 명령어인 flutter doctor 실행 시 아래와 같이

Android license status unknown 에러가 발생 한다면

아래의 명령어를 실행하여 각각의 라이선스에 대하여 Accepted하면 해결 할 수 있다.

flutter doctor --android-licenses

 

반응형

+ Recent posts