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:
RemoteFetch.java
WeatherFragment.java
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
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