https://docs.expo.dev/versions/latest/sdk/location/
Location
A library that provides access to reading geolocation information, polling current location or subscribing location update events from the device.
docs.expo.dev
vscode์์ ํ์ฌ ์คํ์ค์ธ ํฐ๋ฏธ๋์ ๋๋๊ณ
git bash๋ก ํ๋ ๋ ์ด์ด์ ์ค์นํ๋ค.
๊ทธ๋ฌ๋ฉด ์คํ์ค์๋ ์ค์น ๊ฐ๋ฅํจ.
๊ทธ๋ฆฌ๊ณ app.json ์ ์๋์ ํ๋ฌ๊ทธ์ธ์ ์ถ๊ฐํ๋ค.
{
"expo": {
"plugins": [
[
"expo-location",
{
"locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location."
}
]
],
"name": "my-app",
"slug": "my-app",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
App.js๋ก ๋์๊ฐ์
expo-location์ import ํ๊ณ
์ฒ์ ์์ ์ ์์น์ ๋ณด ๊ฐ์ ธ์ค๊ฒ๋ ์์ฒญ์ ๋ณด๋ธ๋ค.
๋ง์ฝ ํ์ฉ์ ํ์ง ์์ผ๋ฉด false ๋ก ๋ฐ๊ฟ
import { StatusBar } from "expo-status-bar";
import { Dimensions, ScrollView, StyleSheet, Text, View } from "react-native";
import * as Location from "expo-location";
import { useEffect, useState } from "react";
//๊ฐ ์ค๋งํธํฐ ํ๋ฉด์ ๊ฐ๋ก ์ฌ์ด์ฆ
const { width: SCREEN_WIDTH } = Dimensions.get("window");
export default function App() {
const [location, setLocation] = useState();
const [ok, setOk] = useState(true);
const ask = async () => {
const { granted } = await Location.requestForegroundPermissionsAsync();
if (!granted) {
setOk(false);
}
};
useEffect(() => {
ask();
}, []);
์๋์ ๊ฐ์ด ๋ฌ๋ค
์ฑ ์ฌ์ฉ ์ค์๋ง ํ์ฉ ํด๋ฆญ
์ด์ ์ค์ ๋ก ๋ก์ผ์ด์
๊ฐ์ฒด์์ ์๋, ๊ฒฝ๋๋ฅผ ๊ฐ์ ธ์ ์์น ์ ๋ณด๋ฅผ ์์๋ด๊ธฐ.
https://docs.expo.dev/versions/latest/sdk/location/
export default function App() {
const [location, setLocation] = useState();
const [ok, setOk] = useState(true);
const ask = async () => {
const { granted } = await Location.requestForegroundPermissionsAsync();
if (!granted) {
setOk(false);
}
//accuracy 5 -> ์ ํ๋ 5๋จ๊ณ ์ ์ผ ๋์
const {
coords: { latitude, longitude },
} = await Location.getCurrentPositionAsync({ accuracy: 5 });
};
import { StatusBar } from "expo-status-bar";
import { Dimensions, ScrollView, StyleSheet, Text, View } from "react-native";
import * as Location from "expo-location";
import { useEffect, useState } from "react";
//๊ฐ ์ค๋งํธํฐ ํ๋ฉด์ ๊ฐ๋ก ์ฌ์ด์ฆ
const { width: SCREEN_WIDTH } = Dimensions.get("window");
export default function App() {
const [location, setLocation] = useState();
const [ok, setOk] = useState(true);
const ask = async () => {
const { granted } = await Location.requestForegroundPermissionsAsync();
if (!granted) {
setOk(false);
}
//๊ฒฝ๋์ ์๋ ๊ฐ์ ๊ฐ์ง๊ณ ์ด
//accuracy 5 -> ์ ํ๋ 5๋จ๊ณ ์ ์ผ ๋์
const {
coords: { latitude, longitude },
} = await Location.getCurrentPositionAsync({ accuracy: 5 });
// ๊ฐ์ง๊ณ ์จ ๊ฒฝ๋, ์๋ ๊ฐ์ ๋ง๋ ์์น๋ฅผ ํ์
ํ ์ ์๋ API์ฌ์ฉํด์ ์์ฒญ
const location = await Location.reverseGeocodeAsync(
{ latitude, longitude },
{ useGoogleMaps: false }
);
};
์ฝ์๋ก ์์น๋ฅผ ์ ๊ฐ์ ธ์๋๋ฐ ํ์ธํ๋ค.
์ฝ์์ ํฐ๋ฏธ๋์์ ํ์ธ๊ฐ๋ฅํ๋ค
์์ ๊ฐ์ด ํ์ฌ ์์น๊ฐ ์ ์ถ๋ ฅ๋๋ค.
์ด๊ฒ์ state๋ก ์ ์ฅํด์ ํ๋ฉด์ ๋ณด์ฌ์ฃผ๋ฉด ๋จ
import { StatusBar } from "expo-status-bar";
import { Dimensions, ScrollView, StyleSheet, Text, View } from "react-native";
import * as Location from "expo-location";
import { useEffect, useState } from "react";
//๊ฐ ์ค๋งํธํฐ ํ๋ฉด์ ๊ฐ๋ก ์ฌ์ด์ฆ
const { width: SCREEN_WIDTH } = Dimensions.get("window");
export default function App() {
const [city, setCity] = useState("Loading...");
const [location, setLocation] = useState();
const [ok, setOk] = useState(true);
const ask = async () => {
const { granted } = await Location.requestForegroundPermissionsAsync(); //์์น ์ ๋ณด ์ฌ์ฉ์ ๋์ ์ป๊ธฐ
if (!granted) {
setOk(false);
}
//๊ฒฝ๋์ ์๋ ๊ฐ์ ๊ฐ์ง๊ณ ์ด
//accuracy 5 -> ์ ํ๋ 5๋จ๊ณ ์ ์ผ ๋์
const {
coords: { latitude, longitude },
} = await Location.getCurrentPositionAsync({ accuracy: 5 });
// ๊ฐ์ง๊ณ ์จ ๊ฒฝ๋, ์๋ ๊ฐ์ ๋ง๋ ์์น๋ฅผ ํ์
ํ ์ ์๋ API์ฌ์ฉํด์ ์์ฒญ
const location = await Location.reverseGeocodeAsync(
{ latitude, longitude },
{ useGoogleMaps: false }
);
console.log(location);
setCity(location[0].city || location[0].district);
};
useEffect(() => {
ask();
}, []);
return (
<View style={styles.container}>
<View style={styles.city}>
<Text style={styles.cityName}>{`${city}`}</Text>
</View>
{/* //์คํฌ๋กค๋ทฐ๋ฅผ ๊ฐ๋ก๋ก ํด์ ์ํ์ผ๋ก ์คํฌ๋กคํ๊ณ ์คํฌ๋กค๋ฐ๋ฅผ ์ญ์ ํจ. */}
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={styles.weather}
>
<View style={styles.day}>
<Text style={styles.temp}>27°</Text>
<Text style={styles.description}>Sunny</Text>
</View>
<View style={styles.day}>
<Text style={styles.temp}>28°</Text>
<Text style={styles.description}>Sunny</Text>
</View>
<View style={styles.day}>
<Text style={styles.temp}>29°</Text>
<Text style={styles.description}>Sunny</Text>
</View>
<View style={styles.day}>
<Text style={styles.temp}>30°</Text>
<Text style={styles.description}>Sunny</Text>
</View>
<View style={styles.day}>
<Text style={styles.temp}>31°</Text>
<Text style={styles.description}>Sunny</Text>
</View>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#FFF3CF",
},
city: {
flex: 1.2,
justifyContent: "center",
alignItems: "center",
},
cityName: {
fontSize: 68,
fontWeight: "500",
},
weather: {},
day: {
flex: 1,
width: SCREEN_WIDTH,
alignItems: "center",
},
temp: {
marginTop: 50,
fontWeight: "600",
fontSize: 170,
},
description: {
marginTop: -30,
fontSize: 60,
},
});
ํ๋ฉด์ ์์ธ -> ๋ถ์ฐ์ง๊ตฌ๋ก ์ถ๋ ฅ๋๋ค.
์ง์ญ์ ๋ง๋ ๋ ์จ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์คํ์จ๋ API ์๋น์ค๋ฅผ ์ด์ฉํ๋ค.
https://openweathermap.org/forecast16
Daily Forecast 16 Days - OpenWeatherMap
openweathermap.org
lat={lat}&lon={lon}
์ฐ๋ฆฌ๊ฐ ๊ฐ์ ธ์จ ์๋ ๊ฒฝ๋๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋จ.
import { StatusBar } from "expo-status-bar";
import {
ActivityIndicator,
Dimensions,
ScrollView,
StyleSheet,
Text,
View,
} from "react-native";
import * as Location from "expo-location";
import { useEffect, useState } from "react";
//๊ฐ ์ค๋งํธํฐ ํ๋ฉด์ ๊ฐ๋ก ์ฌ์ด์ฆ
const { width: SCREEN_WIDTH } = Dimensions.get("window");
const API_KEY = "784ab24ff2ed5d94d4288abed9e25d13";
export default function App() {
const [city, setCity] = useState("Loading...");
const [days, setDays] = useState([]);
const [location, setLocation] = useState();
const [ok, setOk] = useState(true);
const weather = async () => {
const { granted } = await Location.requestForegroundPermissionsAsync(); //์์น ์ ๋ณด ์ฌ์ฉ์ ๋์ ์ป๊ธฐ
if (!granted) {
setOk(false);
}
//๊ฒฝ๋์ ์๋ ๊ฐ์ ๊ฐ์ง๊ณ ์ด
//accuracy 5 -> ์ ํ๋ 5๋จ๊ณ ์ ์ผ ๋์
const {
coords: { latitude, longitude },
} = await Location.getCurrentPositionAsync({ accuracy: 5 });
// ๊ฐ์ง๊ณ ์จ ๊ฒฝ๋, ์๋ ๊ฐ์ ๋ง๋ ์์น๋ฅผ ํ์
ํ ์ ์๋ API์ฌ์ฉํด์ ์์ฒญ
const location = await Location.reverseGeocodeAsync(
{ latitude, longitude },
{ useGoogleMaps: false }
);
// console.log(location);
setCity(location[0].city || location[0].district); // city๊ฐ์ด null์ผ ๊ฒฝ์ฐ์์ district๊ฐ ๋ค์ด๊ฐ
const response = await fetch(
);
const json = await response.json();
console.log(json);
setDays(json.daily);
};
useEffect(() => {
weather();
}, []);
return (
<View style={styles.container}>
<View style={styles.city}>
<Text style={styles.cityName}>{`${city}`}</Text>
</View>
{/* //์คํฌ๋กค๋ทฐ๋ฅผ ๊ฐ๋ก๋ก ํด์ ์ํ์ผ๋ก ์คํฌ๋กคํ๊ณ ์คํฌ๋กค๋ฐ๋ฅผ ์ญ์ ํจ. */}
<ScrollView
pagingEnabled
horizontal
showsHorizontalScrollIndicator={false}
style={styles.weather}
>
{days.length === 0 ? (
<View style={styles.day}>
{/* ์์ ๊ฒฝ์ฐ์๋ ๋ก๋ฉ ํ์ */}
<ActivityIndicator
color="white"
style={{ marginTop: 10 }}
size="large"
/>
</View>
) : (
days.map((day, index) => (
<View key={index} style={styles.day}>
<Text style={styles.temp}>
{parseFloat(day.temp.day).toFixed(1)}
</Text>
<Text style={styles.description}>{day.weather[0].main}</Text>
<Text style={styles.tinyText}>{day.weather[0].description}</Text>
</View>
))
)}
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#FFF3CF",
},
city: {
flex: 1.2,
justifyContent: "center",
alignItems: "center",
},
cityName: {
fontSize: 68,
fontWeight: "500",
},
weather: {},
day: {
flex: 1,
width: SCREEN_WIDTH,
alignItems: "center",
},
temp: {
marginTop: 50,
fontWeight: "600",
fontSize: 170,
},
description: {
marginTop: -30,
fontSize: 60,
},
});
https://jsonformatter.curiousconcept.com/#