Android Kotlin http json

Fórumok

Üdv,

Kotlinban egy demo app-ban szeretnék egy url-ről (json) beolvasni adatot. Lépésekben haladok, pl.: 

http://date.jsontest.com
{
   "date": "01-31-2023",
   "milliseconds_since_epoch": 1675181626452,
   "time": "04:13:46 PM"
}

Amiket találtam példát hibára futnak. Hogyan kellene egyszerűen (szépen) beolvasni?

        // set Button OnClick
        val btn = findViewById<Button>(R.id.button)
        val text = findViewById<TextView>(R.id.textView)
        // set on-click listener
        btn.setOnClickListener {
            val result = URL("http://date.jsontest.com/").readText()

Az URL-nél elszáll:

at com.example.myjsonapi.MainActivity.onCreate$lambda$1(MainActivity.kt:49)

Után kellene majd valamilyen json parser.

Hozzászólások

Ez a stack trace egyetlen eleme. A teteje kellene a hibaüzenettel.

Rémlik nekem, hogy az Android API-k lényegében lehetetlenné teszik a sima http elérést https nélkül, nem ez a baj?

Jogos:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myjsonapi, PID: 14930
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
     Caused by: java.io.IOException: Cleartext HTTP traffic to date.jsontest.com not permitted
        at com.android.okhttp.HttpHandler$CleartextURLFilter.checkURLPermitted(HttpHandler.java:127)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:462)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:248)
        at java.net.URL.openStream(URL.java:1072)
        at kotlin.io.TextStreamsKt.readBytes(ReadWrite.kt:149)
        at com.example.myjsonapi.MainActivity.onCreate$lambda$1(MainActivity.kt:44)

Hát, legalábbis az rémlik asch-nek és a hibaüzenet is arrafele mutat :)

Keress rá az általam fentebb kiemelt hibaüzenetre, biztos feljön valami doksi/Stackoverflow topic az alapján.

(A fejlesztéshez nem csak a program írás, de a debugolás is hozzá tartozik mint fontos képesség, azért próbállak inkább csak irányba állítani :))

Szerkesztve: 2023. 01. 31., k – 17:46

val result = URL("http://date.jsontest.com/").readText()

1, Mi ez az antipattern szar, honnan szerezted?

2, Android 9 óta kell network-security-config és ott meg kell adni, hogy milyen domain felé mehet clear http forgalom

3, Ajánlott olvasmányok: OkHttp, Retrofit2, Moshi és Coroutines; mert a következő hely, ahol el fog botlani, az az I/O művelet az UI szálon.

4, További ajánlott olvasmány: ViewModel.

Egyébként egy https request esetén is elszáll: "https://opentdb.com/api.php?amount=1&category=18"

 

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myjsonapi, PID: 17579
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
        at java.net.InetAddress.getAllByName(InetAddress.java:1152)
        at com.android.okhttp.Dns$1.lookup(Dns.java:41)
        at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:178)
        at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:144)
        at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:86)
        at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:176)
        at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
        at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:248)
        at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211)
        at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
        at java.net.URL.openStream(URL.java:1072)
        at kotlin.io.TextStreamsKt.readBytes(ReadWrite.kt:149)
        at com.example.myjsonapi.MainActivity.onCreate$lambda$1(MainActivity.kt:45)

Megnézem ezt a OkHttp-t. De mi nem tetszett neki fent..?

Igen, a DigitalOcean az Android fejlesztésben élen járó és közismert cég... egyrészt ez Java és nem Kotlin, másrészt ebben is van pár elavultnak tekinthető rész, amit már el kellene felejteni.

Hiába 2022 augusztusi cikk, nagyjából 4-6 éve elavult a tartalma, gondolom kiadták egy gyakornoknak, hogy másoljon írjon Android releváns cikkeket, hogy felhúzzák a DigitalOcean SEO értékét.

Bocsánat, de a faszé' nincs annyi logikád, hogy meg tudd különböztetni a SEO optimalizált szart az értékes tartalomtól?

--

Én azt javaslom, hogy indulj onnan, ahol a legközelebb vagy az adott modulhoz, szóval OkHttp esetén innen ajánlom az "Asynchronous Get" fejezetet: https://square.github.io/okhttp/recipes/

Meg a többit is. Retrofit esetén se javaslom, hogy DigitalOcean blogposztok alapján indulj neki, van rendes dokumentációja: https://square.github.io/retrofit/

Ez most kicsit kemény lesz: először is tanuld meg a Kotlin-t vagy a Java-t, mielőtt nekiállsz Android-on bohóckodni. Az Exception-kezelés eléggé az alapok közé tartozik ebben az ökoszisztémában.

Gyakran fogsz exception-ökkel találkozni, főleg ha ennyire tapasztalatlan vagy. Jobban jársz, ha elolvasod, mit tartalmaz. Mindkét eddigi hibádra az egyértelmű válasz benne volt az Exception szövegében.

Mindenki elkezdte valamikor... érdemes leülni és az alapokat elolvasni legalább egyszer, egy tutorial-sorozat se árt és utána érdemes belecsapni a komplexebb dolgokba, mint JSON letöltés és feldolgozás. Te most úgy akarsz tetőt építeni, hogy nincsenek meg alatta se az alapok, se a falak, nem érted a szálkezelést, se az egész Android működési logikáját és ősrégi blogposztok alapján próbálsz összefoltozni valamit. Nem fog menni...

Ezt csak úgy próbából:

import kotlin.concurrent.thread
...

        // button JSON
        val btnJSON = findViewById<Button>(R.id.buttonJSON)
        val txtView = findViewById<TextView>(R.id.textView)
        btnJSON.setOnClickListener {
            val url = "https://opentdb.com/api.php?amount=1&category=18"
            thread {
                val json = try {
                    URL(url).readText()
                } catch (e: Exception) {
                    return@thread
                }
                runOnUiThread { txtView.text = json }
            }

        }
...