2

I am kinda new to programming, and trying to make a project witch is an android app, but when I try to run it on my device it just crashes.

I get these errors in my logcat:

java.lang.NullPointerException: Attempt to get length of null array
    2020-07-12 19:52:04.128 12417-12417/? E/AndroidRuntime: FATAL EXCEPTION: main
        Process: com.example.temperatura, PID: 12417
        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:121)
            at org.json.JSONTokener.nextValue(JSONTokener.java:98)
            at org.json.JSONArray.<init>(JSONArray.java:94)
            at org.json.JSONArray.<init>(JSONArray.java:110)
            at com.example.temperatura.MainActivity.loadIntoListView(MainActivity.java:116)
            at com.example.temperatura.MainActivity.access$200(MainActivity.java:21)
            at com.example.temperatura.MainActivity$1DownloadJSON.onPostExecute(MainActivity.java:68)
            at com.example.temperatura.MainActivity$1DownloadJSON.onPostExecute(MainActivity.java:52)
            at android.os.AsyncTask.finish(AsyncTask.java:755)
            at android.os.AsyncTask.access$900(AsyncTask.java:192)
            at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:772)
            at android.os.Handler.dispatchMessage(Handler.java:107)
            at android.os.Looper.loop(Looper.java:224)
            at android.app.ActivityThread.main(ActivityThread.java:7520)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)

And this is my main activity.java:

package com.example.temperatura;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {

    ListView listView;
    List<String> sensor = new ArrayList<>();
    ArrayAdapter arrayAdapter;
    boolean needRefresh;        // whether refresh is needed


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

        final SwipeRefreshLayout pullToRefresh = findViewById(R.id.pullToRefresh);

        listView = (ListView) findViewById(R.id.listView);
        downloadJSON("http://pillsmanager.com/temperatura/conn_app.php");

        pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                downloadJSON("http://pillsmanager.com/temperatura/conn_app.php");
                pullToRefresh.setRefreshing(false);
                needRefresh = true;
            }
        });
    }


    private void downloadJSON(final String urlWebService) {

        class DownloadJSON extends AsyncTask<Void, Void, String> {

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
            }


            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
                try {
                    if (needRefresh) {
                        updateAndLoadIntoListView(s);
                    } else {
                        loadIntoListView(s);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }


            @Override
            protected String doInBackground(Void... voids) {
                try {
                    URL url = new URL(urlWebService);
                    HttpURLConnection con = (HttpURLConnection) url.openConnection();
                    StringBuilder sb = new StringBuilder();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
                    String json;
                    while ((json = bufferedReader.readLine()) != null) {
                        sb.append(json + "\n");
                    }
                    return sb.toString().trim();
                } catch (Exception e) {
                    return null;
                }
            }
        }
        DownloadJSON getJSON = new DownloadJSON();
        getJSON.execute();

    }

    private void updateAndLoadIntoListView(String json) throws JSONException {
        JSONArray jsonArray = new JSONArray(json);
        sensor.clear();
        for (int i = 0; i < jsonArray.length(); i++) {
            final JSONObject obj = jsonArray.getJSONObject(i);
            sensor.add(obj.getString("temperature") + " " + obj.getString("humidity"));

        }


        arrayAdapter.notifyDataSetChanged();
        needRefresh = false;
    }


    private void loadIntoListView(String json) throws JSONException {


        JSONArray jsonArray = new JSONArray(json);
        for (int i = 0; i < jsonArray.length(); i++) {
            final JSONObject obj = jsonArray.getJSONObject(i);
            sensor.add(obj.getString("temperature") + " " + obj.getString("humidity"));


        }

        arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, sensor);
        listView.setAdapter(arrayAdapter);


    }
}

All the help is much appreciated, I have tried everything but I can't figure out the problem

Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
  • 1
    That stack trace is saying that you're passing null to `loadIntoListView()` from `onPostExecute()`, which means that `doInBackground()` is returning null. It's quite likely that an Exception is being thrown there, but you're ignoring it in the `catch`. You should at least `e.printStackTrace();`, and look in your logs for that. – Mike M. Jul 12 '20 at 19:25
  • Run Emulator normally without installing app. I am sure emulator have some other issue and crash not happening because to your code. – gpl Jul 12 '20 at 19:27
  • the emulator is running ok, but when i try to run it on my real device the app just crashes – Ashley Young Jul 12 '20 at 19:31
  • @MikeM. what do you mean with that? can you explain it a little bit better pls? – Ashley Young Jul 12 '20 at 19:36
  • In the `catch` in `doInBackground()`, you're ignoring the `Exception` there, and just returning null if something goes wrong. To find out what is going wrong there, you should at least add `e.printStackTrace();`, and look for the stack trace in your logs. That should tell you what the specific issue is. I would guess that it's possibly a [cleartext error](https://stackoverflow.com/q/45940861). – Mike M. Jul 12 '20 at 19:55
  • i already did the https thing and now the app opens, but it still crashes – Ashley Young Jul 12 '20 at 21:48

1 Answers1

0

From the stack trace, it seems that you are passing null to loadIntoListView method.

It can only happen in your code if you are running into exception with your doInBackground method, where you are handling downloading.

There could be many reasons for it to fail on the device and work on the emulator. I recommend switching to some networking library to handle downloads and deal with those edge cases. It can be really annoying. Try using OkHttp

Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216