Psycop Posted October 22, 2016 at 09:20 AM Report #599828 Posted October 22, 2016 at 09:20 AM Bom Dia, 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: 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 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 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
Psycop Posted October 24, 2016 at 05:54 PM Author Report #599873 Posted October 24, 2016 at 05:54 PM Tenho tentado perceber o que está a acontecer, e a conclusão a que chego é que no momento de executar o pedido a API do OpenWeatherMap o sistema ainda não obteve as coordenadas do dispotivo de modo a injecta-las no URL e de seguida este fazer o pedido já com as coordenadas do local... Agora o meu grande problema está em como contornar esta situação. Alguma ideia para me ajudar a resolver esta situação?
apocsantos Posted October 24, 2016 at 06:37 PM Report #599874 Posted October 24, 2016 at 06:37 PM Boa noite, @Psycop, assim "out of the top", uma vez que o problema está na demora de obtenção de coordenadas do device, a quando do pedido ao OpenWeatherMap, porque não usar uma AsyncTask(); , e apenas quando ela estiver concluída executar o pedido ao OpenWeatherMap ? private class GetWeatherTask extends AsyncTask<String, Void, String> { private TextView textView; public GetWeatherTask(TextView textView) { this.textView = textView; } @Override protected String doInBackground(String... strings) { return null; } @Override protected void onPostExecute(String temp) { textView.setText("Clima actual: " + temp); } } @Override protected String doInBackground(String s1, s2) { String weather = "UNDEFINED"; try { URL url = new URL(strings[0]); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream stream = new BufferedInputStream(urlConnection.getInputStream()); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream)); StringBuilder builder = new StringBuilder(); String inputString; while ((inputString = bufferedReader.readLine()) != null) { builder.append(inputString); } JSONObject topLevel = new JSONObject(builder.toString()); JSONObject main = topLevel.getJSONObject("main"); weather = String.valueOf(main.getDouble("temp")); urlConnection.disconnect(); } catch (IOException | JSONException e) { e.printStackTrace(); } return weather; } e por fim no onCreate() executas a seguinte: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); double lat = 41.432088, lon = -8.494201; //o antigo radar dos aviões, que voavam muito alto! :D String units = "Metric"; String url = String.format("http://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&units=%s&appid=%s", lat, lon, units, APP_ID); TextView textView = (TextView) findViewById(R.id.textView); new GetWeatherTask(textView).execute(url); } Cordiais cumprimentos, Apocsantos "A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now