getInputStream() very slow on device, but not on emulator - java

(I believe this question has been asked several times, but often without an accepted answer or with very old or ineffective solutions.)
My app should connect to a server and display read data. This works fine on the emulator, but as soon as I try it on any real device, getInputStream() takes extremely long (15 to 20 seconds instead of 1 to 2 seconds). Interestingly, I have noticed slightly quicker responses when I set setConnectTimeout() to a shorter time, but this could lead to more errors. What am I missing?
What I tried:
connection.setUseCaches(false);
using HttpUrlConnectio instead of HttpsUrlConnection
System.setProperty("http.keepAlive", "false");
connection.setRequestProperty("Content-Length", "1000");
Adding android:usesCleartextTraffic="true" to Manifest
I did see "No Network Security Config specified, using platform default", but fixing that did not seem to help.
The inner class HttpGetRequest was found in an example and adopted to suit my needs:
public class HttpGetRequest extends AsyncTask<Void, Void, String> {
static final String REQUEST_METHOD = "GET";
static final int READ_TIMEOUT = 15000;
static final int CONNECTION_TIMEOUT = 15000; //shorter time works faster!
#Override
protected void onPreExecute() {
clipEditText.setText("loading...");
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params){
String result="";
String inputLine;
//create connection
URL myUrl = null;
try {
myUrl = new URL(urlString);
} catch (MalformedURLException e) {
e.printStackTrace();
}
HttpsURLConnection connection = null;
try {
connection = (HttpsURLConnection) myUrl.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
try {
connection.setRequestMethod(REQUEST_METHOD);
} catch (ProtocolException e) {
e.printStackTrace();
}
connection.setReadTimeout(READ_TIMEOUT);
connection.setConnectTimeout(CONNECTION_TIMEOUT);
// get the string from the input stream
InputStreamReader streamReader = null;
try {
streamReader = new InputStreamReader(connection.getInputStream());
BufferedReader reader = new BufferedReader(streamReader);
StringBuilder stringBuilder = new StringBuilder();
Log.d(TAG, "doInBackground: Reading...");
while((inputLine = reader.readLine()) != null){
stringBuilder.append(inputLine);
}
//clean up when done
reader.close();
streamReader.close();
connection.disconnect();
result = stringBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
protected void onPostExecute(String result){
super.onPostExecute(result);
clipContent = result;
//show us the data
clipEditText.setText(clipContent);
}
}

Related

Why my android program works fine on 4.4.3 version but doesnt work on 10.0

On the phone string is empty, why thats happend?
Phone is android version 10, nox is 4.4.3 if thats matters?
I try more codes for read web page but result is same, i dont know why its happend?
class GetData extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
HttpURLConnection urlConnection = null;
String result = "";
try {
URL url = new URL("http://www.b92.net/info/rss/sport.xml");
urlConnection = (HttpURLConnection) url.openConnection();
int code = urlConnection.getResponseCode();
if(code==200){
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
if (in != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = bufferedReader.readLine()) != null)
result += line;
}
in.close();
}
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
urlConnection.disconnect();
}
return result;
}
#Override
protected void onPostExecute(String result) {
tv.setText(result);
}
}
}
To turn #intellij-amiya s comment into an answer:
Use https instead of http: https://www.b92.net/info/rss/sport.xml
this blog post tells us that clear-traffic is (basically) forbidden now (as #morrison-chang pointed out)
You need to add Internet Permission in Manifest.

Send data(Client_id=1,Staff_id=2) from android application to tomcat server

i want to send data from android application to tomcat java server.
Data is just one is client_id which is 1 and second is staff_id which is 2.
after authenticate the client id and staff id from tomcat show me a toast of success....please help...
Code is here
public class MyAsyncTasks extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// display a progress dialog for good user experiance
}
#Override
protected String doInBackground(String... params) {
// implement API in background and store the response in current variable
String current = "";
try {
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL("http://192.168.1.13:8080/digitaldisplay/s/m/data");
urlConnection = (HttpURLConnection) url
.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader isw = new InputStreamReader(in);
int data = isw.read();
while (data != -1) {
current += (char) data;
data = isw.read();
System.out.print(current);
}
// return the data to onPostExecute method
return current;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
} catch (Exception e) {
e.printStackTrace();
return "Exception: " + e.getMessage();
}
return current;
}
#Override
protected void onPostExecute(String s) {
Toast.makeText(Register.this, "success", Toast.LENGTH_SHORT).show();
Log.d("data", s.toString());
// dismiss the progress dialog after receiving data from API
try {
// JSON Parsing of data
JSONArray jsonArray = new JSONArray(s);
JSONObject oneObject = jsonArray.getJSONObject(0);
// Pulling items from the array
client = Integer.parseInt(oneObject.getString("client"));
staff = Integer.parseInt(oneObject.getString("staff"));
} catch (JSONException e) {
e.printStackTrace();
}
} }}
The logic in your code looks off to me. This is the pattern I usually follow when making a REST call from an activity using HttpURLConnection:
try {
String endpoint = "http://192.168.1.13:8080/digitaldisplay/s/m/data";
URL obj = new URL(endpoint);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST"); // but maybe you want GET here...
con.setConnectTimeout(10000);
con.setDoInput(true);
con.setDoOutput(true);
JSONObject inputJSON = new JSONObject();
inputJSON.put("Client_id", 1);
inputJSON.put("Staff_id", 2);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
OutputStream os = con.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(inputJSON.toString());
writer.flush();
writer.close();
os.close();
int responseCode = con.getResponseCode();
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response);
} catch (SocketTimeoutException se) {
// handle timeout exception
responseCode = -1;
} catch (Exception e) {
// handle general exception
responseCode = 0;
}
The only major change in adapting the above code for GET would be that you wouldn't write your input data to the connection. Instead, you would just append query parameters to the URL. I am possibly guessing that you need POST here, since your URL doesn't have any query parameters in it.

Trouble with "inputstream" when creating mobile app that downloads weather information (with AsyncTask)

I'm trying to make a mobile app that downloads info from the openweathermap.org apis. For example, if you feed that app this link: http://api.openweathermap.org/data/2.5/weather?q=Boston,us&appid=fed33a8f8fd54814d7cbe8515a5c25d7 you will get the information about the weather in Boston, MA. My code seems to work up to the point where I have to convert the input stream to a string variable. When I do that, I get garbage. Is there a particular way to do this seemingly simple task in a proper way? Here is my code so far...
private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
// params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return null;
}
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
TextView test = (TextView) findViewById(R.id.test);
if(result!=null) test.setText(result);
else{
Log.i(DEBUG_TAG, "returned result is null");}
}
}
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.i(DEBUG_TAG, "The response is: " + response);
is = conn.getInputStream();
String text = getStringFromInputStream(is);
//JSONObject json = new JSONObject(text);
//try (Scanner scanner = new Scanner(is, StandardCharsets.UTF_8.name())) {
//text = scanner.useDelimiter("\\A").next();
//}
//Bitmap bitmap = BitmapFactory.decodeStream(is);
return text;
}catch(Exception e) {
Log.i(DEBUG_TAG, e.toString());
}finally {
if (is != null) {
is.close();
}
}
return null;
}
private static String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
Check this library . Is An asynchronous callback-based Http client for Android built on top of Apache’s HttpClient libraries.

Make simply HTTP request and receive the content

I have found a working code for makeing simply HTTP requests here, from How can I make a simple HTTP request in MainActivity.java? (Android Studio) and I am going to post it below (with some changes, if I am not wrong it is now necessery to use try{} catch{}). But I would like to ask how I can receive the content? I work with the code in the following way:
GetUrlContentTask req = new GetUrlContentTask();
req.execute("http://192.168.1.10/?pin=OFF1");
textView3.setText(req.doInBackground("http://192.168.1.10/?pin=OFF1"));
GetUrlContentTask
private class GetUrlContentTask extends AsyncTask<String, Integer, String> {
protected String doInBackground(String... urls) {
// String content1 = "";
try {
URL url = new URL(urls[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.connect();
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String content = "", line;
while ((line = rd.readLine()) != null) {
content += line + "\n";
}
// content1 = content;
}
catch (Exception e) {
e.printStackTrace();
}
// return content1; - returns "", wrong
return "aaa";
//does not work return content;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(String result) {
// this is executed on the main thread after the process is over
// update your UI here
}
}
Add this to your onPostExecute(String result) call
protected void onPostExecute(String result) {
// this is executed on the main thread after the process is over
// update your UI here
setMyData(result);
}
And then fill your textfield or whatever other data you need to update.
private void setMyData(String result){
textView3.setText(result);
}
Where exactly are you stuck? Your code mostly correct although you may need to rearrange it slightly. Your scope is a bit off and your commented code almost gets there. See below
protected String doInBackground(String... urls) {
String content = "", line = "";
HttpURLConnection httpURLConnection;
BufferedReader bufferedReader;
URL url;
try {
for(String uri : urls) {
url = new URL(uri);
url = new URI(url.toURI().getScheme(), url.getAuthority(), url.getPath(), "pin=" + URLEncoder.encode("&OFF1", "UTF-8"), null).toURL();
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setDoOutput(true);
httpURLConnection.connect();
bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
while ((line = bufferedReader.readLine()) != null) {
content += line + System.lineSeparator();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bufferedReader.close();
} catch(Exception e) {
e.printStackTrace();
}
}
return content;
}
That will return a String representation of your page. If the page contains HTML it will return text/html, if it contains text it will return just text.
Then as a previous user stated you can set the response on your GUI
protected void onPostExecute(String result) {
textView3.setText(result);
}
The above example will technically work. However, I would highly recommend using http://loopj.com/android-async-http/ over HttpURLConnection. Your code will be much nicer which will matter down the line.
The code I sent you assumes that the parameter is always pin=OFF1 because it's more a proof of concept

AsyncTask LIFX Bulb response

I have got problem with read output form request.
public JSONArray listLights()
{
try
{
URL adres = new URL("https://api.lifx.com/v1/lights/all");
HttpURLConnection polaczenie = (HttpURLConnection) adres.openConnection();
polaczenie.setRequestProperty("Authorization", "Bearer " + apiKey);
polaczenie.setRequestMethod("GET");
BufferedReader wejscie = new BufferedReader(new InputStreamReader((polaczenie.getInputStream())));
StringBuilder odpowiedz = new StringBuilder();
String json;
while ((json = wejscie.readLine()) != null)
odpowiedz.append(json);
wejscie.close();
return new JSONArray(odpowiedz.toString());
}
catch (Exception wyjatek)
{
wyjatek.printStackTrace();
}
return new JSONArray();
}
StackTrace
I added to AndroidManifest Internet access too.
Welcome to leave any comments. :P
EDIT:
I google internet and found partial solution. Added AsyncTask, but now I'm receiving '429' response code.
public class JSONTask extends AsyncTask<String, String, String>
{
String apiKey = "blah_blah_blah";
String txtresult;
#Override
protected String doInBackground(String... params) {
HttpsURLConnection connection = null;
BufferedReader reader = null;
try
{
URL adres = new URL(params[0]);
HttpsURLConnection polaczenie = (HttpsURLConnection) adres.openConnection();
polaczenie.setRequestProperty("Authorization", "Bearer " + apiKey);
polaczenie.setRequestMethod("GET");
System.out.println(polaczenie.getResponseCode());
InputStream stream = polaczenie.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null)
{
buffer.append(line);
}
return buffer.toString();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
if (connection != null)
connection.disconnect();
try
{
if (reader != null)
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
widok.setText(s);
}
}
My current StackTrace
EDIT2:
New day, new surprise. I figure out that I'm making connection with Bulb once/twice on every 10 attempts. Any ideas?
HTTP Status code 429 means too many requests in a given an amount of time. So how many requests exactly are you doing?
android.os.NetworkOnMainThreadException it means, that You have to make a htttp request from another threat than UIthread. Why are you using async task ?
Edit: You can also try make a call from postman and maybe You will see the problem.
In the end, everything is working. Problem was on the side of bulb or Lifx Cloud.

Categories