AsyncTaks HTTP-request timeouts and exception handling - java

I'm making HTTP-get requests to the Facebook graph API.
In about 1/5 times my code never gets to Log.i("debug", "resp");. No exception thrown. Shouldn't it? Or is it just a very long timeout by default?
If I add a custom timeout (see below), I get to throw an exception. But even though my code is wrapped in a try+catch statement, my app crashes (just like on any unhandled exceptions), instead of letting me handle the error in onPostExecute(). Why dont I end up in the method?
protected Map<String, Integer> doInBackground(Void... params) {
Map<String, Integer> result = new HashMap<String, Integer>();
try {
HttpGet get = new HttpGet("https://graph.facebook.com/....etc");
//final HttpParams httpParams = httpclient.getParams();
//HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
//HttpConnectionParams.setSoTimeout(httpParams, 5000);
HttpResponse response = httpclient.execute(get);
Log.i("debug", "resp");
HttpEntity resEntityGet = response.getEntity();
//do stuff with resEntityGet
return result;
} catch (Exception e) {
Toast.makeText(mainActivity, "Error: " + ex.getMessage(), Toast.LENGTH_LONG).show();
return null;
}
}
protected void onPostExecute(Map<String, Integer> result) {
if(result != null){
//use the result data
} else {
//exception occured
}
}

You can show a Toast from the doInBackground method if you post it to the UI thread. There's a few ways to do it, but here's one way:
mainActivity.runOnUiThread( new Runnable() {
#Override
public void run() {
Toast.makeText(mainActivity, "Error: " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
} );
You'll need to make the Exception variable final

Figured it out myself. Turns out that you can't create toasts in doInBackground(). Hope this helps someone else.

i also faced same problem that time i handle exception this way
public class ServerCheckingActvity extends Activity{
ProgressDialog progress;
static String constant="";
Map<String, Integer> result;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyAsynchTask().execute();
}
private class MyAsynchTask extends AsyncTask<Void,Void,String>{
#Override
protected void onPreExecute(){
progress=new ProgressDialog(ServerCheckingActvity.this);
// progress.setTitle(" DATA RETRIVEING");
progress.setMessage("please wait........");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.setCancelable(true);
progress.show();
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
String view="";
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet("www.facebook .com/...........");
//final HttpParams httpParams = httpclient.getParams();
//HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
//HttpConnectionParams.setSoTimeout(httpParams, 5000);
HttpResponse response =httpClient.execute(get);
Log.i("debug", "resp");
HttpEntity resEntityGet = response.getEntity();
//do stuff with resEntityGet
// assigen ur value to result map object here;
result = new HashMap<String, Integer>();
} catch (Exception e) {
constant="Exception";
//Toast.makeText(mainActivity, "Error: " + ex.getMessage(), Toast.LENGTH_LONG).show();
//return null;
}
return view="from doing background";
}
#Override
protected void onPostExecute(String view ){
if(constant=="Exception"){
constant="";
Toast.makeText(getApplicationContext(), "server problem", Toast.LENGTH_LONG).show();
}else if(result != null){
//use the result data
} else {
//exception occured
}
}
}

catch (Exception ex) {
// execep is here string variable u declare in globally
execep=ex.getMessage();
runOnUiThread( new Runnable() {
#Override
public void run() {
Toast.makeText( getApplicationContext(), "Error: " +execep, Toast.LENGTH_LONG).show();
}} );
}//catch

Your code is right but it's not clearly and safe. If you do not set up timeout, it is set default value 0. A timeout value of zero is interpreted as an infinite timeout. In that case , when response data has problem because of anything, your client either is interrupted or do not know anything. In case 2 - worse case - client will not throw any exception and your program will live forever.
Resolve for this problem, you should set timeout when get or post everything to server. It's safe.
I do not exactly know the cause client lives forever without any exception. I think it it a server problem or network problem.
Hope can help you.

Related

Interface returning null in java

I am trying to get information from my AsyncHttpClient in my Android app, and I need to use an interface to set the variable so I can use it in my main method. However, when I run System.out.println(PostResponse);, I am getting null.
I don't understand why, because if I put the line in my callback() method, I get the values.
From my main method:
try {
JSONArray PostResponse = PerformPostRequest(new OnJSONResponseCallback() {
#Override
public JSONArray onJSONResponse(boolean success, JSONArray response) {
System.out.println("Response: " + response); //This is returning the correct value
return response;
}
}, PostData);
System.out.println("Useable: " + PostResponse); //This is returning null.
} catch (Exception e) {
e.printStackTrace();
}
The interface:
public interface OnJSONResponseCallback {
public JSONArray onJSONResponse(boolean success, JSONArray response);
}
The AsyncHttpClient:
public JSONArray PerformPostRequest(final OnJSONResponseCallback callback, JSONObject PostData) {
//To authenticate against the API we need the user's credentials
String Email = getSharedPreferences(ctx).getString("Email","");
String Password = getSharedPreferences(ctx).getString("Password","");
final JSONArray[] ResponseStorage = new JSONArray[1];
//Add the credentials to post data
try{
PostData.put("email", Email);
PostData.put("password", Password);
} catch (Exception e){
e.printStackTrace();
}
//Then we need to put the post data into request parameters so we can send them in the call.
RequestParams RequestParameters = new RequestParams();
RequestParameters.put("data", PostData);
//This is the client we will use to make the request.
AsyncHttpClient client = new AsyncHttpClient();
client.post(AppHost + "MyMeetings.php", RequestParameters, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
String ResponseString = new String(responseBody);
ResponseStorage[0] = new JSONArray(ResponseString);
System.out.println(ResponseStorage[0] + "<============="); //Returns with the array
callback.onJSONResponse(true, ResponseStorage[0]);
} catch (Exception e) {
Log.e("Exception", "JSONException on success: " + e.toString());
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
try {
Toast.makeText(ctx, "Error: " + statusCode, Toast.LENGTH_LONG).show();
} catch (Exception e) {
Log.e("Exception", "JSONException on failure: " + e.toString());
}
}
});
JSONArray ResponseArray = new JSONArray();
try{
System.out.println(ResponseStorage[0] + "<==============="); //Returning null?
ResponseArray = ResponseStorage[0];
} catch (Exception e){
e.printStackTrace();
}
System.out.println("ResponseArray" + ResponseArray); //Returns null
return ResponseArray;
}
Where am I going wrong? I think it is something to do with my call in the main method.
Edit:
1) I tried to return the ResponseArray (set in onsuccess) but I can't return it from onsuccess because it is public void. When I tried to change it to public JSONArray, I get an incompatible return type error.
2) I have updated the method so it returns something other than null, however, it still returns as null, even when I am printing it inside the AsyncHttp.
The general idea behind the asynchronous calls is that:
the asynchronous method call (in your case PerformPostRequest) returns immediately and does not return the expected result - instead it returns either just an accept confirmation or an object from which you can sometimes in the future get the result (such as an instance of a Future)
you provide the method a callback interface (in your case OnJSONResponseCallback) or the method returns an instance of a callback interface, and you check regularly if there is already a result ready.
You should not expect that the asynchronous method returns the result immediately, this is exactly the opposite of asynchronous call.
Here is the rough idea expressed by pictures. It is just an overall picture of the whole idea, so the implementation details may be quite different!
I was trying to set the variable from the PerformPostRequest(), which by default does not get called. At the top of my class, I set a
public JSONArray[] PostResponse = new JSONArray[1];
and updated the bit where I was calling the post request to the following:
//Make a post request
try {
JSONObject PostData = new JSONObject();
PostData.put("action","test");
PerformPostRequest(new OnJSONResponseCallback(){
#Override
public JSONArray onJSONResponse(boolean success, JSONArray response) {
PostResponse[0] = response;
System.out.println(PostResponse[0]); //This will be replaced by calling the method I want to call.
return PostResponse[0];
}
}, PostData);
System.out.println(PostResponse[0]);
} catch (Exception e){
e.printStackTrace();
}

the app crashes when using OkHttpClient in doInBackground [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
My application on Android LOLLIPOP runs well, but in the lower version, program crashe and displays this error:
Exception caught
java.lang.RuntimeException: An error occured while executing doInBackground()
And points to this line of code:
OkHttpClient client = new OkHttpClient();
this is my code:
private void getMoviesFromDBz(int id) {
AsyncTask<Integer, Void, Void> asyncTask = new AsyncTask<Integer, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Integer... movieIds) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(linkkk + movieIds[0])
.build();
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().string());
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
Movie movie = new Movie(object.getInt("id") , object.getString("per") , object.getString("movie_name"),
object.getString("movie_image"), object.getString("movie_genre") , object.getString("movie_discription") , object.getString("movie_lat"), object.getString("movie_lon") , object.getString("movie_marker") , object.getString("sort") , object.getString("price") , object.getString("email") , object.getString("tell") , object.getString("location") , object.getString("count"));
ItemOneFragment.this.movies2.add(movie);
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
adapter2.notifyDataSetChanged();
getMoviesFromDB(0);
}
};
asyncTask.execute(id);
scroll2 = 1;
}
You're trying to access the Main/UI Thread in a background Thread:
ItemOneFragment.this.movies2.add(movie);
just return the movie object and execute the above line on the onPostExecute() method, also I wouldn't recommend instantiating an OkHttpClient for each request.
You're trying to performing action the on UI Thread from background Thread. So you can userunonuithread
runOnUiThread(new Runnable() {
#Override
public void run() {
ItemOneFragment.this.movies2.add(movie);
}
});
see the changes below in your code.
#Override
protected Void doInBackground(Integer... movieIds) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(linkkk + movieIds[0])
.build();
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().string());
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
Movie movie = new Movie(object.getInt("id") , object.getString("per") , object.getString("movie_name"),
object.getString("movie_image"), object.getString("movie_genre") , object.getString("movie_discription") , object.getString("movie_lat"), object.getString("movie_lon") , object.getString("movie_marker") , object.getString("sort") , object.getString("price") , object.getString("email") , object.getString("tell") , object.getString("location") , object.getString("count"));
runOnUiThread(new Runnable() {
#Override
public void run() {
ItemOneFragment.this.movies2.add(movie);
}
});
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
I think this may solve your problem.
You don't need any Asynctask with Okhttp
Look up examples that use the enqueue method
// Build the client and request in the main thread
// Start an asynchronous method
client.newCall(request).enqueue(new Callback() {
#Override public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
JSONObject json = new JSONObject(responseBody.string());
}
}
});
If you want to use JSON objects with Okhttp, Retrofit would be a better library

random com.android.volley.NoConnection error, java.io.InterruptedIOException, statuscode=0

I have a native android app using volley framework to fetch data from a PHP server end script.
It worked well on most time, but I have 20% percentage failure.
The error says:
com.android.volley.NoConnection, java.io.InterruptedIOException.
I debugged that I found the statuscode = 0, which obviously was wrong.
I have no idea what can be the reason? Since it is working most time so there should be no obvious error code.
FYI, those PHP script on the server end works very well for my IOS app.
Please allow me post my code here:
retryConnBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
txtOut.append("\n");
txtOut.append("Button with Retry Click");
Log.d("Click", "Button Click");
final String url = "https://www.myserver.com/api/getBalanceInfoTest?token=7ff3317a4f3dc07d0c297a7d16d2049c&t=" + System.currentTimeMillis();
//final String url = "http://192.168.1.23/base/test/";
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
txtOut.append("\n");
txtOut.append("Result with Retry:");
txtOut.append(response.toString());
Log.d("Response", response.toString());
VolleyLog.e("Response:", response.toString());
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
txtOut.append("\n");
txtOut.append("Error with Retry:");
txtOut.append(error.toString());
Log.d("Error.Response", error.toString());
VolleyLog.e("Error:", error.getMessage());
}
});
getRequest.setRetryPolicy(new DefaultRetryPolicy(5000, 5, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(getRequest);
queue.start();
}
});
}
And for more information, the output of my PHP script is:
{"hsaBalance":"1000.00"}, created by Json_encode() function of PHP.
I have fixed this bug.
It is not a network issue.
queue.add(getRequest);
queue.start();
should be
queue.add(getRequest);
So the key is we should remove queue.start().
Michael Cheng is right,because volley had start the RequestQueue when we call newRequestQueue as below:
public static RequestQueue newRequestQueue(Context context, HttpStack stack) {
File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);
String userAgent = "volley/0";
try {
String packageName = context.getPackageName();
PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
userAgent = packageName + "/" + info.versionCode;
} catch (NameNotFoundException e) {
}
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
// Prior to Gingerbread, HttpUrlConnection was unreliable.
// See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir), network);
queue.start();
return queue;
}
and when we call start, volley will call stop to “make sure any currently running dispatchers are stopped”,in stop method volley does this below:
public void stop() {
if (mCacheDispatcher != null) {
mCacheDispatcher.quit();
}
for (int i = 0; i < mDispatchers.length; i++) {
if (mDispatchers[i] != null) {
mDispatchers[i].quit();
}
}
}
and the quit method does this below:
public void quit() {
mQuit = true;
interrupt();
}
maybe you can see the reason,why interrupted.
More, interrupt method does this below:
public void interrupt() {
// Interrupt this thread before running actions so that other
// threads that observe the interrupt as a result of an action
// will see that this thread is in the interrupted state.
nativeInterrupt();
synchronized (interruptActions) {
for (int i = interruptActions.size() - 1; i >= 0; i--) {
interruptActions.get(i).run();
}
}
}
the reason maybe this as metioned above:
Interrupt this thread before running actions so that other threads that observe the interrupt as a result of an action will see that this thread is in the interrupted state.
You are having sometimes problems with your connection. Look at InterruptedIOException API:
InterruptedIOException Signals that an I/O operation has been interrupted. An InterruptedIOException is thrown to indicate that an input or output transfer has been terminated because the thread performing it was interrupted.
so only you can do is to catch the possible exceptions occuring when converting JSon and having a workaround for this.
// rest of your code...
final String url = "https://www.myserver.com/api/getBalanceInfoTest?token=7ff3317a4f3dc07d0c297a7d16d2049c&t=" + System.currentTimeMillis();
try {
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.GET, url, null,
// rest of your code...
queue.add(getRequest);
queue.start();
} catch (InterruptedIOException e) {
// do something when fail print error, show a toast
System.out.err("Error, connection interrupted" + e.getMessage());
Toast.makeText(getApplicationContext(), "press button again", Toast.LENGTH_LONG).show();
}

JAVA: How to listen to calling of event handler/How to get returned result of an event handler?

I am creating an Android chat application wherein I am using WebSockets and on top of that I want to create a custom implementation of Application protocol.
I am stuck in a situation.
Essentially, what I want is a way to know that an event handler method has been called in another class, fire up my own method in my class based on that and then get the result of that event handler method in my class.
How is that possible?
I researched a lot and found something like binding, event emitters, etc. Can someone point me to the right direction and provide some resources from where I can learn this technique?
This is what I have done so far:
public void connect(){
try {
setUpWebSocketHandler(handler);
mConnection.connect(wsuri, handler);
}
catch (WebSocketException e) {
Log.d("exception", e.toString());
}
}
public void setUpWebSocketHandler(WebSocketHandler handler)
{
handler = new WebSocketHandler(){
//first method for websockethandler
#Override
public void onOpen() {
//here i create a json format string to be sent to my server that returns something afterwards
String output = json.toString();
Log.d("OUTPUT+" , output);
Log.d("onOpen", "Status: Connected to " + wsuri);
mConnection.sendTextMessage(output);
}
//second method for websockethandler
#Override
public void onTextMessage(final String payload) {
Log.d("onTextMessage", "Response: " + payload);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(payload);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
String type = jsonObj.getString("type");
switch (type) {
case "xxx":
//authEvent
System.out.println("xxx");
break;
case "yyy":
//userOnlineEvent
System.out.println("yyy");
break;
case "zzz":
System.out.println("zzz");
break;
case "userListToken":
userList = getUserList(payload);
break;
default:
System.out.println("DefaultCase");
break;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//third method for websockethandler
#Override
public void onClose(int code, String reason) {
Log.d("onClose", "Connection lost.");
}
};
}
public String getUserList(final String payload)
{
final Thread connectthread;
connectthread = new Thread(
new Runnable()
{
public void run()
{
try {
//here i create a URL, send post request to it and i get a response with userlist
HttpClient client = new DefaultHttpClient();
HttpGet post = new HttpGet(url);
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((userList = rd.readLine()) != null) {
System.out.println(userList);
Log.d("HTTP GET RESPONSE", "Response: " + userList);
}
} catch (JSONException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
);
connectthread.start();
try
{
connectthread.join();
}
catch (Exception e)
{
Log.i("error","Error!!");
}
System.out.println("userListToken");
return userList;
}
I have another question. I got the userList using callbacks....The problem now is:
private class ProcessLogin extends AsyncTask<String, Void, String> {
private ProgressDialog pDialog;
String uname,password;
#Override
protected void onPreExecute() {
super.onPreExecute();
uname = txtUsername.getText().toString();
password = txtPassword.getText().toString();
pDialog = new ProgressDialog(LoginActivity.this);
pDialog.setTitle("Contacting Servers");
pDialog.setMessage("Logging in ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... args) {
String user = null;
ifly.connect();
user = userList;
return user;
}
#Override
protected void onPostExecute(String user) {
try {
if(user != null){
//Intent i = new Intent("com.example.tabmainactivity");
Log.d("Got it", "Response: " + userList);
pDialog.dismiss();
//startService(new Intent(getApplicationContext(),iFlyChatMessage.class));
//startActivity(i);
//finish();
}else{
// username / password doesn't match
pDialog.dismiss();
Toast.makeText(getApplicationContext(),
"Incorrect username/password", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void processMessage(String userList)
{
this.userList = userList;
}
I want the userList in postExecute so that i can send this userList to another activity. How do i stop doinbackground() to wait for callback to finish. If I use thread.sleep, the whole process stops, not even connect works.
Thanks
You can declare an interface somewhere, make your event handler accept an instance of this interface, then create an anonymous class implementing this interface while passing that instance in your handler's registration with event source.
Something like below:
public class MyClass{
...
...
component.addXXXListener(new EventHandler(new MyInterface() {
#Override
public void doSomething() {
callMethod();
}
}));
...
...
public void callMethod() {
...
...
}
I hope you got the point.
I'm not sure that I understood you correctly.
You should use callback object.
Something like:
public interface MessageProcesor{
public void processMessage(String message);
}
Your activity should implement this interface.
And you should have MessageProcesor field in your "client" class.
Your code should look something like this:
private MessageProcesor callback;
public void setUpWebSocketHandler(WebSocketHandler handler)
{
handler = new WebSocketHandler(){
//first method for websockethandler
#Override
public void onOpen() {
//here i create a json format string to be sent to my server that returns something afterwards
String output = json.toString();
Log.d("OUTPUT+" , output);
Log.d("onOpen", "Status: Connected to " + wsuri);
mConnection.sendTextMessage(output);
}
//second method for websockethandler
#Override
public void onTextMessage(final String payload) {
Log.d("onTextMessage", "Response: " + payload);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(payload);
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
String type = jsonObj.getString("type");
switch (type) {
case "xxx":
//authEvent
System.out.println("xxx");
break;
case "yyy":
//userOnlineEvent
System.out.println("yyy");
break;
case "zzz":
System.out.println("zzz");
break;
case "userListToken":
userList = getUserList(payload);
callback.processMessage(userList);
break;
default:
System.out.println("DefaultCase");
break;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//third method for websockethandler
#Override
public void onClose(int code, String reason) {
Log.d("onClose", "Connection lost.");
}
};
}
public String getUserList(final String payload)
{
final Thread connectthread;
connectthread = new Thread(
new Runnable()
{
public void run()
{
try {
//here i create a URL, send post request to it and i get a response with userlist
HttpClient client = new DefaultHttpClient();
HttpGet post = new HttpGet(url);
HttpResponse response = client.execute(post);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
while ((userList = rd.readLine()) != null) {
System.out.println(userList);
Log.d("HTTP GET RESPONSE", "Response: " + userList);
}
} catch (JSONException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
);
connectthread.start();
try
{
connectthread.join();
}
catch (Exception e)
{
Log.i("error","Error!!");
}
System.out.println("userListToken");
return userList;
}
You can pass "callback" as constructor param or via setter method.
Hope this helps.

Performance of Android using HttpClient with Apache server running php scripts with Memcache

I have an application in which an Android device is connected to a data acquisition system and the data is stored in a local db. I want to monitor in real time the data on a second Android as well. In order to enhance performance, I set up my own Apache server (XAMPP) on a Windows machine. I wrote two php scripts; one to store data in Memcache and one to get data from memcache. The Android devices are using HttpClient to call the scripts. I used memcache in order to eliminate some delays of writing to database. Below is the code used for sending and receiving the data... For testing, it is a simple loop (counter) with a thread delay. If I set the delay for 1 second, the textview is updated and runs smoothly. When I drop the delay to 0.1 seconds, it runs fine for a few seconds and then stutters (pauses) for 3-5 seconds. It continues this process of intermittent pausing while running. If I drop the delay to 0.01 seconds, the system crashes. My Apache server is connected to directly to my router. The Android devices are connected to my WiFi. My question is whether or not I'm doing something fundamentally wrong. I thought with memcache, I would easily be able to do 0.01 s sampling of data. Is my code properly handling the AsyncTasks? How can I prevent the Android system from apparently becoming "overloaded" with new tasks? It is as if I need a method to determine when a task is complete such that the next task can be called. I appreciate any feedback regarding php, httpclient, etc...anything that affects performance.
EDIT: My system no longer crashes when I drop the delay to 0.01 sec. I now have a catch for the null value in the onpostexecute method. However, I still get stutters/freezes.
private void startsendingdata() {
loop = 0;
if (sendingdatathread != null)
sendingdatathread.interrupt();
sendingdatathread = new Thread() {
public void run() {
while (loop < 5000) {
try {
runOnUiThread(new Runnable() {
#Ov
erride
public void run() {
new SendDataTask().execute();
loop++;
myvar = Integer.toString(loop);
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
sendingdatathread.start();
}
private class SendDataTask extends AsyncTask<String, Integer, Double> {
#Override
protected Double doInBackground(String... params) {
postData();
return null;
}
protected void onPostExecute(Double result) {
}
public void postData() {
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
// put all variables here (with connection code attached)
nameValuePairs.add(new BasicNameValuePair("connectioncode",
connectioncode));
nameValuePairs.add(new BasicNameValuePair("myvar", myvar));
httppostsend
.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httppostsend);
response.getEntity().consumeContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void startgettingdata() {
if (gettingdatathread != null)
gettingdatathread.interrupt();
gettingdatathread = new Thread() {
public void run() {
while (true) {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
new GetDataTask().execute();
}
});
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
gettingdatathread.start();
}
private class GetDataTask extends AsyncTask<String, Integer, Double> {
#Override
protected Double doInBackground(String... params) {
getData();
return null;
}
protected void onPostExecute(Double result) {
if (!line.isEmpty() && line!=null&&connectioncode.length() >= 6) {
tvLapTime.setText("MyVar: " + myvar);
}
}
public void getData() {
if (connectioncode.length() >= 6) {
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("connectioncode",
connectioncode));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
response = httpclient.execute(httppost);
entity = response.getEntity();
is = entity.getContent();
line = convertInputStreamToString(is);
response.getEntity().consumeContent();
} catch (ClientProtocolException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
// convert inputstream to String
private static String convertInputStreamToString(InputStream inputStream)
throws IOException {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(inputStream));
String result = "";
while ((line = bufferedReader.readLine()) != null)
result += line;
try {
json = new JSONObject(result);
} catch (JSONException e1) {
e1.printStackTrace();
}
if (json != null) {
try {
myvar = json.getString(connectioncode + "myvar");
} catch (JSONException e) {
e.printStackTrace();
}
}
inputStream.close();
return result;
}
Do away with startsendingdata() and startgettingdata(). In the onPostExecute() of the tasks initiate the start of the next task. Now you are sure a task is finished before starting a new one. For instance you could start a timer which executes the next task.

Categories

Resources