Make simple code but app has stopping work in kotlin


#1

l am try to learn kotlin language , and the first app to me is take data fro json array . but the problem is when start to debug app l got FATAL EXCEPTION: main and app has stopping working .

package com.example.ali.test

import android.os.AsyncTask
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.view.*
import org.json.JSONArray
import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val url = "https://mysafeinfo.com/api/data?list=presidents&format=json"
        Download().execute(url)

    }
//    full class for json api
    inner class Download : AsyncTask<String,String,String>(){

        override fun onPreExecute() {
        }
//        for build connection
        override fun doInBackground(vararg p0: String?): String{

            try {

                val url = URL(p0[0])
                val urlConnect = url.openConnection() as HttpURLConnection
                urlConnect.connectTimeout = 700
                val inputStream = urlConnect.inputStream
                val dataJsonAsStr = covertStreamToString(urlConnect.inputStream)
                publishProgress(dataJsonAsStr)

                }   catch (e: Exception){

            }
            return ""
        }

//        for get items from json api
        override fun onProgressUpdate(vararg values: String?) {



        }

        override fun onPostExecute(result: String?) {

            super.onPostExecute(result)
            handleJson(result)

        }


    }

    fun handleJson (jsonString: String?){

        val jsonArray = JSONArray(jsonString)
        val list =  ArrayList<FlightShdu>()
        var x = 0
        while (x < jsonArray.length()){

            val jsonObject = jsonArray.getJSONObject(x)
            list.add(FlightShdu(

                jsonObject.getInt("id"),
                jsonObject.getString("nm")
            ))


            x++
        }
        val adapter = ListAdapte(this@MainActivity,list)
        flightShdu_list.adapter = adapter

    }

//    for connection api
    fun covertStreamToString (inputStream: InputStream): String {

        val bufferReader = BufferedReader(InputStreamReader(inputStream))
        var line:String
        var  allString:String=""
        try {
            do{
                line=bufferReader.readLine()
                if (line!=null)
                    allString+=line
            }while (line!=null)

            bufferReader.close()
        }catch (ex:java.lang.Exception){}

        return allString;
    }
}

error in console

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.ali.test, PID: 24738
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386) 
     Caused by: org.json.JSONException: End of input at character 0 of 
        at org.json.JSONTokener.syntaxError(JSONTokener.java:449)
        at org.json.JSONTokener.nextValue(JSONTokener.java:97)
        at org.json.JSONArray.<init>(JSONArray.java:92)
        at org.json.JSONArray.<init>(JSONArray.java:108)
        at com.example.ali.test.MainActivity.handleJson(MainActivity.kt:68)
        at com.example.ali.test.MainActivity$Download.onPostExecute(MainActivity.kt:59)
        at com.example.ali.test.MainActivity$Download.onPostExecute(MainActivity.kt:27)
        at android.os.AsyncTask.finish(AsyncTask.java:660)
        at android.os.AsyncTask.-wrap1(AsyncTask.java)
        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:677)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6776)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386) 

#2

Hi @aligassan,

The simple answer to your question is that jsonString is empty ("") when it gets to

 val jsonArray = JSONArray(jsonString)

very likely due to you returning with return ""

You can put a break point on that line to verify.

But there are a number of things that you could do to improve the code.

  • Use a library like Retrofit
  • Use the built in buffered reader.
  • Don’t return your result in the progress event.
  • do pass your result in doInBackground
  • do process result in onPostExecute
  • There are a few more things that set’s my spider-senses tingling, but I’ll leave them for now.

An example of a few things simplified.

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val url = "https://mysafeinfo.com/api/data?list=presidents&format=json"
        Download.execute(url)
    }

    object Download : AsyncTask<String, Int, String>() {
        override fun doInBackground(vararg params: String): String? {
            return try {
                params.first().let {
                    val url = URL(it)
                    val urlConnect = url.openConnection() as HttpURLConnection
                    urlConnect.connectTimeout = 700
                    publishProgress(100)
                    urlConnect.inputStream.bufferedReader().readText()
                }
            } catch (e: Exception) {
                null
            }
        }

        override fun onProgressUpdate(vararg values: Int?) {
            for (it in values) {
                Log.d("onProgressUpdate", it.toString())
            }
        }

        override fun onPostExecute(result: String?) {
            Log.d("MainActivity", "onPostExecute")
            when {
                result != null -> handleJson(result)
                else -> {
                    // some error
                }
            }
        }

        private fun handleJson(jsonString: String) {
            val jsonArray = JSONArray(jsonString)
            for (x in 0 until jsonArray.length()) {
                val jsonObject = jsonArray.getJSONObject(x)
                val id = jsonObject.getInt("id")
                val nm = jsonObject.getString("nm")
                Log.d("handleJson", "$id\t$nm")
            }
        }
    }
}