This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 8 years ago.
This is my error message:
08-17 07:58:14.286 32620-32620/xxx.dk.xxx E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: xxx.dk.xxx, PID: 32620
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1239)
at java.net.InetAddress.lookupHostByName(InetAddress.java:388)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:239)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at com.android.okhttp.internal.Dns$1.getAllByName(Dns.java:28)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:216)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:122)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:292)
at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)
at xxx.dk.xxx.DAL.JsonConnection.checkSecret(JsonConnection.java:42)
at xxx.dk.xxx.BLL.CheckCarrierData.checkSecret(CheckCarrierData.java:14)
at xxx.dk.xxx.GUI.Login.onClick(Login.java:49)
at android.view.View.performClick(View.java:4480)
at android.view.View$PerformClick.run(View.java:18686)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5872)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674)
at dalvik.system.NativeStart.main(Native Method)
Im trying to use a httpGet method, which is working on API10, but it fails when im using it on an unit with 4.4.2 -> i need the support from API10 and up.
The code:
public class JsonConnection
{
private String secretJsonStr = null;
private String nameOfCarrier = "";
public String checkSecret(String secret)
{
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
final String QueryParam = "secret";
try
{
final String httpUrl = "***SOMEURL***?";
Uri builtUri = Uri.parse(httpUrl).buildUpon().
appendQueryParameter(QueryParam, secret.toString()).build();
URL url = new URL(builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null)
{
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null)
{
buffer.append(line + "\n");
}
if (buffer.length() == 0)
{
// Stream was empty. No point in parsing.
return null;
}
secretJsonStr = buffer.toString();
} catch (IOException e)
{
Log.e("Login", "Error", e);
return null;
} finally
{
if (urlConnection != null)
{
urlConnection.disconnect();
}
if (reader != null)
{
try
{
reader.close();
} catch (final IOException e)
{
Log.e("Login", "Error closing stream", e);
}
}
}
try
{
JSONObject secretJson = new JSONObject(secretJsonStr);
nameOfCarrier = getCarrierInfoFromJson(secretJson);
}
catch (JSONException e)
{
e.printStackTrace();
}
return nameOfCarrier;
}
private String getCarrierInfoFromJson(JSONObject secretJson)
throws JSONException
{
final String CARRIER_NAME = "Name";
String nameOfCarrier2 = secretJson.getString(CARRIER_NAME);
return nameOfCarrier2;
}
}
Due to some protection, i cannot show you the URL, but everything is working like a charm when running in API 10 2.3.6 units..
I though there where complete backwards compatibility on all android devices.
Hope you have the knowledge to help me on, I for sure cannot see how. :-(
Kindest regards
Rasmus
The problem is that the http requests are executed on the main thread (NetworkOnMainThreadException), so you need to move the calls into a Thread. More info here.
update: actually, possible duplicate of this.
As error say you can't execute an HTTP connection on the MainThread that would froze the screen. which is not appropriate.
You can get that permission as the following:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
But, this is not a good practice. you must run the http connection on a background thread and display a loading msg to the user.
new Thread(new Runnable() {
#Override
public void run() {
// code goes here ...
}
}).start();
As other answers are suggesting, you are getting this error because you are running network operation on main thread. I would suggest to use AsyncTask.
This link shows you structure of AsyncTask.
To call the AsyncTask, use
//getData() is name of class
new getData().execute();
More reference on Android Developer site.
Related
I'm writing a program that connects to a servlet thanks to a HttpURLConnection but I stuck while checking the url
public void connect (String method) throws Exception {
server = (HttpURLConnection) url.openConnection ();
server.setDoInput (true);
server.setDoOutput (true);
server.setUseCaches (false);
server.setRequestMethod (method);
server.setRequestProperty ("Content-Type", "application / xml");
server.connect ();
/*if (server.getResponseCode () == 200)
{
System.out.println ("Connection OK at the url:" + url);
System.out.println ("------------------------------------------- ------- ");
}
else
System.out.println ("Connection failed");
}*/
I got the error :
java.net.ProtocolException: Cannot write output after reading input.
if i check the url with the code in comments but it work perfectly without it
unfortunately, I need to check the url so i think the problem comes from the getResponseCode method but i don t know how to resolve it
Thank you very much
The HTTP protocol is based on a request-response pattern: you send your request first and the server responds. Once the server responded, you can't send any more content, it wouldn't make sense. (How could the server give you a response code before it knows what is it you're trying to send?)
So when you call server.getResponseCode(), you effectively tell the server that your request has finished and it can process it. If you want to send more data, you have to start a new request.
Looking at your code you want to check whether the connection itself was successful, but there's no need for that: if the connection isn't successful, an Exception is thrown by server.connect(). But the outcome of a connection attempt isn't the same as the HTTP response code, which always comes after the server processed all your input.
I think the exception is not due toprinting url. There should some piece of code which is trying to write to set the request body after the response is read.
This exception will occur if you are trying to get HttpURLConnection.getOutputStream() after obtaining HttpURLConnection.getInputStream()
Here is the implentation of sun.net.www.protocol.http.HttpURLConnection.getOutputStream:
public synchronized OutputStream getOutputStream() throws IOException {
try {
if (!doOutput) {
throw new ProtocolException("cannot write to a URLConnection"
+ " if doOutput=false - call setDoOutput(true)");
}
if (method.equals("GET")) {
method = "POST"; // Backward compatibility
}
if (!"POST".equals(method) && !"PUT".equals(method) &&
"http".equals(url.getProtocol())) {
throw new ProtocolException("HTTP method " + method +
" doesn't support output");
}
// if there's already an input stream open, throw an exception
if (inputStream != null) {
throw new ProtocolException("Cannot write output after reading
input.");
}
if (!checkReuseConnection())
connect();
/* REMIND: This exists to fix the HttpsURLConnection subclass.
* Hotjava needs to run on JDK.FCS. Do proper fix in subclass
* for . and remove this.
*/
if (streaming() && strOutputStream == null) {
writeRequests();
}
ps = (PrintStream)http.getOutputStream();
if (streaming()) {
if (strOutputStream == null) {
if (fixedContentLength != -) {
strOutputStream =
new StreamingOutputStream (ps, fixedContentLength);
} else if (chunkLength != -) {
strOutputStream = new StreamingOutputStream(
new ChunkedOutputStream (ps, chunkLength), -);
}
}
return strOutputStream;
} else {
if (poster == null) {
poster = new PosterOutputStream();
}
return poster;
}
} catch (RuntimeException e) {
disconnectInternal();
throw e;
} catch (IOException e) {
disconnectInternal();
throw e;
}
}
I have this problem too, what surprises me is that the error is caused by my added code System.out.println(conn.getHeaderFields());
Below is my code:
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
configureConnection(conn);
//System.out.println(conn.getHeaderFields()); //if i comment this code,everything is ok, if not the 'Cannot write output after reading input' error happens
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(paramsContent.getBytes());
os.flush();
os.close();
I had the same problem.
The solution for the problem is that you need to use the sequence
openConnection -> getOutputStream -> write -> getInputStream -> read
That means..:
public String sendReceive(String url, String toSend) {
URL url = new URL(url);
URLConnection conn = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.sets...
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(toSend);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String receive = "";
do {
String line = in.readLine();
if (line == null)
break;
receive += line;
} while (true);
in.close();
return receive;
}
String results1 = sendReceive("site.com/update.php", params1);
String results2 = sendReceive("site.com/update.php", params2);
...
i am trying to send a JSONObject as input parameter for a C# Web API with the following code
protected String doInBackground(JSONObject... companyInfo) {
try {
URL url;
URLConnection urlConn;
url = new URL(HOST_NAME + WEB_API_METHOD);
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
urlConn.setUseCaches(false);
urlConn.setRequestProperty("Content-Type", "application/json");
urlConn.setRequestProperty("Host", HOST_NAME);
urlConn.connect();
PrintWriter out = new PrintWriter(urlConn.getOutputStream());
out.print(companyInfo[0]);
out.close();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close();
Log.i("companyInfo > ", stringBuilder.toString());
}
catch (Exception ex)
{
Log.e("Exception", ex.getLocalizedMessage());
}
return null;
}
When this is called, the method doesn't execute and when i try to catch the error, i don't get a meaningful message. it shows the URL name and thats it.
I am unable to find the issue and any help would be appreciated.
this is the error i got
java.io.FileNotFoundException: http://MY_FULL_URL
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:238)
at com.fourtyninetons.NewCompanyActivity$saveCompanyProfile.doInBackground(NewCompanyActivity.java:103)
at com.fourtyninetons.NewCompanyActivity$saveCompanyProfile.doInBackground(NewCompanyActivity.java:70)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Lakshman.
As mentioned in the solution of this question, the problem is with the web api method and the backend database. Fiddler helped me solve the issue and the above code is working fine.
Useful Tip: When anyone gets this FileNotFoundExceptionuser POSTMAN or FIDDLER to execute the method and find for the errors.
Thank you everyone who attempted to solve this.
I am new to this website, so if i do something wrong please tell me.
I am trying to establish a connection between my node.js server and my android app. For example, I'm trying to connect a page called showWithAuth, where i need to authenticate with digest stategy.
For this purpose i use Authenticator :
Authenticator.setDefault(new Authenticator()
{
#Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication (username, password.toCharArray());
// System.out.println(pa.getUserName() + ":" + new String(pa.getPassword()));
}
});
My real issue is when i try to establish the connection :
try {
URL url = new URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
in = new BufferedReader(new InputStreamReader(connection
.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
System.out.println(sb);
/*connection.setInstanceFollowRedirects(false);
int status = connection.getResponseCode();
InputStream is;
if (status >= 400 && status <= 499) {
throw new Exception("Bad authentication status: " + status); //provide a more meaningful exception message
}
else
{*/
//connection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
//connection.setRequestProperty("Accept", "*/*");
/*is = connection.getInputStream();
}
byte[] buffer = new byte[8196];
int readCount;
final StringBuilder builder = new StringBuilder();
while ((readCount = is.read(buffer)) > -1) {
builder.append(new String(buffer, 0, readCount));
}
String response = builder.toString();
System.out.println(response);*/
} catch (java.net.ProtocolException e) {
sb.append("User Or Password is wrong!");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
The issue i have is a filenotfoundexception, at this line :.getInputStream()));
The response of the server is a 401 : bad authentication status
I saw some people having the same issue i deal with, but i tried every single solution without getting anything better.
If you could help me to get what i do wrong ! Thank you !
PS: the commented code was also tried.
PS2: sorry for being so long.
Edit: Just to say also that this code is working on Netbeans with Java only, but not in Android Studio
Please try by adding the
<uses-permission android:name="android.permission.INTERNET" />
To your AndroidManifest.xml file, this may solve your problem.
For my application I need to have the latest data from an webpage that is hosted on a server on my local network.
So I request the latest page with a HTTP GET and when the data is received, I send another request.
With my current implementation I reach around the 100 - 120 ms per request. Is there a possibility to make this quicker because it's the same url that is requested.
For example keep the connection open to the page and grep the latest data without setting up a new connection?
This page is around the 900-1100 bytes.
HTTP get code:
public static String makeHttpGetRequest(String stringUrl) {
try {
URL url = new URL(stringUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(300);
con.setConnectTimeout(300);
con.setDoOutput(false);
con.setDoInput(true);
con.setChunkedStreamingMode(0);
con.setRequestMethod("GET");
return readStream(con.getInputStream());
} catch (IOException e) {
Log.e(TAG, "IOException when setting up connection: " + e.getMessage());
}
return null;
}
Reading inputstream
private static String readStream(InputStream in) {
BufferedReader reader = null;
StringBuilder total = new StringBuilder();
try {
String line = "";
reader = new BufferedReader(new InputStreamReader(in));
while ((line = reader.readLine()) != null) {
total.append(line);
}
} catch (IOException e) {
Log.e(TAG, "IOException when reading InputStream: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return total.toString();
}
As I know there isn't an implementation like you are asking for. I've been dealing a lot with http requests and the best thing you can do is your code. There is another thing which need some attention...your connection maybe slow and depending on that connection time can be more or in some cases which I've been dealing a lot the connection's timeout isn't enough big, but that's server problem.
In my opinion you should use what you have now.
I am trying to write a AndroidTestCase for one of my classes that make connection to a server and parse the returned JSONObject. When I test the functionality in the UI, the file works fine and the correct information are parsed and displayed. When I input the URL into my browser, I get the correct JSONObject back. However, when I try to get the JSONObject through a AndroidTestCase and simply verifying that it's not null, I get IOException when it tries to get the corresponding JSONObject for an url. I verified that the url it's using is correct. Here's the stack trace.
java.net.UnknownHostException: api.penncoursereview.com
at java.net.InetAddress.lookupHostByName(InetAddress.java:506)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:294)
at java.net.InetAddress.getAllByName(InetAddress.java:256)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:69)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:322)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:285)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:267)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1018)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:512)
at edu.upenn.cis.cis350.backend.Parser.retrieveJSONObject(Parser.java:34)
at edu.upenn.cis.cis350.test.ParserTest.test_retrieveJSONObject(ParserTest.java:22)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1448)
Any idea why the code works in simulator but not in test?
Thanks in advance for the help!
edit:
Here is the relevant method:
public JSONObject retrieveJSONObject(String path){
try{
URL url = new URL(path);
Log.w("Parser: retrieveJSONObject", "url=" + url);
URLConnection connection = url.openConnection();
String line;
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((line = reader.readLine()) != null) {
builder.append(line);
}
Log.v("Length",builder.toString());
return new JSONObject(builder.toString());
}
catch(IOException e) {
Log.w("Parser: retrieveJSONObject", "IOException: Bad Url");
e.printStackTrace();
return null;
} catch (JSONException e) {
Log.w("Parser: retrieveJSONObject", "JSONException: mis-formatted JSON");
e.printStackTrace();
return null;
}
}
Line 34 is the line initializing the BufferedReader.
I guess what you are missing is the INTERNET permission.
Considering that your method is defined static in Utils class, the following test works.
public void testRetrieveJSONObjectWithUrl() {
final String url = "http://www.bom.gov.au/fwo/IDV60901/IDV60901.94868.json";
assertNotNull(Utils.retrieveJSONObject(url));
}