I try to make a request for a resource json
usingHttpURLConnection
I test the following code in onCreate()
try {
URL url = new URL("http://localhost/testrealm/api/v1/status");
HttpURLConnection urlConnection = null;
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
Log.d(TAG, "get json: " + in.toString());
urlConnection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
Error in the request
java.lang.RuntimeException: Unable to start activity ComponentInfo ... android.os.NetworkOnMainThreadException
Log Error integer
06-10 14:32:21.113 E/AndroidRuntime: FATAL EXCEPTION: main
Process: realm.test.app.testrealm, PID: 11702
java.lang.RuntimeException: Unable to start activity ComponentInfo{realm.test.app.testrealm/realm.test.app.testrealm.MainActivity}: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
at android.app.ActivityThread.access$800(ActivityThread.java:155)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1161)
at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:332)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:199)
at realm.test.app.testrealm.MainActivity.onCreate(MainActivity.java:57)
at android.app.Activity.performCreate(Activity.java:6010)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
at android.app.ActivityThread.access$800(ActivityThread.java:155)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5343)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
HttpURLConnection documentation
If you use StrictMode.ThreadPolicy.Builder to allow any operation it works but you are disabling a policy that is not supposed to allow certain behavior in the application, in this case operations on the main Thread, this is mainly used for development, for production you shouldn't use it .
Use runOnUiThread()
Other options are Asynctask and also Handler.post() .
I found this excellent article for more information: "Android Background Tasks (I): Thread and AsyncTask" (Salvador Gómez's blog).
You should use AsynkTask:
If you need to know when you get a response and/or modify views after the call, use AsynkTask like this:
Add the following code before making the web request with
HttpURLConnection
As another option to this problem, which I also passed through my hands, is to implement your code inside a
runOnUiThread()
that will allow access to the variables of the main thread, since that is exactly the problem.In this question, I explain this method:
Use Activity.runOnUiThread() or Handler.post(Runnable) to update main Thread?
As soon as I have the opportunity again, I will try your solution and thus learn about other possible solutions.
This topic is always something to talk about. Disabling policies is definitely not the option.
But beware that this has a lot to do with how you want to do things, in my experience I have seen the following scenarios:
Therefore, I do not know what your case is and it is important that you think about it. For the first case
AsyncTask
it is very good for you. You execute your heavy process indoInBackground
it, you inform the user about its progress in itpublishProgress
and at the end you show the result on his screen through theonPostExecute
. It is the usual, not only to make requests to servers, it is also valid for complicated calculations, database searches, etc. As long as your intention is to keep the user waiting for this process (something that can be annoying) and that they can interact with the app once it has finished.For the second case, one
Thread
or oneRunnable
together with oneHandler
comes in handy, you execute a process in a methodrun
that is independent of its completion status and the user is not even aware of this.For the third case, let's take an example: You have a process that captures data and transforms it into useful information, you save this information in your local database but you must also send it to the server for reasons of data redundancy; but you must also wait for the result of the sending to the server to update an indicator on the record that defines if the sending was successful or not, so as not to send it again, for example. For this type of situation, it is convenient to work with Thread schedulers that allow you to execute an action for the moment in which the thread finishes its execution. A very simple example is Google Guava and its classes
Futures
andListenableFuture
.It is a bit of additional information to what you have been answered that is good to know, so define your scenarios well so that you can choose a better way to work.