Problema com AsyncTask Android

Psycop

I fold therefore I AM
Bom dia,

Estou a ter alguns problemas em implementar uma pequena app para obter a meteorologia vinda das respostas do OpenWeatherMap, no entanto estou com problemas em implementar.

Main Activity:

Código:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private static final String APP_ID = "api_id";

    private static final int PERMISSION_ACCESS_COARSE_LOCATION = 1;
    private GoogleApiClient googleApiClient;

    private TextView textView;
    private TextView textView_humidity;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION },
                    PERMISSION_ACCESS_COARSE_LOCATION);
        }

        googleApiClient = new GoogleApiClient.Builder(this, this, this).addApi(LocationServices.API).build();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_ACCESS_COARSE_LOCATION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // All good!
                } else {
                    Toast.makeText(this, "Need your location!", Toast.LENGTH_SHORT).show();
                }

                break;
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (googleApiClient != null) {
            googleApiClient.connect();
        }
    }

    @Override
    protected void onStop() {
        googleApiClient.disconnect();
        super.onStop();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.i(MainActivity.class.getSimpleName(), "Connected to Google Play Services!");

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);

            double lat = lastLocation.getLatitude();
            double lon = lastLocation.getLongitude();

            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);
            new GetWeatherTask(textView).execute(url);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.i(MainActivity.class.getSimpleName(), "Can't connect to Google Play Services!");
    }

    private class GetWeatherTask extends AsyncTask<Meteo, Void, Meteo> {
        private TextView textView;
        private TextView textView_humidity;

        public GetWeatherTask(TextView textView) {
            this.textView = textView;
        }


        @Override
        protected Meteo doInBackground(Meteo... params) {
            Meteo meteo = new Meteo();
            String weather = "UNDEFINED";

            try {
                URL url = new URL(params[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");
                meteo.temperatura = String.valueOf(main.getDouble("temp"));
                meteo.humidade = String.valueOf(main.getDouble("humidity"));

                urlConnection.disconnect();
            } catch (IOException | JSONException e) {
                e.printStackTrace();
            }
            return meteo;
        }

        @Override
        protected void onPostExecute(Meteo meteo) {
            textView.setText("Current Weather: " + meteo.temperatura + " ºC");
            textView.setText("Current Humidity: " + meteo.humidade + " ºC");
        }
    }
}

Classe Meteo:

Código:
 * Created by Nuno on 27/11/2016.
*/

public class Meteo {

    public String temperatura;
    public String humidade;
    public String vento;

    public Meteo()
    {
        temperatura = "";
        humidade = "";
        vento = "";
    }

    public Meteo(String tEmperatura, String hUmidade, String vEnto)
    {
        temperatura = tEmperatura;
        humidade = hUmidade;
        vento = vEnto;
    }

    public String getTemperatura(){
        return temperatura;
    }

    public String getHumidade (){
        return humidade;
    }

    public String getVento()
    {
        return vento;
    }
}

Basicamente o meu problema está no URL, eu ainda não estou muito familiarizado com estes elementos quer URL, quer asynctasks será que me poderiam ajudar a resolver este problema?

Cumprimentos
 
Boa noite,

Apesar de ter conseguido pelo menos "resolver" os problemas da async task, ainda não consigo retornar as informações que desejo, e acho que o problema está na minha implementação do objecto que depois não consegue ser carregado com os valores recebidos do serviço...

Ou seja os valores que supostamente deveriam vir do serviço não estão a ser apresentados.

MainActivity:

Código:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private static final String APP_ID = "api_key";

    private static final int PERMISSION_ACCESS_COARSE_LOCATION = 1;
    private GoogleApiClient googleApiClient;

    private TextView textView;
    private TextView textView_humidity;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);
        textView_humidity = (TextView) findViewById(R.id.textView_humidity);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.ACCESS_COARSE_LOCATION },
                    PERMISSION_ACCESS_COARSE_LOCATION);
        }

        googleApiClient = new GoogleApiClient.Builder(this, this, this).addApi(LocationServices.API).build();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_ACCESS_COARSE_LOCATION:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // All good!
                } else {
                    Toast.makeText(this, "Need your location!", Toast.LENGTH_SHORT).show();
                }

                break;
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (googleApiClient != null) {
            googleApiClient.connect();
        }
    }

    @Override
    protected void onStop() {
        googleApiClient.disconnect();
        super.onStop();
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.i(MainActivity.class.getSimpleName(), "Connected to Google Play Services!");

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);

            double lat = lastLocation.getLatitude();
            double lon = lastLocation.getLongitude();

            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);
            new GetWeatherTask(textView, textView_humidity).execute(url);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.i(MainActivity.class.getSimpleName(), "Can't connect to Google Play Services!");
    }

    private class GetWeatherTask extends AsyncTask<String, Void, Meteo> {
        private TextView textView;
        private TextView textView_humidity;

        public GetWeatherTask(TextView textView, TextView textView_humidity) {
            this.textView = textView;
            this.textView_humidity = textView_humidity;
        }


        @Override
        protected Meteo doInBackground(String... params) {
            Meteo meteo = new Meteo();
            String weather = "UNDEFINED";

            try {
                URL url = new URL(params[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");
                meteo.temperatura = String.valueOf(main.getDouble("temp"));
                meteo.humidade = String.valueOf(main.getDouble("humidity"));

                urlConnection.disconnect();
            } catch (IOException | JSONException e) {
                e.printStackTrace();
            }
            return meteo;
        }

        @Override
        protected void onPostExecute(Meteo meteo) {
            textView.setText("Current Weather: " + meteo.temperatura + " ºC");
            textView_humidity.setText("Current Humidity: " + meteo.humidade + " ");
        }
    }
}

Meteo:

Código:
public class Meteo {

    public String temperatura;
    public String humidade;
    public String vento;

    public Meteo()
    {
        temperatura = "";
        humidade = "";
        vento = "";
    }

    public Meteo(String tEmperatura, String hUmidade, String vEnto)
    {
        temperatura = tEmperatura;
        humidade = hUmidade;
        vento = vEnto;
    }

    public String getTemperatura(){
        return temperatura;
    }

    public String getHumidade (){
        return humidade;
    }

    public String getVento()
    {
        return vento;
    }
}

Não estou a ver o que possa estar a fazer de mal, uma vez que eu adaptei este exemplo para usar o objecto Meteo e poder retornar masi do que um parametro, pois no exemplo original ele retornava apenas uma String temperatura.

Alguém me pode ajudar a perceber e a corrigir a situação?
 
Eu não obtenho qualquer erro no log de que o serviço não devolve ou falha, mas nas textview nada é apresentado vindo do serviço

_yIWPt3ssriPx7B1IDDXFVRRukXBia-BJVhlidKnwQtjBiCDhZTpaEtgWD55nsu0KSI8WwVroMKfVjo3rTfCFSToJifbsKBE5hTzqoN8tpHRtg0VHBXgm_qNoU5H0HmrG4mDZdOqaFNlGx5ARSLY7UBMou06iVoaWPd3zIDsEZNUmIxAdCAVTpnmJ29bgK7cRF8uGQ_J_oC3QE-CjXnvcGrUmO8qfGNIYlMl2Y_Ki1ysQVMbscLiFTPAVywmDP2qWHjH9T4DHHPtWwf11xQXVmM74psy_8ukIPsF3J0KY8iGBDn5VwH6lRmL8gtCqZsgSHVFGv4nTXFcxt7KD3dxoj8QBuaqJ560yU7N8XzP7CQ42Sux5Gp2tA9F5Mwf_udRobMJVcwDpIvpY387BcdDiKxHJVIs8rqgwqM7sjTlUgvHIiT56vPLZtq3rm59Um1aYU6nzNd8kT5HAAyNK8H5cpnGb6Msxo0vE0QKjdeyiUmvQB0oapCB7ZgE0TJ-nxzVcR58XP_3NCGIIaVKansAAJ2e6tIYeE1sFaVwCiQ8DVJ9BNL563vFa5nlQYTv3qvPyFyUOrQst33hpb46uyqEHzTmJiEIYCcBhJdPC0Au9bqENNBg=w507-h901-no
 
Última edição:
Pelo que consegui apurar estou a fazer algo mal ao "carregar" a informação para o objecto de modo a poder apresenta-la depois.... Mas não consigo perceber o quê!
 
Pelo que consegui apurar estou a fazer algo mal ao "carregar" a informação para o objecto de modo a poder apresenta-la depois.... Mas não consigo perceber o quê!

isso por vezes acontece por o onPostExecute iniciar antes de obteres a resposta da httpConnection
Usa Volley como API para os webservices, funciona muito melhor que a httpConnection normal. ;)

pequeno exemplo :

String url = "ENDEREÇO DE ONDE VAIS LER A INFORMAÇAO";

JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET, url, null, new Response.Listener<JSONObject> () {

@Override
public void onResponse(JSONObject response) {
// ADICIONA AQUI O PARSE DO JSON E ACTUALIZA AS TEXTVIEWS !!!
}
}, new Response.ErrorListener() {

@Override
public void onErrorResponse(VolleyError error) {
// MENSAGEM DE ERRO
}
});

// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);
 
Back
Topo