본문 바로가기
프로그래밍/Flutter

[Flutter] 날씨 정보 받아오기(weather, geolocator)

by YuminK 2022. 5. 2.

개발하고 있는 프로젝트에서 날씨 정보가 ... 한 줄이 필요한데 날씨 API에다가 위치 처리를 package를 같이 연동해야 하는 형태입니다. weather 패키지에서 geolocator 패키지를 사용하길 추천하고 있습니다. 

 

weather 패키지에서는 위도, 경도 정보를 토대로 정보를 받아오는 방식과 도시 이름을 가지고 받아오는 형태가 있는데 각 사용자의 위치에 따른 처리를 하기 위해서는 geolocator 패키지를 사용하는 방식으로 가야 합니다.

 

1. 위치 정보 알아오기(geolocator)

A Flutter geolocation plugin which provides easy access to platform specific location services (FusedLocationProviderClient or if not available the LocationManager on Android and CLLocationManager on iOS).

 

Features

  • 마지막으로 알려진 위치를 얻기
  • 디바이스의 현재 위치 얻어오기
  • 지속적인 위치 업데이트 정보 얻기
  • 기기에서 위치 서비스가 활성화 되어 있는지 확인하기
  • 두 geocoordinates간 bearing을 계산(위도, 경도 가지고 거리를 받아올 수 있는 거 같네요)

 

Usage

Android 

더보기
  1. Add the following to your "gradle.properties" file:
android.useAndroidX=true
android.enableJetifier=true

 2. Make sure you set the compileSdkVersion in your "android/app/build.gradle" file to 31:

android {
  compileSdkVersion 31

  ...
}

3. Make sure you replace all the android. dependencies to their AndroidX counterparts (a full list can be found here: Migrating to AndroidX).

 

4. Permissions

AndroidManifest.xml file (located under android/app/src/main) and add one of the following two lines as direct children of the <manifest> tag (when you configure both permissions the ACCESS_FINE_LOCATION will be used by the geolocator plugin):

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

 

Starting from Android 10 you need to add the ACCESS_BACKGROUND_LOCATION permission (next to the ACCESS_COARSE_LOCATION or the ACCESS_FINE_LOCATION permission) if you want to continue receiving updates even when your App is running in the background (note that the geolocator plugin doesn't support receiving an processing location updates while running in the background):

만약 앱이 백그라운드 상태에서도 업데이트를 받고 싶으면 안드로이드 10부터 ACCESS_BACKGROUND_LOCATION 권한을 추가할 필요가 있다. (geolocator 플러그인에서는 백그라운드에서 위치 업데이트 처리를 하는 것을 지원하지 않는다.)

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

 

굳이 백그라운드까지 갈 필요는 없어서 처리하지 않겠습니다.

 

IOS

더보기

On iOS you'll need to add the following entries to your Info.plist file (located under ios/Runner) in order to access the device's location. Simply open your Info.plist file and add the following (make sure you update the description so it is meaningfull in the context of your App):

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when open.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>

 

If you would like to receive updates when your App is in the background, you'll also need to add the Background Modes capability to your XCode project (Project > Signing and Capabilities > "+ Capability" button) and select Location Updates. Be careful with this, you will need to explain in detail to Apple why your App needs this when submitting your App to the AppStore. If Apple isn't satisfied with the explanation your App will be rejected.

When using the requestTemporaryFullAccuracy({purposeKey: "YourPurposeKey"}) method, a dictionary should be added to the Info.plist file.

<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
  <key>YourPurposeKey</key>
  <string>The example App requires temporary access to the device&apos;s precise location.</string>
</dict>

The second key (in this example called YourPurposeKey) should match the purposeKey that is passed in the requestTemporaryFullAccuracy() method. It is possible to define multiple keys for different features in your app. More information can be found in Apple's documentation.

 

굳이 백그라운드까지 갈 필요는 없어서 처리하지 않겠습니다.

 

Web

더보기

The following methods of the geolocator API are not supported on the web and will result in a PlatformException with the code UNSUPPORTED_OPERATION:

  • getLastKnownPosition({ bool forceAndroidLocationManager = true })
  • openAppSettings()
  • openLocationSettings()

다음 함수들을 웹에서 못 쓴다고 합니다.

 

NOTE

Geolocator Web is available only in secure_contexts (HTTPS). More info about the Geolocator API can be found here.

 

https://pub.dev/packages/geolocator

다양한 예시들이 있는데 위치 정보만 받아오는 예제만 사용하겠습니다.

위치 정보를 받기 전에 location 권한을 입력받아야 합니다. 

import 'package:geolocator/geolocator.dart';

/// Determine the current position of the device.
///
/// When the location services are not enabled or permissions
/// are denied the `Future` will return an error.
Future<Position> _determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  // Test if location services are enabled.
  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    // Location services are not enabled don't continue
    // accessing the position and request users of the 
    // App to enable the location services.
    return Future.error('Location services are disabled.');
  }

  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      // Permissions are denied, next time you could try
      // requesting permissions again (this is also where
      // Android's shouldShowRequestPermissionRationale 
      // returned true. According to Android guidelines
      // your App should show an explanatory UI now.
      return Future.error('Location permissions are denied');
    }
  }
  
  if (permission == LocationPermission.deniedForever) {
    // Permissions are denied forever, handle appropriately. 
    return Future.error(
      'Location permissions are permanently denied, we cannot request permissions.');
  } 

  // When we reach here, permissions are granted and we can
  // continue accessing the position of the device.
  return await Geolocator.getCurrentPosition();
}

 

권한을 받은 유저라면 문제 없이 경도, 위도 값이 출력이 됩니다.

// user should grant location permissions before this function.
Future<Position> getPosition() async {
  if(!isWeb()) {
    Position? lastPosition = await Geolocator.getLastKnownPosition();
    if(lastPosition != null) {
      printLog("lastKnownPosition : " + lastPosition.toString());
      return lastPosition;
    }
  }

  var curPos = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.low);
  printLog("currentPos: " + curPos.toString());
  return curPos;
}

https://www.google.com/maps

구글 맵에서 37.4220125, -122.0840023 이런 형태로 검색해보시면 위치가 나옵니다.

에뮬레이터에서 돌리니까 구글 위치 나오네요.

 

2. 위치 정보를 토대로 날씨 받아오기(weather)

This package uses the OpenWeatherMAP API to get the current weather status as well as weather forecasts.

The weather can currently be fetched by providing a geolocation or a city name.

 

Usage

OpenWeather API를 발급 받으시면 됩니다.

https://openweathermap.org/price

 

계정 생성하시고 자신의 정보에 무료키가 나옵니다. 백만번/1달, 60회/1분으로 제한이 걸려 있기는 한데 개발 단계에서는 크게 신경쓸 필요는 없습니다.

@override
void initState() {
  super.initState();
  getWeather();
}

Future<void> getWeather() async {
  try {
    WeatherFactory wf =  WeatherFactory("apiKeyHere", language: Language.KOREAN);
    Position pos = await getPosition();
    Weather w = await wf.currentWeatherByLocation(pos.latitude, pos.longitude);
    printLog(w.toString());
  }
  catch(e) {
    printLog(e.toString());
  }
}
lastKnownPosition : Latitude: 37.4220125, Longitude: -122.0840023 Place Name: Mountain View [US] (37.422, -122.084) Date: 2022-05-02 06:12:35.000 Weather: Clear, 맑음 Temp: 11.9 Celsius, Temp (min): 9.5 Celsius, Temp (max): 13.6 Celsius, Temp (feels like): 11.0 Celsius Sunrise: 2022-05-01 13:13:00.000, Sunset: 2022-05-02 02:57:38.000 Wind: speed 3.6, degree: 270.0, gust null Weather Condition code: 800

API키를 가지고 객체를 생성해주고 다음과 같이 정보를 받아올 수 있습니다. 

더 자세한 내용은 공식 문서: OpenWeatherMap weather API docs.

 

weather.temperature  // 온도
weather.areaName. // 지역
weather.weatherMain // 주요 날씨 요약

아이콘 주소 (https://openweathermap.org/weather-conditions#Icon-list)
http://openweathermap.org/img/wn/${weather.weatherIcon}@2x.png

 

'프로그래밍 > Flutter' 카테고리의 다른 글

[Flutter] AES 암호화  (0) 2022.05.13
[Flutter] Flavor 처리(Old version)  (0) 2022.05.05
[Flutter] 난독화  (0) 2022.04.28
[Flutter] Screen, StatusBar Size  (0) 2022.04.27
[Flutter] Screen Orientation  (0) 2022.04.27

댓글