0
I’m trying to make a small application that consumes the API OpenWeatherMap
but to use the location of the device to do so, the coordinates.
I was able to get the coordinates of the device however when I inject those same coordinates into the URL to make the call to the service it does not return information, as if no coordinates had been entered in its parameters.
I wonder if you could help me?
Below is the code I’ve created so far:
<code="java">public class MainActivity extends AppCompatActivity {
private LocationManager locationManager;
private LocationListener listener;
static float lat;
static float lon;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new WeatherFragment()).commit();
}
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
listener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
lat = (float)location.getLatitude();
lon = (float)location.getLongitude();
//t.setText("\n " + lat + "\n" + lon);
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(i);
}
};
configure_button();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.weather, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.change_city){
showInputDialog();
}
return false;
}
private void showInputDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Escolher a Cidade:");
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
builder.setPositiveButton("Go", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
changeCity(input.getText().toString());
}
});
builder.show();
}
public void changeCity(String city){
WeatherFragment wf = (WeatherFragment)getSupportFragmentManager()
.findFragmentById(R.id.container);
wf.changeCity(city);
new CityPreference(this).setCity(city);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case 10:
configure_button();
break;
default:
break;
}
}
void configure_button(){
// first check for permissions
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.INTERNET}
,10);
}
return;
}
// this code won't execute IF permissions are not allowed, because in the line above there is return statement.
//noinspection MissingPermission
locationManager.requestLocationUpdates("gps", 5000, 0, listener);
}
}</code>
Remotefetch.java
<code>public class RemoteFetch extends MainActivity{
//private static final String OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?q=%s&units=metric";
//private static final String OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&units=metric";
private static final String OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&units=metric";
public static JSONObject getJSON(Context context, String city){
try {
URL url = new URL(String.format(OPEN_WEATHER_MAP_API, city));
HttpURLConnection connection =
(HttpURLConnection)url.openConnection();
connection.addRequestProperty("x-api-key", context.getString(R.string.open_weather_maps_app_id));
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
StringBuffer json = new StringBuffer(1024);
String tmp="";
while((tmp=reader.readLine())!=null)
json.append(tmp).append("\n");
reader.close();
JSONObject data = new JSONObject(json.toString());
if(data.getInt("cod") != 200){
return null;
}
return data;
}catch(Exception e){
return null;
}
}
}</code>
Weatherfragment.java
<code>public class WeatherFragment extends Fragment {
Typeface weatherFont;
TextView cityField;
TextView updatedField;
TextView detailsField;
TextView currentTemperatureField;
TextView weatherIcon;
TextView windField;
Handler handler;
public WeatherFragment(){
handler = new Handler();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_weather, container, false);
cityField = (TextView)rootView.findViewById(R.id.city_field);
updatedField = (TextView)rootView.findViewById(R.id.updated_field);
detailsField = (TextView)rootView.findViewById(R.id.details_field);
currentTemperatureField = (TextView)rootView.findViewById(R.id.current_temperature_field);
weatherIcon = (TextView)rootView.findViewById(R.id.weather_icon);
windField = (TextView)rootView.findViewById(R.id.wind_detail);
weatherIcon.setTypeface(weatherFont);
return rootView;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
weatherFont = Typeface.createFromAsset(getActivity().getAssets(), "weather.ttf");
updateWeatherData(new CityPreference(getActivity()).getCity());
}
private void updateWeatherData(final String city){
new Thread(){
public void run(){
final JSONObject json = RemoteFetch.getJSON(getActivity(), city);
if(json == null){
handler.post(new Runnable(){
public void run(){
Toast.makeText(getActivity(),
getActivity().getString(R.string.place_not_found),
Toast.LENGTH_LONG).show();
}
});
} else {
handler.post(new Runnable(){
public void run(){
renderWeather(json);
}
});
}
}
}.start();
}
private void renderWeather(JSONObject json){
try {
cityField.setText(json.getString("name").toUpperCase(Locale.US) +
", " +
json.getJSONObject("sys").getString("country"));
JSONObject details = json.getJSONArray("weather").getJSONObject(0);
JSONObject main = json.getJSONObject("main");
detailsField.setText(
details.getString("description").toUpperCase(Locale.US) +
"\n" + "Humidity: " + main.getString("humidity") + "%" +
"\n" + "Pressure: " + main.getString("pressure") + " hPa");
JSONObject wind = json.getJSONObject("wind");
//converter para km/h
double wind_ms = Double.parseDouble(wind.getString("speed").toUpperCase(Locale.getDefault()));
double wind_km = wind_ms * 3.6;
//DecimalFormat decimal = new DecimalFormat("#.##");
//wind_km = Double.valueOf(decimal.format(wind_km));
windField.setText("Wind: " + wind_km + " Km/h ");
currentTemperatureField.setText(
String.format("%.2f", main.getDouble("temp"))+ " ℃");
DateFormat df = DateFormat.getDateTimeInstance();
String updatedOn = df.format(new Date(json.getLong("dt")*1000));
updatedField.setText("Last update: " + updatedOn);
setWeatherIcon(details.getInt("id"),
json.getJSONObject("sys").getLong("sunrise") * 1000,
json.getJSONObject("sys").getLong("sunset") * 1000);
}catch(Exception e){
Log.e("SimpleWeather", "One or more fields not found in the JSON data");
}
}
private void setWeatherIcon(int actualId, long sunrise, long sunset){
int id = actualId / 100;
String icon = "";
if(actualId == 800){
long currentTime = new Date().getTime();
if(currentTime>=sunrise && currentTime<sunset) {
icon = getActivity().getString(R.string.weather_sunny);
} else {
icon = getActivity().getString(R.string.weather_clear_night);
}
} else {
switch(id) {
case 2 : icon = getActivity().getString(R.string.weather_thunder);
break;
case 3 : icon = getActivity().getString(R.string.weather_drizzle);
break;
case 7 : icon = getActivity().getString(R.string.weather_foggy);
break;
case 8 : icon = getActivity().getString(R.string.weather_cloudy);
break;
case 6 : icon = getActivity().getString(R.string.weather_snowy);
break;
case 5 : icon = getActivity().getString(R.string.weather_rainy);
break;
}
}
weatherIcon.setText(icon);
}
public void changeCity(String city){
updateWeatherData(city);
}
}</code>
Running this code the result I have is as follows:
However, if I manually inject a valid coordinates I get the corresponding response from the service, so I predict that the problem is in obtaining the coordinates of the device and its injection on time in the service URL.
Have you tried playing the URL generated with the coordinates on the screen to analyze what is happening differently?
– Bacco
Yes, by placing valid coordinates in the URL all data are presented correctly, which leads me to believe that the problem lies in obtaining and injecting the coordinates of the device.... However I already got and did print the coordinates using Location, however these take a few seconds to appear, maybe it is this delay that is hindering the obtaining of the coordinates by the URL
– Nuno Santos
What I asked was another thing, showed on the screen the URL generated by the application, to see if the generation is in order.
– Bacco
private Static final String OPEN_WEATHER_MAP_API = "http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&units=metric"; If I use this appears everything as expected on the screen
– Nuno Santos
That’s not what I said. I talked about printing on the screen the URL that your program generates, and not touching it manually. It’s probably generating wrong. If you do not play the URL on the screen, you will not be sure. Create a debug textview, and play the URL generated on it to read as it was
– Bacco
Actually the URL is not even shown
– Nuno Santos
@What @Bacco suggested is you add a line of code to print the url you generated, you have something like :
url/weather?lat=" + lat + "&lon=" + lon
, the suggestion is you see if the variableslat
andlon
have been replaced by latitude and longitude correctly. You may be generating a url with null in the fields– Lucas Queiroz Ribeiro