Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>So first of all you're not allowed to do Network stuff on the main thread because those things tend to take long (if the server is not responding or the connection is bad or the file you are trying to fetch is big) and if done on the main thread it will block the application on the phone. If your app is not responsive for too long it will be killed automatically from the Android OS. In order to avoid such things you need to use AsyncTasks. These are tasks that can do work in the background while your main thread is still being responsive to user input. </p> <p>You can read more about AsyncTasks <a href="http://developer.android.com/reference/android/os/AsyncTask.html" rel="nofollow" title="here">here</a>.</p> <p>[EDIT] So answering to your comment on your question: The reason why you get a <code>NetworkOnMainThreadException</code> is because you call <code>jParser.getJSONFromUrl(url);</code> in your main thread (the one where you execute code normally). The reason why this is not allowed is because in the method <code>getJSONFromUrl()</code> you make a HTTP request and have to wait for a response from the given URL. This can take a very long time as I have explained above and would block your application on the phone with the already explained consequences. Now to fix this you need to do something like this:</p> <p><strong>Before (bad):</strong></p> <pre><code>protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Creating new JSON Parser JSONParser jParser = new JSONParser(); // Getting JSON from URL JSONObject json = jParser.getJSONFromUrl(url); // get the data from your JSONObject } </code></pre> <p><strong>Better:</strong></p> <pre><code>protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Getting JSON from URL new JsonRequest().execute(url); } private class JsonRequest extends AsyncTask&lt;String, Void, JSONObject&gt; // I will talk about the parameters to AsyncTask below @Override protected JSONObject doInBackground(String... urls) { // Creating new JSON Parser JSONParser jParser = new JSONParser(); // Getting JSON from URL JSONObject json = jParser.getJSONFromUrl(url); return json; } @Override protected void onPostExecute(JSONObject result) { // Get the array JSONArray array = result.getJSONArray("data"); // Display the data // Import textviews // and so on.. } </code></pre> <p>Now about the parameters to <code>AsyncTask</code>: </p> <ol> <li>This type is the type of the parameters given to <code>doInBackground</code></li> <li>This type is used for showing a progress bar for example if you download many things you can override a function called <code>onProgressUpdate</code> and could show how many things already have been downloaded on your app so the user knows that something is happening.</li> <li>This type is the type that <code>doInBackground</code> will return and that <code>onPostExecute</code> has as a parameter.</li> </ol> <p>This way your main thread will keep running and the user won't notice a thing that there is a download going on in the background because it's a seperate task that is running. I hope this made it quite clear if not, just leave another comment and I'll explain more. :)</p> <p>[\EDIT]</p> <p>Then the second problem is that the <code>JSONParser</code> from learn2crack can't parse JSONArrays, in other words the function <code>getJSONFromUrl()</code> simply tries to create a new <code>JSONObject</code> from the <code>String</code> it gets from the given url.</p> <p>Theres basically several ways to fix this, I did a little hack (it invovles little code but you will need more time getting to the data afterwards). I added the following lines into the <code>getJSONFromUrl()</code> method:</p> <pre><code>if (json.startsWith("[")) { // We have a JSONArray try { jObj = new JSONObject(); jObj.put("data", new JSONArray(json)); } catch (JSONException e) { Log.d("JSON Parser", "Error parsing JSONArray " + e.toString()); } return jObj; } </code></pre> <p>These lines should be added right above this part:</p> <pre><code>// try parse the string to a JSON object try { jObj = new JSONObject(json); } catch (JSONException e) { Log.e("JSON Parser", "Error parsing data " + e.toString()); } </code></pre> <p>Basically what you will end up with then is that you can simply call <code>getJSONFromUrl()</code> on any url, and if it contains a <code>JSONObject</code> you will get that object, but if it contains a <code>JSONArray</code> you will get a <code>JSONObject</code> with a single field called <code>data</code> which will contain your <code>JSONArray</code>. So you could do something like this:</p> <pre><code>JSONObject json = jParser.getJSONFromUrl(url); JSONArray array = json.getJSONArray("data"); </code></pre> <p>And then you have your array (of course surrounded with a try catch for <code>JSONException</code>).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload