Android 9.0 Java.net.URL

2019-07-18 04:11发布

问题:

I've been wondering, how does networking actually work on android 9.0 without java.net.URL(because my app crashes on android pie saying, that class java.net.url can't be found). While browsing the web, I've found a few posts saying that I should use URI, but wherever I check, it's always using .toURL().

Could I get some examples for downloading images and getting the input stream without the usage of java.net.url?

Thanks in advance!

EDIT: Here is the stacktrace I've promissed:

12/17 17:24:37: Launching app
$ adb shell am start -n "xyz.mglolenstine.nekoslife/xyz.mglolenstine.nekoslife.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Client not ready yet..Waiting for process to come online
Connected to process 14213 on device xiaomi-pocophone_f1-8e0cf863
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
W/stine.nekoslif: JIT profile information will not be recorded: profile file does not exits.
I/chatty: uid=10172(xyz.mglolenstine.nekoslife) identical 10 lines
W/stine.nekoslif: JIT profile information will not be recorded: profile file does not exits.
I/Perf: Connecting to perf service.
I/InstantRun: starting instant run server: is main process
W/stine.nekoslif: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
W/stine.nekoslif: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
W/stine.nekoslif: Accessing hidden field Ljava/net/URL;->host:Ljava/lang/String; (dark greylist, reflection)
W/stine.nekoslif: Accessing hidden field Ljava/net/URL;->host:Ljava/lang/String; (dark greylist, reflection)
W/stine.nekoslif: Accessing hidden field Ljava/net/URL;->host:Ljava/lang/String; (dark greylist, reflection)
W/stine.nekoslif: Accessing hidden field Ljava/net/URL;->host:Ljava/lang/String; (dark greylist, reflection)
E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-3
    Process: xyz.mglolenstine.nekoslife, PID: 14213
    java.lang.Error: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.lang.Class.getDeclaredField(Native Method)
        at khttp.requests.GenericRequest.toIDN(GenericRequest.kt:198)
        at khttp.requests.GenericRequest.makeRoute(GenericRequest.kt:208)
        at khttp.requests.GenericRequest.<init>(GenericRequest.kt:132)
        at khttp.KHttp.request(KHttp.kt:60)
        at khttp.KHttp.get(KHttp.kt:30)
        at khttp.KHttp.get$default(KHttp.kt:29)
        at xyz.mglolenstine.nekoslife.MainActivity$addImage$1.run(MainActivity.kt:426)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 
E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-4
    Process: xyz.mglolenstine.nekoslife, PID: 14213
    java.lang.Error: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.lang.Class.getDeclaredField(Native Method)
        at khttp.requests.GenericRequest.toIDN(GenericRequest.kt:198)
        at khttp.requests.GenericRequest.makeRoute(GenericRequest.kt:208)
        at khttp.requests.GenericRequest.<init>(GenericRequest.kt:132)
        at khttp.KHttp.request(KHttp.kt:60)
        at khttp.KHttp.get(KHttp.kt:30)
        at khttp.KHttp.get$default(KHttp.kt:29)
        at xyz.mglolenstine.nekoslife.MainActivity$addImage$1.run(MainActivity.kt:426)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 
E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
    Process: xyz.mglolenstine.nekoslife, PID: 14213
    java.lang.Error: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.lang.Class.getDeclaredField(Native Method)
        at khttp.requests.GenericRequest.toIDN(GenericRequest.kt:198)
        at khttp.requests.GenericRequest.makeRoute(GenericRequest.kt:208)
        at khttp.requests.GenericRequest.<init>(GenericRequest.kt:132)
        at khttp.KHttp.request(KHttp.kt:60)
        at khttp.KHttp.get(KHttp.kt:30)
        at khttp.KHttp.get$default(KHttp.kt:29)
        at xyz.mglolenstine.nekoslife.MainActivity$addImage$1.run(MainActivity.kt:426)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 
E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-2
    Process: xyz.mglolenstine.nekoslife, PID: 14213
    java.lang.Error: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.NoSuchFieldException: No field host in class Ljava/net/URL; (declaration of 'java.net.URL' appears in /system/framework/core-oj.jar)
        at java.lang.Class.getDeclaredField(Native Method)
        at khttp.requests.GenericRequest.toIDN(GenericRequest.kt:198)
        at khttp.requests.GenericRequest.makeRoute(GenericRequest.kt:208)
        at khttp.requests.GenericRequest.<init>(GenericRequest.kt:132)
        at khttp.KHttp.request(KHttp.kt:60)
        at khttp.KHttp.get(KHttp.kt:30)
        at khttp.KHttp.get$default(KHttp.kt:29)
        at xyz.mglolenstine.nekoslife.MainActivity$addImage$1.run(MainActivity.kt:426)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 
I/Process: Sending signal. PID: 14213 SIG: 9
I/Process: Sending signal. PID: 14213 SIG: 9
I/Process: Sending signal. PID: 14213 SIG: 9
Application terminated.

Once again, this only happens in android 9.0(API 28), but works flawlessly in lower versions

回答1:

I was blind, apparently there was a change in a newer version of Java, that's used in android 9.0, which doesn't have a field named 'host' in 'java.net.URL', which khttp is trying to access.

Thanks to @emandt I figured it out and made my own function for doing exactly the same without reflection.

EDIT: A promised example, that works in the pretty similar way to khttp, but only for get and it's written in Kotlin. If you want, I can post Java versions as well.

    fun get(url: String): String {
        try {
            val connection = URI(url).toURL().openConnection() as HttpURLConnection
            connection.connect()
            val text = connection.inputStream.use { it.reader().use { reader -> reader.readText() } }
            return text
        } catch (e: IOException) {
            Log.e("Error: ", "" + e)
        }
        return ""
    }

    fun getImage(url: String): InputStream? {
        try {
            val connection = URI(url).toURL().openConnection() as HttpURLConnection
            connection.connect()
            return BufferedInputStream(connection.inputStream)
        }catch(e: FileNotFoundException){
            e.printStackTrace()
        }
        return null
    }