Android: OpenWeatherMap via Coordenadas GPS

Psycop

I fold therefore I AM
Boa Tarde,

Estou a tentar fazer uma pequena aplicação que consuma a API OpenWeatherMap mas que use a localização do dispositivo para tal, as coordenadas.

Já consegui obter as coordenadas do dispositivo no entanto quando injecto essas mesmas coordenadas no URL para fazer a chamada ao serviço este não devolve informações, como se não tivessem sido introduzidas quaisquer coordenadas nos seus parametros.

Será que me podem ajudar?

Em baixo está o código que criei até agora:
Código:
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);
    }

}

RemoteFetch.java

Código:
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;
        }
    }

}

WeatherFragment.java

Código:
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);
    }
}

No entanto se injectar manualmente umas coordenadas válidas no URL obtenho a respetiva resposta do serviço, pelo que prevejo que o problema esteja na obtenção das coordenadas do dispositivo e a sua injecção on time no URL do serviço.

Da a sensação que as coordenadas obtidas pelo location não estão a ser injetadas em tempo útil para o pedido do URL ao serviço.

Alguém me consegue ajudar a resolver este problema?

Cumprimentos
 
Hey,

Este é o link que mostras:
http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&units=metric

Se abrir da erro 401 pq não existe uma Appid

Agora o teu link com uma Appid que achei pela net:
http://api.openweathermap.org/data/...metric&APPID=ea574594b9d36ab688642d5fbeab847e

E obtenho este resultado:
Código:
{"coord":{"lon":138.93,"lat":34.97},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":18.71,"pressure":1024.59,"humidity":100,"temp_min":18.71,"temp_max":18.71,"sea_level":1033.89,"grnd_level":1024.59},"wind":{"speed":5.76,"deg":63.5007},"clouds":{"all":0},"dt":1477334700,"sys":{"message":0.0153,"country":"JP","sunrise":1477256311,"sunset":1477295861},"id":1851632,"name":"Shuzenji","cod":200}


Depois tens isto:
Código:
public static JSONObject getJSON(Context context, String city)

Estas a receber uma String com o nome da cidade, no entanto o teu link apenas aceita Latitude e Longitude.. como é que estas a pensar informar o URL da lat e lon apenas com uma String?

Tens 2 opções

1º Recebes lat e lon e passas para o url
2º Pesquisas por cidade com um link deste tipo: http://api.openweathermap.org/data/2.5/weather?q=Shuzenji&APPID=ea574594b9d36ab688642d5fbeab847e


1º Opção

Código:
 public static JSONObject getJSON(Context context, float lat, float lon){
        try {
            URL url = new URL("http://api.openweathermap.org/data/2.5/weather?lat="+ lat +"&lon="+ lon +"&units=metric&APPID=ea574594b9d36ab688642d5fbeab847e");

.
.
.

}


2º Opção
Código:
 public static JSONObject getJSON(Context context, String city){
        try {
            URL url = new URL("http://api.openweathermap.org/data/2.5/weather?q=" + city +"&APPID=ea574594b9d36ab688642d5fbeab847e");

.
.
.

}

Nunca usei essa API, mas penso que seja esse o problema.

Cumprimentos
 
Última edição:
Back
Topo