일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 플러터 구글맵
- ios 시뮬레이터 location
- ios 시뮬레이터 위치 설정
- 안드로이드 에뮬레이터
- android emulator
- 안드로이드 에뮬레이터 설정
- ios 시뮬레이터 위치
- ios 시뮬레이터 features
- android simulator
- 플러터 구글맵api
- 플러터 위치권한요청
- android emulator location setting
- ios 시뮬레이터 gps
- ios simulator location setting
- 플러터 구글 지도
- android emulator gps
- error: the plugin "google_maps_flutter_ios" requires a higher minimum ios deployment version than your application
- 구글 map api key
- 플러터 위치권한
- error: the plugin "google_maps_flutter_ios"
- ios 시뮬레이터
- ios simulator gps
- ios 시뮬레이터 위치변경
- 안드로이드 에뮬레이터 위치
- flutter 개발환경
- 안드로이드 에뮬레이터 위치 설정
- 구글 map api 받는법
- ios 시뮬레이터 설정
- flutter 설치
- android emulator location
- Today
- Total
planX
[Flutter] google map api 사용 예제 본문
오늘은 google map api를 사용한 앱을 만들어 보겠습니다.
일단, api가 사용 가능하다는 가정 하에 포스팅을 진행하겠습니다.
만약 내가 google map api가 없는데 하시면 아래 포스팅 보시고
api를 받으신 다음 이 글을 참고해주시면 되겠습니다.
[API] Google map api key 받기
📍Google Map API Key 받기준비물 : 구글 계정 1. 구글 클라우드 접속 https://cloud.google.com/ 클라우드 컴퓨팅 서비스 | Google Cloud데이터 관리, 하이브리드 및 멀티 클라우드, AI와 머신러닝 등 Google의 클
oxxo.tistory.com
1. Flutter 프로젝트 만들기
📍 터미널에 프로젝트 만들 위치로 이동하고 명령어 입력
flutter create google_map_api
2. VScode로 Flutter 프로젝트 열기
📍 VScode 열기 -> open -> google_map_api 폴더 열기
3. 패키지 추가 (geolocator, google_maps_flutter)
📍 Terminal -> New Terminal
📍 아래 명령어 각각 terminal 에 복붙
https://pub.dev/packages/geolocator/install
geolocator install | Flutter package
Geolocation plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API for generic location (GPS etc.) functions.
pub.dev
flutter pub add geolocator
https://pub.dev/packages/google_maps_flutter/install
google_maps_flutter install | Flutter package
A Flutter plugin for integrating Google Maps in iOS and Android applications.
pub.dev
flutter pub add google_maps_flutter
설치가 제대로 됐다면, pubspec.yaml에서 설치된 것을 확인할 수 있다.
geolocator: ^13.0.1
google_maps_flutter: ^2.9.0
4. 안드로이드 네이티브 설정
📍 android/app/src/main/AndroidManifest.xml - 구글 api 키 등록
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/>
- Android 앱에서 정확한 위치 정보를 얻기 위해 필요한 권한을 요청하는 선언
- 이 권한은 GPS와 같은 고정밀 센서를 사용해 사용자의 정확한 위치(수 미터 이내)를 가져올 수 있다.
- 이 권한이 있어야 앱이 Google Maps 등에서 사용자의 정확한 현재 위치를 표시할 수 있다.
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="자신의_API_KEY"/>
5. iOS 네이티브 설정
📍 ios/Runner/AppDelegate.swift - 아래 사진을 참고하여 코드를 수정해주세요.
import GoogleMaps
GMSServices.provideAPIKey("자신의_API_KEY")
📍 ios/Runner/Info.plist - 아래 사진을 참고하여 코드를 수정해주세요.
<key>NSLocationWhenInUseUsageDescription</key>
<string>앱 사용 중에 위치 정보를 이용하여 서비스를 제공합니다.</string>
<key>NSLocationWhenAlwaysUsageDescription</key>
<string>앱이 백그라운드에서도 위치 정보를 이용하여 더 나은 서비스를 제공합니다.</string>
7. 추가 설정
위 설정대로 테스트를 해봤는데 오류가 있네요.
📍 Xcode - Open Existing Project - 자신의 프로젝트/ios/Runner.xcworkspace를 open해주세요.
📍 Runner - Runner - General - Minimum Deployments : 14.0 으로 변경
📍 ios/Podfile 에서 platform의 주석을 해제하고, '14.0'으로 수정
📍 terminal에 명령어 한 줄씩 입력
flutter clean
flutter pub get
cd ios
pod install
8. 예제 내용 설명
간단한 API 사용 예제이기 때문에 디자인은 최소화하여
📍 AppBar() + 지도 + 현재 위치 버튼
📍 권한을 요청하고 허가 받는 코드
9. 초기 코드
📍 저도 시작하지 얼마 안 된 쌩초보여서 ! 참고만 해주세요 !
📍 코드는 일단, main.dart와 home_screen.dart로 만들어줬어요.
(현재 코드 블럭에 dart언어가 없네요;; ㅋㅋㅋㅋㅋ 이건 후에 제가 다시 설정해볼게요)
📍 main.dart
import 'package:flutter/material.dart';
import 'package:google_map_api/home_screen.dart';
void main() {
runApp(const MaterialApp(
home: HomeScreen(),
));
}
📍 home_screen.dart
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Maps'),
),
body: const Text('hello world'),
);
}
}
📍 iOS simulator
📍 지도를 추가하는 방법을 몰라서 일단 구글링해서 찾아봤어요.
https://codelabs.developers.google.com/codelabs/google-maps-in-flutter?hl=ko#3
Flutter 앱에 Google 지도 추가 | Google Codelabs
이 Codelab에서는 iOS 및 Android에서 고품질 네이티브 환경을 제작하기 위해 Flutter 모바일 앱 SDK를 사용하여 Google 지도 환경을 빌드합니다.
codelabs.developers.google.com
위에 링크에 제시된 코드에는 late GoogleMapController mapController; 라는게 있는데 이게 뭔지는 잘 모르겠어요.
꼭 찾아보고 기록해볼게요 :)
위도 경도를 아무거나 해서 설정해봤는데 지도가 뜨긴하네요.
GoogleMap(
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
📍 저는 Column 위젯을 사용해서 아래에 원래 자신의 위치로 돌아가는 버튼을 만드려는데 비슷한 기능을 하는 구글 지도 버튼이 있어요. 그걸 없애줄게요.
myLocationButtonEnabled: false,
📍 TextButton 만들기
body: Column(
children: [
Expanded(
child: GoogleMap(
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
myLocationButtonEnabled: false,
),
),
Expanded(
child: TextButton(
onPressed: () {},
child: const Text('현재위치'),
),
)
],
),
📍 지도와 버튼 부분 비율 변경 (지도 flex : 4, 버튼 flex : 1)
body: Column(
children: [
Expanded(
flex: 4,
child: GoogleMap(
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
myLocationButtonEnabled: false,
),
),
Expanded(
flex: 1,
child: TextButton(
onPressed: () {},
child: const Text('현재위치'),
),
)
],
),
📍 버튼을 눌렀을 때 현재 위치로 돌아가는 기능 구현
- 기기의 GPS기능이 켜져있는지 확인
- 앱내 위치 권한 허가확인, 권한이 없다면 요청
- 버튼을 클릭했을 때, 현재 위치가져오기
- 현재 위치를 지도로 보여주기
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart'; // 현재 위치 가져오기
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() {
return _HomeScreenState();
}
}
class _HomeScreenState extends State<HomeScreen> {
late GoogleMapController _mapController;
final LatLng _center = const LatLng(34.11, 111.4);
@override
void initState() {
super.initState();
_checkLocationService(); // 앱 시작 시 GPS 확인
_checkLocationPermission(); // 앱 시작 시 권한 확인
}
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
}
Future<void> _checkLocationService() async {
// 위치 서비스가 활성화 되어있는지 확인
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
print('GPS가 꺼져 있습니다. 켜주세요.');
return;
}
}
Future<void> _checkLocationPermission() async {
// 위치 권한 확인
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
}
if (permission == LocationPermission.whileInUse ||
permission == LocationPermission.always) {
print("위치 권한이 부여되었습니다.");
} else {
print("위치 권한이 없습니다.");
}
}
Future<void> _goToCurrentLocation() async {
Position currentPosition = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
),
);
_mapController.animateCamera(
CameraUpdate.newLatLng(
LatLng(currentPosition.latitude, currentPosition.longitude),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Maps'),
),
body: Column(
children: [
Expanded(
flex: 4,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
myLocationButtonEnabled: false,
),
),
Expanded(
flex: 1,
child: TextButton(
onPressed: () async {
await _goToCurrentLocation();
},
child: const Text('현재위치'),
),
)
],
),
);
}
}
📍 수정(1)
- GPS가 꺼져있다면 권한을 받아올 필요가 없음 -> GPS와 권한 한번에 확인
- Google map zoom 크기 변경 11.0 -> 15.0
- 사용자에게 메시지 전달을 위해 _showSnackBar 함수 만듦
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() {
return _HomeScreenState();
}
}
class _HomeScreenState extends State<HomeScreen> {
late GoogleMapController _mapController;
final LatLng _center = const LatLng(34.11, 111.4);
@override
void initState() {
super.initState();
_checkLocationServiceAndPermission();
}
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
}
Future<void> _checkLocationServiceAndPermission() async {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// 위치 서비스가 비활성화된 경우 사용자에게 안내
_showSnackBar("GPS가 꺼져 있습니다. 켜주세요.");
return; // GPS가 꺼져있으면 권한 확인할 필요 없음
}
// 위치 권한 확인 및 요청
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
}
if (permission == LocationPermission.whileInUse || permission == LocationPermission.always) {
print('위치 권한이 부여되었습니다.');
} else {
_showSnackBar('위치 권한이 없습니다.');
}
}
void _showSnackBar(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
),
);
}
Future<void> _goToCurrentLocation() async {
Position currentPosition = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
),
);
_mapController.animateCamera(
CameraUpdate.newLatLng(
LatLng(currentPosition.latitude, currentPosition.longitude),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Maps'),
),
body: Column(
children: [
Expanded(
flex: 4,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 15.0,
),
myLocationButtonEnabled: false,
),
),
Expanded(
flex: 1,
child: TextButton(
onPressed: () async {
await _goToCurrentLocation();
},
child: const Text('현재위치'),
),
)
],
),
);
}
}
📍 수정(2)
- 위치 권한을 거부 했을 때 설정으로 이동
- 위치를 가져오는 과정에서 오류 예외 처리 (try-catch)
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() {
return _HomeScreenState();
}
}
class _HomeScreenState extends State<HomeScreen> {
late GoogleMapController _mapController;
final LatLng _center = const LatLng(34.11, 111.4);
@override
void initState() {
super.initState();
_checkLocationServiceAndPermission();
}
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
}
Future<void> _checkLocationServiceAndPermission() async {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// 위치 서비스가 비활성화된 경우 사용자에게 안내
_showSnackBar("GPS가 꺼져 있습니다. 켜주세요.");
return; // GPS가 꺼져있으면 권한 확인할 필요 없음
}
// 위치 권한 확인 및 요청
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.deniedForever) {
_showSnackBar("위치 권한이 영구적으로 거부되었습니다. 설정에서 권한을 활성화하세요.");
return;
}
}
if (permission == LocationPermission.whileInUse ||
permission == LocationPermission.always) {
print('위치 권한이 부여되었습니다.');
} else {
_showSnackBar('위치 권한이 없습니다.');
}
}
void _showSnackBar(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
action: SnackBarAction(
label: '설정으로 가기',
onPressed: () {
Geolocator.openAppSettings(); // 앱 설정으로 가기
}),
),
);
}
Future<void> _goToCurrentLocation() async {
try {
Position currentPosition = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
),
);
_mapController.animateCamera(
CameraUpdate.newLatLng(
LatLng(currentPosition.latitude, currentPosition.longitude),
),
);
} catch (e) {
_showSnackBar('현재 위치를 가져올 수 없습니다.');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Maps'),
),
body: Column(
children: [
Expanded(
flex: 4,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 15.0,
),
myLocationButtonEnabled: false,
),
),
Expanded(
flex: 1,
child: TextButton(
onPressed: () async {
await _goToCurrentLocation();
},
child: const Text('현재위치'),
),
)
],
),
);
}
}
📍 수정(3)
- 현재 위치 마커 추가 (진짜 중요한 건데 깜빡해서 나중에 넣었어요.)
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart'; // 현재 위치 가져오기
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() {
return _HomeScreenState();
}
}
class _HomeScreenState extends State<HomeScreen> {
late GoogleMapController _mapController;
final LatLng _center = const LatLng(34.11, 111.4);
LatLng? _currentPosition;
Set<Marker> _markers = {};
@override
void initState() {
super.initState();
_checkLocationServiceAndPermission();
}
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
}
Future<void> _checkLocationServiceAndPermission() async {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// 위치 서비스가 비활성화된 경우 사용자에게 안내
_showSnackBar("GPS가 꺼져 있습니다. 켜주세요.");
return; // GPS가 꺼져있으면 권한 확인할 필요 없음
}
// 위치 권한 확인 및 요청
LocationPermission permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.deniedForever) {
_showSnackBar("위치 권한이 영구적으로 거부되었습니다. 설정에서 권한을 활성화하세요.");
return;
}
}
if (permission == LocationPermission.whileInUse ||
permission == LocationPermission.always) {
print('위치 권한이 부여되었습니다.');
} else {
_showSnackBar('위치 권한이 없습니다.');
}
}
void _showSnackBar(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
action: SnackBarAction(
label: '설정으로 가기',
onPressed: () {
Geolocator.openAppSettings(); // 앱 설정으로 가기
}),
),
);
}
Future<void> _goToCurrentLocation() async {
try {
Position currentPosition = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
),
);
// 현재 위치를 변수에 저장하고 상태 업데이트
setState(() {
_currentPosition =
LatLng(currentPosition.latitude, currentPosition.longitude);
_markers.add(
Marker(
markerId: const MarkerId('currentPosition'),
position: _currentPosition!,
),
);
});
_mapController.animateCamera(
CameraUpdate.newLatLng(
LatLng(currentPosition.latitude, currentPosition.longitude),
),
);
} catch (e) {
_showSnackBar('현재 위치를 가져올 수 없습니다.');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Maps'),
),
body: Column(
children: [
Expanded(
flex: 4,
child: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 15.0,
),
markers: _markers,
myLocationButtonEnabled: false,
),
),
Expanded(
flex: 1,
child: TextButton(
onPressed: () async {
await _goToCurrentLocation();
},
child: const Text('현재위치'),
),
)
],
),
);
}
}
우열곡절 끝에 만들어봤구만유 💡
읽어주셔서 감사합니다.