I'm having an issue on multiple devices where when the device isn't interacted with for a period of time, my HttpUrlConnection's don't operate as expected. The projects target platform is Android 4.0.3.
Below is an example of how I'm using HttpUrlConnection.
new AsyncRequestDTOBaseItemArray(callback).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
The actual AsyncTask
public class AsyncRequestDTOBaseItem extends AsyncTask<String,String,Object> {
HttpURLConnection connection;
InputStream inStream;
IApiCallback callback;
public AsyncRequestDTOBaseItem(IApiCallback callback) {
this.callback = callback;
}
#Override
protected Object doInBackground(String... uri) {
try {
URL url = new URL(uri[0]);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.addRequestProperty("Accept-Encoding", "gzip");
connection.setInstanceFollowRedirects(false);
connection.connect();
String encoding = connection.getContentEncoding();
// Determine if the stream is compressed and uncompress it if needed.
if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
inStream = new GZIPInputStream(connection.getInputStream());
} else {
inStream = connection.getInputStream();
}
if (inStream != null) {
InputStreamReader isr = new InputStreamReader(inStream);
Gson gson = new Gson();
try {
DTOBaseItem item = gson.fromJson(isr, DTOBaseItem.class);
return item;
} catch (Exception e) {
Log.i("AsyncRequestDTOBaseItem", "Exception");
if (e != null && e.getMessage() != null) {
Log.e("AsyncRequestDTOBaseItem", e.getMessage());
}
} finally {
inStream.close();
}
}
} catch (SocketTimeoutException e) {
Log.i("AsyncRequestDTOBaseItem", "Socket Timeout occured");
} catch (IOException e) {
Log.i("AsyncRequestDTOBaseItem","IOException");
if (e != null && e.getMessage() != null) {
Log.i("AsyncRequestDTOBaseItem",e.getMessage());
}
} finally {
if (connection != null)
connection.disconnect();
}
return null;
}
#Override
protected void onPostExecute(Object result) {
callback.Execute(result);
}
}
I don't see any issues with the above code unless the device has been inactive. When the device has been inactive the last code line that executes is
String encoding = connection.getContentEncoding();
I've also gone into the wifi settings and made sure that my wifi doesn't sleep. I thought at first it might be that the wifi reconnecting was creating this issue.
It looks like the issue may have been the server not sending data back.
I added connection.setReadTimeout(5000); and now the issue seems to have gone away.
Related
I'm using Asynctask to pass the parameters of API. The Asynctask executing but the String Response in Asynctask PostExecute giving me a null for a device with SDK 23 and below. But when the device is equal or higher to SDK24(Nougat), it works perfectly and the data are being sent to the API however when the SDK is 23 and lower data are not being sent to API. Does anyone encounter this problem? Please enlighten me what I miss in my code or I do wrong code. Massive thank you.
private class sendToServerOfficial extends AsyncTask<String,Void,String> {
int statusCodeone;
String convert_txt_et_username = et_username.getText().toString();
String convert_txt_content = et_content.getText().toString();
#Override
protected String doInBackground(String... strings) {
try {
urlURL = new URL("http://www.testingsite.com/api/sendServer?/ip="+getIPAddress+"&phone_num="+getMobilePhoneNumber+"&user_text="+convert_txt_et_username+"&content_text="+convert_txt_content);
HttpURLConnection httpURLConnection = (HttpURLConnection) urlURL.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Content-Type","UTF-8");
httpURLConnection.connect();
statusCodeone = httpURLConnection.getResponseCode();
if (statusCodeone == 200) {
InputStream it = new BufferedInputStream(httpURLConnection.getInputStream());
InputStreamReader read = new InputStreamReader(it);
BufferedReader buff = new BufferedReader(read);
StringBuilder dta = new StringBuilder();
String chunks;
while ((chunks = buff.readLine()) != null) {
dta.append(chunks);
}
buff.close();
read.close();
return dta.toString();
}
}
catch (ProtocolException e) { e.printStackTrace(); }
catch (MalformedURLException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
return null;
}
#Override
protected void onPostExecute(String response) {
Toast.makeText(MainActivity.this, response + "Form is submitted already" + urlURL, Toast.LENGTH_LONG).show();
txt_inputURL.setEnabled(true);
btnClick.setClickable(true);
txt_inputURL.getText().clear();
}
}
I am downloading JSON Content from server in the MainActivity and passing the JSON from MainActivity to ListActivity, the problem here is I have added a sleep time of 10s in the backend server i.e. Php from where the data is fetched. Since, the response will the delayed I would expect that screen opens and waits until the response comes and move to next screen.
But what is happening is the screen goes white/black completely untill the response is recieved and ListActivity is loaded, the problem here is the MainActivity is never visible. Below is code for the same:
MainActivity
JSONData jsonData = new JSONData();
String jsonList = jsonData.fetchList();
Intent intent = new Intent(getApplicationContext(),ListActivity.class);
intent.putExtra("jsonList",jsonList);
startActivity(intent);
finish();
JSON Data class
public String fetchList() {
try {
String list = new DownloadJSONData().execute(listURL).get().toString();
return list;
} catch (Exception e) {
return "";
}
}
private class DownloadJSONData extends AsyncTask<String, String, String> {
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
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 "";
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
you are using get() method which accquires the main thread or ui thread untill the async task is completed
you should avoid using get() and also can use progress dialog in onPreExecute for displaying progression on network call to user
I using the class async to download and upload data in two activitys. The upload is not working and I dunno why.
This one works fine!
new DatabaseConnector(true).execute("http://web2page.ch/apps/FruityNumber/highscoreShow.php");
But this one not!
new DatabaseConnector(false).execute("http://web2page.ch/apps/FruityNumber/highscoreUpload.php?user=test7&highscore=timer7");
But if I remove "if" in the class it works fine... Does someone understand why?
public DatabaseConnector(Boolean download) {
this.download = download;
}
#Override
protected Long doInBackground(String... params) {
try {
try {
//Verbinden
url = new URL(params[0]);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.connect();
if (download) {
//Falls die App nochmal geladen wird, sind die Daten nur einmal enthalten. Darum leeren.
arrayList.clear();
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream);
bufferedReader = new BufferedReader(inputStreamReader);
for (String line = bufferedReader.readLine(); line != null; line = bufferedReader.readLine()) {
arrayList.add(line);
}
} else {
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
See comments in code
new DatabaseConnector(false) means
public DatabaseConnector(Boolean download) {
this.download = false; // see here
}
so
if (download) { // this won't execute because download == false
and
else {
// there is nothing here to do!
}
I'm not sure how you expect anything different..
To solve this will depend on why you are even using the boolean variable. If there is no reason for it then remove that and don't pass it anything.
Otherwise, it sounds like you want to put the upload code in the else{}
I have an app where i read some data from online api every 30sec. I have somewhat secured my app so that it will check if the device is connected to network and data can be trasfered.
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
But this does not include situations when i am connected to a network which needs authentification for internet access. Or when you have only local connectivity enabled.
The app tries to get data from that api and it crashes. Here is the request code:
public static JSONObject requestWebService(String serviceUrl) {
disableConnectionReuseIfNecessary();
HttpURLConnection urlConnection = null;
try {
// create connection
URL urlToRequest = new URL(serviceUrl);
urlConnection = (HttpURLConnection)urlToRequest.openConnection();
urlConnection.setConnectTimeout(10000);
urlConnection.setReadTimeout(10000);
// handle issues
int statusCode = urlConnection.getResponseCode();
if (statusCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
// handle unauthorized (if service requires user login)
} else if (statusCode != HttpURLConnection.HTTP_OK) {
// handle any other errors, like 404, 500,..
}
// create JSON object from content
InputStream in = new BufferedInputStream(
urlConnection.getInputStream());
return new JSONObject(getResponseText(in));
} catch (MalformedURLException e) {
// URL is invalid
} catch (SocketTimeoutException e) {
// data retrieval or connection timed out
} catch (IOException e) {
// could not read response body
// (could not create input stream)
} catch (JSONException e) {
// response body is no valid JSON string
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return null;
}
All i need is that this app will not crash. How can i achieve this?
SOLUTION: it needed null check before reading JSON object... it was in different method:
public void check(){
JSONArray jsonArray = null;
if(isNetworkAvailable()) {
JSONObject dataZNetu = requestWebService("http://census.soe.com/get/ps2:v2/world_event?type=METAGAME");
if(dataZNetu != null) { //THIS WAS THE SOLUTION TO MY PROBLEM
try {
jsonArray = dataZNetu.getJSONArray("world_event_list");
for (int i = jsonArray.length() - 1; i >= 0; i--) {
JSONObject tempObj = jsonArray.getJSONObject(i);
int worldId = tempObj.getInt("world_id");
int stateID = tempObj.getInt("metagame_event_state");
int eventType = tempObj.getInt("metagame_event_id");
int instanceId = tempObj.getInt("instance_id");
checkUIchange(worldId, stateID, eventType, instanceId);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
Since it looks like you are catching the appropriate exceptions, I'm guessing that the crash is in the code that calls this method.
If it tries to do something with the result, without checking for null, that's the problem.
But of course, knowing exactly where it crashes would help.
I'm writing an Android app which receives data from a server. Theoretical there could not be an internet connection so I try to catch this case by catching a SocketTimeoutException to show an error message an a retry screen or something else. Unfortunately this exception won't be thrown. At least it doesn't jump into the catch clause. What am I doing wrong?
public class HttpConnector {
private String urlString;
private int connectionTimeout = 5000; //milliseconds
public HttpConnector(String urlString) {
this.urlString = urlString;
}
public String receiveData() throws PolizeiwarnungException {
URL url = null;
HttpURLConnection urlConnection = null;
StringBuffer b = new StringBuffer();
try {
url = new URL(urlString);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(connectionTimeout);
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //Here it gets stuck if there is no connection to the server
String str;
while ((str = reader.readLine()) != null) {
b.append(str + "\n");
}
}
catch (SocketTimeoutException e) {
//TODO
e.printStackTrace();
}
catch (IOException e) {
throw new PolizeiwarnungException(e);
}
finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return b.toString();
}
public void sendData(String data) {
//TODO
}
}
You need to also set the connect timeout. Please see this documentation.
Since the end point does not exist, without having set a connect time out the connection will never time out.
setConnectTimeout(int timeout) Sets the timeout value in milliseconds
for establishing the connection to the resource pointed by
this URLConnection instance.