I'm making a weather forcast app for my uni project and I wonder how to get the name of the closest city so I can get the weather data from sites like OpenWeatherMap, is there maybe other site that can return the data of the city that is closest to me?
CodePudding user response:
1. Using LocationManager, get the lat, lng of current location.
LocationManager mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Location location = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
2. Use Geocoder api, to fetch the address list based on your current lat, lng.
Geocoder gcd = new Geocoder(context, Locale.getDefault());
List<Address> addresses = gcd.getFromLocation(location.getLatitude(),
location.getLongitude(), 1);
if (addresses.size() > 0) {
for(Address adr : addresses){
if(adr != null && adr.getLocality().length() > 0){
cityName = adr.getLocality()
break;
}
}
CodePudding user response:
Let's break down problem as below:
1. Request User location coordinate
With Geolocation API you can request user location. For sake of simplicity, let we use EXPO SDK as it provides a unified API for common tasks.
import * as Location from "expo-location";
export const hasLocationServiceEnable = async () =>
await Location.hasServicesEnabledAsync();
const getUserLocation = async () => {
let result = null;
const isLocationAccessEnabled = await hasLocationServiceEnable();
if (!isLocationAccessEnabled) {
return result;
} else {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
return result;
} else {
try {
let { coords } = await Location.getCurrentPositionAsync({});
result = coords || null;
} catch (error) {
console.log(error);
}
return result;
}
}
};
export default getUserLocation;
2. Geocode coordinates to physical address names
Geocoding requires third-party services, let us use Google Map Geocoding API and has react native wrapper package.
import Geocoder from "react-native-geocoding";
// Initialize the module (needs to be done only once)
Geocoder.init("xxxxxxxxxxxxxxxxxxxxxxxxx"); // use a valid API key
export const getPlaceFromCoordinate = async ({ longitude, latitude }) => {
let place = null;
const response = await Geocoder.from(
parseFloat(latitude),
parseFloat(longitude)
);
address = response.results[0].formatted_address || null;
return address;
};
export default getPlaceFromCoordinate;
3. Request place weather data
export const WEATHER_API = `http://api.openweathermap.org/data/2.5/weather?APPID=${"YOUR_OPEN_WEATHER_MAP_API_KEY"}&units=metric`;
export const getWeatherForecast = (place) => {
const requestUrl = `${WEATHER_API}&q=${place}`;
let forecast = null;
try {
const todayForecast = await fetch(`${requestUrl}`);
forecast = await todayForecast.json();
return forecast;
} catch (e) {
console.log(e);
return forecast;
}
};
4. Connect all together
const getPlaceWeather = async () => {
try {
const coordinate = await getUserLocation();
if (!coordinate) return;
const place = await getPlaceFromCoordinate(coordinate);
if (!place) return;
const placeForecast = await getWeatherForecast(place);
console.log({ placeForecast });
} catch (error) {
console.log(error);
}
};
This is a high-level solution, there are a lot of features, I didn't cover including show weather icons, weather widget, and more.