-3

I am trying to create an Android app for weather. After some failed results, I decided to try a code from the internet. It still doesn't work. I found it here: https://androstock.com/tutorials/create-a-weather-app-on-android-android-studio.html The error I'm getting is:

I have checked the url with my actual API key - in browser it works.

MainActivity:

public class MainActivity extends AppCompatActivity {
    TextView selectCity, cityField, detailsField, currentTemperatureField, humidity_field, pressure_field, weatherIcon, updatedField;
    ProgressBar loader;
    Typeface weatherFont;
    String city = "Rome, IT";
    /* Please Put your API KEY here */
    String OPEN_WEATHER_MAP_API = "f2b6e17d5a21b6580934286ac8fa696a";
    /* Please Put your API KEY here */


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

        loader = (ProgressBar) findViewById(R.id.loader);
        selectCity = (TextView) findViewById(R.id.selectCity);
        cityField = (TextView) findViewById(R.id.city_field);
        updatedField = (TextView) findViewById(R.id.updated_field);
        detailsField = (TextView) findViewById(R.id.details_field);
        currentTemperatureField = (TextView) findViewById(R.id.current_temperature_field);
        humidity_field = (TextView) findViewById(R.id.humidity_field);
        pressure_field = (TextView) findViewById(R.id.pressure_field);
        weatherIcon = (TextView) findViewById(R.id.weather_icon);
        weatherFont = Typeface.createFromAsset(getAssets(), "fonts/weathericons-regular-webfont.ttf");
        weatherIcon.setTypeface(weatherFont);

        taskLoadUp(city);

        selectCity.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);
                alertDialog.setTitle("Change City");
                final EditText input = new EditText(MainActivity.this);
                input.setText(city);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                input.setLayoutParams(lp);
                alertDialog.setView(input);

                alertDialog.setPositiveButton("Change",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                city = input.getText().toString();
                                taskLoadUp(city);
                            }
                        });
                alertDialog.setNegativeButton("Cancel",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.cancel();
                            }
                        });
                alertDialog.show();
            }
        });

    }


    public void taskLoadUp(String query) {
        if (Function.isNetworkAvailable(getApplicationContext())) {
            Log.w("myApp", "network available in main 91");
            DownloadWeather task = new DownloadWeather();
            task.execute(query);
        } else {
            Toast.makeText(getApplicationContext(), "No Internet Connection", Toast.LENGTH_LONG).show();
        }
    }



    class DownloadWeather extends AsyncTask < String, Void, String > {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            loader.setVisibility(View.VISIBLE);

        }
        protected String doInBackground(String...args) {
            String xml = Function.excuteGet("http://api.openweathermap.org/data/2.5/weather?q=" + args[0] +
                    "&units=metric&appid=" + OPEN_WEATHER_MAP_API);
            Log.w("myApp", "xml is " +xml);
            return xml;
        }
        @Override
        protected void onPostExecute(String xml) {
            try {
                JSONObject json = new JSONObject(xml);
                if (json != null) {
                    JSONObject details = json.getJSONArray("weather").getJSONObject(0);
                    JSONObject main = json.getJSONObject("main");
                    DateFormat df = DateFormat.getDateTimeInstance();

                    cityField.setText(json.getString("name").toUpperCase(Locale.US) + ", " + json.getJSONObject("sys").getString("country"));
                    detailsField.setText(details.getString("description").toUpperCase(Locale.US));
                    currentTemperatureField.setText(String.format("%.2f", main.getDouble("temp")) + "°");
                    humidity_field.setText("Humidity: " + main.getString("humidity") + "%");
                    pressure_field.setText("Pressure: " + main.getString("pressure") + " hPa");
                    updatedField.setText(df.format(new Date(json.getLong("dt") * 1000)));
                    weatherIcon.setText(Html.fromHtml(Function.setWeatherIcon(details.getInt("id"),
                            json.getJSONObject("sys").getLong("sunrise") * 1000,
                            json.getJSONObject("sys").getLong("sunset") * 1000)));

                    loader.setVisibility(View.GONE);

                }else{
                    Toast.makeText(getApplicationContext(), "Json variable is null", Toast.LENGTH_SHORT).show();
                }
            } catch (JSONException e) {
                Toast.makeText(getApplicationContext(), "Error, Check City", Toast.LENGTH_SHORT).show();
            }


        }
    }

}

Function:

public class Function {

    // Project Created by Ferdousur Rahman Shajib
    // www.androstock.com

    public static boolean isNetworkAvailable(Context context)
    {
        return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo() != null;
    }



    public static String excuteGet(String targetURL)
    {
        URL url;
        HttpURLConnection connection = null;
        try {
            //Create connection
            url = new URL(targetURL);
            connection = (HttpURLConnection)url.openConnection();
            connection.setRequestProperty("content-type", "application/json;  charset=utf-8");
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setUseCaches (false);
            connection.setDoInput(true);
            connection.setDoOutput(false);

            InputStream is;
            int status = connection.getResponseCode();
            if (status != HttpURLConnection.HTTP_OK)
                is = connection.getErrorStream();
            else
                is = connection.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuffer response = new StringBuffer();
            while((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();
        } catch (Exception e) {
            return null;
        } finally {
            if(connection != null) {
                connection.disconnect();
            }
        }
    }


    public static String 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 = "&#xf00d;";
            } else {
                icon = "&#xf02e;";
            }
        } else {
            switch(id) {
                case 2 : icon = "&#xf01e;";
                    break;
                case 3 : icon = "&#xf01c;";
                    break;
                case 7 : icon = "&#xf014;";
                    break;
                case 8 : icon = "&#xf013;";
                    break;
                case 6 : icon = "&#xf01b;";
                    break;
                case 5 : icon = "&#xf019;";
                    break;
            }
        }
        return icon;
    }


}

The output:

FATAL EXCEPTION: main
Process: com.example.weatherapp, PID: 30032
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
    at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:116)
    at org.json.JSONTokener.nextValue(JSONTokener.java:94)
    at org.json.JSONObject.<init>(JSONObject.java:159)
    at org.json.JSONObject.<init>(JSONObject.java:176)
    at com.example.weatherapp.MainActivity$DownloadWeather.onPostExecute(MainActivity.java:117)
    at com.example.weatherapp.MainActivity$DownloadWeather.onPostExecute(MainActivity.java:101)
    at android.os.AsyncTask.finish(AsyncTask.java:695)
    at android.os.AsyncTask.access$600(AsyncTask.java:180)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-02-09 18:27:45.489 30032-30032/com.example.weatherapp I/Process: Sending signal. PID: 30032 SIG: 9

The app begins to start, but then closes immediately.

EDIT: The question should not be a duplicate, in my opinion, as the problem is not from wrong initialization of an object, but from not adding a specific line in the manifest file

lidia901
  • 39
  • 7
  • You are actually calling length() method on null String. kindly post your whole code – Ratish Bansal Feb 09 '19 at 17:41
  • @RatishBansal I updated the post. I think the problem is in the method excuteGet(), since it goes on the catch and returns null.. But I do not know how to manage that. – lidia901 Feb 09 '19 at 18:56

1 Answers1

2

The issue can be with the permission for internet and permission for cleartext HTTP traffic value in your manifest. Please make sure to add

?xml version="1.0" encoding="utf-8"?>

    <manifest ...>
        <uses-permission android:name="android.permission.INTERNET" />
        <application
            ...
            android:usesCleartextTraffic="true"
            ...>
            ...
        </application>
    </manifest>
Ratish Bansal
  • 1,982
  • 1
  • 10
  • 19
  • The url is okay, I checked. The problem is not from there. – lidia901 Feb 10 '19 at 17:02
  • Can you please tell what this line is logging Log.w("myApp", "xml is " +xml); – Ratish Bansal Feb 10 '19 at 17:12
  • It will print that xml is null. the function executeGet returns null, because it somehow enters on the catch – lidia901 Feb 10 '19 at 17:18
  • What is the complete url value you are hitting? what is the value of arg[0] in the url? I don't see you passing values in args – Ratish Bansal Feb 10 '19 at 17:21
  • W/url: url is http://api.openweathermap.org/data/2.5/weather?q=Rome,IT&units=metric&appid=f2b6e17d5a21b6580934286ac8fa696a and arg[0] represents the city, which is passed in MainActivity on line 54: taskLoadUp(city); Then, if the network is available, I try to download the weather, executing the querry with the given city name DownloadWeather task = new DownloadWeather(); task.execute(query); – lidia901 Feb 10 '19 at 17:24
  • i created a stand alone java program and executed the get from the url you provided and its working fine.I am getting the json response correctly.Are you sure the url is formed correctly at run time.Also check what is the exception you are getting in catch block. – Ratish Bansal Feb 10 '19 at 17:47
  • As I saw from the logs, the url is correctly formated... – lidia901 Feb 10 '19 at 17:51
  • can you please log you url in execute() method. public static String excuteGet(String targetURL) { // log targetURL here – Ratish Bansal Feb 10 '19 at 17:53
  • yes, that is where it is logged. url = new URL(targetURL); Log.w("url", "url is " + url); connection = (HttpURLConnection)url.openConnection(); – lidia901 Feb 10 '19 at 17:55
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/188189/discussion-between-ratish-bansal-and-lidia901). – Ratish Bansal Feb 10 '19 at 17:55