Hi I'm trying to connect with internet with this code:
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.0.100/webnet/xyz.php");
String result = null;
InputStream is = null;
StringBuilder sb = null;
HttpResponse response = httpclient.execute(httppost);
I registered Internet permission on manifest file
I got this error:
System.err android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
I tests this app with API level 8
You can not run long running task on main thread. please move your network related task in background.
Refer this : AsyncTask Android example
Try this before executing this block of code. may works in some cases:
try {
Class strictModeClass=Class.forName("android.os.StrictMode");
Class strictModeThreadPolicyClass=Class.forName("android.os.StrictMode$ThreadPolicy");
Object laxPolicy = strictModeThreadPolicyClass.getField("LAX").get(null);
Method method_setThreadPolicy = strictModeClass.getMethod("setThreadPolicy",strictModeThreadPolicyClass );
method_setThreadPolicy.invoke(null,laxPolicy);
}
catch (Exception e) {
}
And Try this before asking questions here: "google.com" # agree with kevinDTimm
Anyway you SHOULD NOT call network on UI threads.
Since Android 3.0, you'll see this error when you're trying to make network requests from the main thread. Move this code to a separate thread.
You check first which ip-address is the on (IPV4/IPV6)
Related
Ok, what I want is to ask to my server for an url, and load that url on a WebView, but a problem appears: when you run a http request you need to do it in a separate thread, and loadUrl() needs to be runned in the UI thread. So, how can I do to first make the request and then load the url?
The code isn't inside an Activity, so I can't call runOnUiThread(Runnable).
How can I do it?
EDIT: As Alécio suggested, it's better to not have too much code inside custom views, so what I want to do is to create a method that allows me to pass the url when the app has received the response from the server. The code that I'm using for the request is:
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://requesturl.com");
try {
HttpResponse response = client.execute(post);
InputStream content = response.getEntity().getContent();
String url = getStringFromInputStream(content);
//web.loadUrl(url);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
So, it's possible to know when a response has been received?
WebView is a UI component it must be in the context of an Activity or Fragment, so loadUrl() from the UI thread is OK.
If you want to make a server call, process the response before displaying something on the UI, then you might just use the conventional options to connect to a server URL using the HttpURLConnection. See the sample code below:
URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
In this example, you really need to execute it in a background Thread. Never from the UI Thread.
This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 9 years ago.
I want to check the HTTP response of a certain URL before loading into a webview. I only want to load webview if http response code is 200. This is a workaround for intercepting http errors. I have below:
HttpGet httpRequest = new HttpGet( "http://example.com");
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httpRequest);
int code = response.getStatusLine().getStatusCode();
But I encountered the following error:
java.lang.RuntimeException: Unable to start activity ComponentInfo
android.os.NetworkOnMainThreadException
How to fix it? Or any workaround to interept http errors in webview? Thanks
android.os.NetworkOnMainThreadException occurs whenever you try to make long running tasks/process on Main UI Thread directly.
To resolve this issue, cover your webservice call inside AsyncTask. FYI, AsyncTask in android known as Painless Threading which means developer don't need to bother about Thread management. So Go and implement web API call or any long running tasks using AsyncTask, there are plenty of examples available on the web.
Update:
I only want to load webview if http response code is 200.
=> Based on your requirement, I would say include your code inside doInBackground() method and return status code value, Which you can check inside onPostExecute(). Now here you are getting status code value 200/201 then you can load WebView.
class HTTPRequest extends AsyncTask<int, Void, void> {
protected int doInBackground() {
try {
HttpGet httpRequest = new HttpGet( "http://example.com");
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httpRequest);
int code = response.getStatusLine().getStatusCode();
return code;
} catch (Exception e) {
e.printstacktrace();
}
}
protected void onPostExecute(int code) {
// TODO: check this.exception
// retrieve your 'code' here
}
}
You are getting this Exception because you are carrying out a heavy Computation i.e Acessing Network in your case on UI Thread.
You should never do this .
Rather you can move this code to background Java Thread :
Try :
private void doNetworkCompuation()
{
new Thread(new Runnable() {
#Override
public void run() {
HttpGet httpRequest = new HttpGet( "http://example.com");
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httpRequest);
int code = response.getStatusLine().getStatusCode();
}).start();
}
Try executing this code in Async Thread.
You can have a refrence from here:
How to fix android.os.NetworkOnMainThreadException?
You are not allowed to execute network requests on the main thread. You have to use a different thread for making this requests. You should use the AsyncTask, for an example look here.
I've been struggling a bit on sending JSON objects from an application on android to a php file (hosted locally). The php bit is irrelevant to my issue as wireshark isn't recording any activity from my application (emulation in eclipse/ADK) and it's almost certainly to do with my method of sending:
try {
JSONObject json = new JSONObject();
json.put("id", "5");
json.put("time", "3:00");
json.put("date", "03.04.12");
HttpParams httpParams = new BasicHttpParams();
HttpClient client = new DefaultHttpClient(httpParams);
//
//String url = "http://10.0.2.2:8080/sample1/webservice2.php?" +
// "json={\"UserName\":1,\"FullName\":2}";
String url = "http://localhost/datarecieve.php";
HttpPost request = new HttpPost(url);
request.setEntity(new ByteArrayEntity(json.toString().getBytes(
"UTF8")));
request.setHeader("json", json.toString());
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
if (entity != null) {
InputStream instream = entity.getContent();
}
} catch (Throwable t) {
Toast.makeText(this, "Request failed: " + t.toString(),
Toast.LENGTH_LONG).show();
}
I've modified this from an example I found, so I'm sure I've taken some perfectly good code and mangled it. I understand the requirement for multi-threading so my application doesn't hang and die, but am unsure about the implementation of it. Would using Asynctask fix this issue, or have I missed something else important?
Thankyou for any help you can provide.
Assuming that you are using emulator to test the code, localhost refers to the emulated environment. If you need to access the php hosted on your computer, you need to use the IP 10.0.2.2 or the LAN IP such as 192.168.1.3. Check Referring to localhost from the emulated environment
You can refer to Keeping Your App Responsive to learn about running your long running operations in an AsyncTask
you should use asynctask or thread, because in higher versions of android it doesn't allow long running task like network operations from ui thread.
here is the link for more description
I've got a class:
public class WebReader implements IWebReader {
HttpClient client;
public WebReader() {
client = new DefaultHttpClient();
}
public WebReader(HttpClient httpClient) {
client = httpClient;
}
/**
* Reads the web resource at the specified path with the params given.
* #param path Path of the resource to be read.
* #param params Parameters needed to be transferred to the server using POST method.
* #param compression If it's needed to use compression. Default is <b>true</b>.
* #return <p>Returns the string got from the server. If there was an error downloading file,
* an empty string is returned, the information about the error is written to the log file.</p>
*/
public String readWebResource(String path, ArrayList<BasicNameValuePair> params, Boolean compression) {
HttpPost httpPost = new HttpPost(path);
String result = "";
if (compression)
httpPost.addHeader("Accept-Encoding", "gzip");
if (params.size() > 0){
try {
httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
}
try {
HttpResponse response = client.execute(httpPost);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
if (entity.getContentEncoding() != null
&& "gzip".equalsIgnoreCase(entity.getContentEncoding()
.getValue()))
result = uncompressInputStream(content);
else
result = convertStreamToString(content);
} else {
Log.e(MyApp.class.toString(), "Failed to download file");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
private String uncompressInputStream(InputStream inputStream)
throws IOException {...}
private String convertStreamToString(InputStream is) {...}
}
I cannot find a way to test it using a standard framework. Especially, I need to simulate total internet lost from inside the test.
There are suggestions to manually turn the Internet in the emulator off while performing the test. But it seems to me as not quite a good solution, because the automatic tests should be... automatic.
I added a "client" field to the class trying to mock it from inside the test class. But implementation of the HttpClient interface seems quite complex.
The Robolectric framework allows the developers to test Http connection as far as I know. But I guess there is some way to write such a test without using so big additional framework.
So are there any short and straightforward ways of unit testing classes that use HttpClient? How did you solve this in your projects?
I added a "client" field to the class trying to mock it from inside the test class. But implementation of the HttpClient interface seems quite complex.
I am a little bit confuse about this statement. From the question title, you are asking about unit-testing httpClint, by mocking a FakeHttpClient may help you unit-testing other part of app except httpClient, but doesn't help anything for unit-testing httpClient. What you need is a FakeHttpLayer for unit-testing httpClient (no remote server, network requires, hence unit-testing).
HttpClient Dummy Test:
If you only need examine app behavior in the situation that internet is lost, then a classic Android Instrument Test is sufficient, you can programmatically turn the Internet in the emulator off while performing the test:
public void testWhenInternetOK() {
... ...
webReader.readWebResource();
// expect HTTP 200 response.
... ...
}
public void testWhenInternetLost() {
... ...
wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(false);
webReader.readWebResource();
// expect no HTTP response.
... ...
}
This requires the remote http server is completely setup and in a working state, and whenever you run your test class, a real http communication is made over network and hit on http server.
HttpClient Advanced Test:
If you want to test app behavior more precisely, for instance, you want to test a http call in you app to see if it is handle different http response properly. the Robolectric is the best choice. You can use FakeHttpLayer and mock the http request and response to whatever you like.
public void setup() {
String url = "http://...";
// First http request fired in test, mock a HTTP 200 response (ContentType: application/json)
HttpResponse response1 = new DefaultHttpResponseFactory().newHttpResponse(HttpVersion.HTTP_1_1, 200, null);
BasicHttpEntity entity1 = new BasicHttpEntity();
entity1.setContentType("application/json");
response1.setEntity(entity1);
// Second http request fired in test, mock a HTTP 404 response (ContentType: text/html)
HttpResponse response2 = new DefaultHttpResponseFactory().newHttpResponse(HttpVersion.HTTP_1_1, 404, null);
BasicHttpEntity entity2 = new BasicHttpEntity();
entity2.setContentType("text/html");
response2.setEntity(entity2);
List<HttpResponse> responses = new ArrayList<HttpResponse>();
responses.add(response1);
responses.add(response2);
Robolectric.addHttpResponseRule(new FakeHttpLayer.UriRequestMatcher("POST", url), responses);
}
public void testFoo() {
... ...
webReader.readWebResource(); // <- a call that perform a http post request to url.
// expect HTTP 200 response.
... ...
}
public void testBar() {
... ...
webReader.readWebResource(); // <- a call that perform a http post request to url.
// expect HTTP 404 response.
... ...
}
Some pros of using Robolectric are:
Purely JUnit test, no instrument test so don't need start emulator (or real device) to run the test, increase development speed.
Latest Robolectric support single line of code to enable/disable FakeHttpLayer, where you can set http request to be interpreted by FakeHttpLayer (no real http call over network), or set the http request bypass the FakeHttpLayer(perform real http call over network). Check out this SO question for more details.
If you check out the source of Robolectric, you can see it is quite complex to implement a FakeHtppLayer properly by yourself. I would recommend to use the existing test framework instead of implementing your own API.
Hope this helps.
I need post data to server.
I use this code:
HttpClient client = new DefaultHttpClient();
try {
HttpPost httppost = new HttpPost(serverUrl);
StringEntity se = new StringEntity(data);
httppost.setEntity(se);
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/json");
// Execute HTTP Post Request
HttpResponse response = client.execute(httppost);
int statusCode = response.getStatusLine().getStatusCode();
Log.i(TVProgram.TAG, "ErrorHandler post status code: " + statusCode);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (client != null) {
client.getConnectionManager().shutdown();
}
}
But problem is that Android freeze on execute() method, application is blocked out and after some time Android tell me that application doesn't respond.
I tried to debug into SDK classes and it freeze in AbstractSessionInputBuffer class on the line 103 which is
l = this.instream.read(this.buffer, off, len);
I also tried it run the request in separated thread, but the same problem.
I tested it on Android 2.1 (emulator) and Android 2.2 real mobile device.
I also tried to set HTTP proxy and use Fiddler to check HTTP communication data are received by server and server also send correct answer and HTTP code 200. All seems to be ok.
What is wrong please?
UPDATE: When I use AndroidHttpClient which is part of Android 2.2 SDK it works great. But it is not in earlier version of Android. So I include it's source code in my app for now. But AndroidHttpClient use DefaultHTTPClient internally, so problem will be in configuration of DefaultHttpClient.
I am using a POST HTTP request successfully. Here is my code. I removed pieces using handler to display messages etc. and the handler itself.
The POST string is like "&NAME=value#NAME2=value2"...
protected class ConnectingThread implements Runnable
{
Message msg;
private Handler mExtHandler;
private String mData;
private String mUrl;
/**
* #param h (Handler) - a handler for messages from this thread
* #param data (String) - data to be send in HTTP request's POST
* #param url (String) - URL to which to connect
*/
ConnectingThread(Handler h, String data, String url) {
mExtHandler = h;
mData = data;
mUrl = url;
}
public void run() {
try {
// TODO use the handler to display txt info about connection
URL url = new URL(mUrl);
URLConnection conn = url.openConnection();
conn.setConnectTimeout(CONN_TIMEOUT_MILLIS);
conn.setDoOutput(true);
BufferedOutputStream wr = new BufferedOutputStream(conn.getOutputStream());
wr.write(mData.getBytes());
wr.flush();
wr.close();
String sReturn = null;
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
int length = conn.getContentLength();
char[] buffer = new char[length];
int read = rd.read(buffer);
if(read == length)
sReturn = new String(buffer);
rd.close();
buffer = null;
// TODO use the handler to use the response
} catch (Exception e) {
//....
}
// TODO use the handler to display txt info about connection ERROR
}
}
Isn't client.execute(httppost); synchronous ?
You probably need to put this in a thread, else it will freeze the UI.
Yes it is being freezed just becoz you haven't implemented this as Asynchronous process. Because while it makes web request, your UI will wait for the response and then it will be updated once the response is received.
So this should be implemented as Asynchronous process, and user should be notified (with progress bar or progress dialog) that there is something happening.
Now, Instead of implementing Runnable class, in android its preferrable and recommended to use AsyncTask, its also known as Painless Threading.
Do you background tasks inside the doInBackground() method.
Do your display type of operations inside onPostExecute() method, like updating listview with fetched data, display values inside TextViews....etc.
Display ProgressBar or ProgressDialog inside the onPreExecute() method.
Use AndroidHttpClient helped me in this situation.
But now complete AndroidHttpClient and DefaultHttpClient are obsolete in current version of Android so it is not important now.