I have an app with an httprequest. I wanted to set a timeout for that request, and since I can't control de DNS timeout a user from stackoverflow suggested to create a Thread with a timer to cancel the request after a certain time, and that's what I'm doing.
In my new Thread I use Thread.sleep to wait 30 seconds and, when that time finishes, cancel the request if it hasn't ended, but my Thread never wakes up. This is my code:
private Thread timeout_request = new Thread(new Runnable() {
public void run() {
try{
Log.d(TAG, "Thread start");
Thread.sleep(30000);
Log.d(TAG, "Thread awake");
if(!httprequest_finished){
request_aborted = true;
mHttpClient.getConnectionManager().shutdown();
}
}catch(Exception e){
e.printStackTrace();
}
}
});
public String sendData(String token){
...
timeout_request.start();
Log.i(TAG, "Sending request");
final HttpResponse resp = httpClient.execute(post);
Log.i(TAG, "Execute finished");
if(request_aborted) return null;
httprequest_finished = true;
...
}
If I execute the sendData function without internet connection the log shows "Sending request" and "Thread start", but doesn't show "Thread awake" or "Execute finished" (I've waited like 5 minutes). Why is that?
------ EDIT ------
By the way, I don't know if it matters, but I'm using ThreadSafeClientConnManager in my connection.
I've tested a few thing:
1- Replace HttpResponse resp = httpClient.execute(post) with while(!request_aborted). The thread awakes (it works).
2- Use mHandler.postDelayed(r, 30000) instead of a Thread. I'm still executing httpClient.execute(post). Result: the Runnable is NOT launched.
private Handler mHandler = new Handler();
private Runnable r = new Runnable() {
public void run() {
Log.d(TAG, "Runnable()");
if(!httprequest_finished){
request_aborted = true;
mHttpClient.getConnectionManager().shutdown();
}
}
};
3- Use mHandler.postDelayed(r, 30000) instead of a Thread. Replace HttpResponse resp = httpClient.execute(post) with while(!request_aborted). Result: the Runnable is NOT launched.
So the thread works if I'm not executing the http request, but the handler never works. I noticed these lines in my log:
threadid=3: reacting to signal 3
Wrote stack traces to '/data/anr/traces.txt'
threadid=3: reacting to signal 3
Wrote stack traces to '/data/anr/traces.txt'
This appears 6 or 7 seconds after executing the thread or setting the handler. I've tried to use:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
Log.e("Alert","Lets See if it Works !!!");
}
});
But the log never shows "Lets See if it Works !!!". I looked the traces.txt file and I don't understand what it's saying -.-
I have tested the following code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication1;
/**
*
* #author paro
*/
public class JavaApplication1 {
public boolean req_aborted = false;
public Thread timeout_request = new Thread(new Runnable() {
public void run() {
try{
System.out.println("start");
Thread.sleep(30000);
System.out.println("awake");
if(req_aborted ==false)
{
req_aborted = true;
System.out.println("flag change");
}
}catch(Exception e){
e.printStackTrace();
}
}
});
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
JavaApplication1 jap = new JavaApplication1();
jap.timeout_request.start();
System.out.println("requset started");
if(jap.req_aborted)
{
System.out.println("flag is true now");
}
}
}
and the output is
requset started
start
awake
flag change
seems that no problem with the thread related part of your code.
and your code's logic says it should print "awake". seems that you are having problem with the following statement
final HttpResponse resp = httpClient.execute(post);
Rather than using Thread.sleep I think you should be using Handler.postDelayed. Have a look at the documentation.
Something like:
Handler mHandler = new Handler();
...
mhandler.postDelayed(new Runnable() {
public void run() {
if(!httprequest_finished){
request_aborted = true;
mHttpClient.getConnectionManager().shutdown();
}
}
}, 30000);
This will execute the passed in Runnable after the specified delay.
Related
I'm very new to Android programming so pls excuse my ignorance...
I'm trying to do simple Android app:
User presses a button, starts postDelayed job and then waits on conditional var
after timeout the postDelayer job should signal
private final static long TIMEOUT = 10000;
private Handler mHandler;
final Lock lock = new ReentrantLock();
final Condition condition = lock.newCondition();
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mHandler = new Handler();
...
}
private void timeOutSignal() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d(">> ", "---> timeout notify");
lock.lock();
try {
condition.signal(); // releases lock and waits until doSomethingElse is called
} finally {
lock.unlock();
}
}
}, TIMEOUT);
}
public void buttonClick(View view) {
timeOutSignal();
Log.i("???", "... WAIT");
lock.lock();
try {
condition.await();
} catch (InterruptedException e) {
// todo
} finally {
lock.unlock();
}
Log.i("???", "... WAIT DONE !");
}
What happens is that buttonClick() is stuck waiting and I'm not even seeing the "---> timeout notify" message after timeout...
What I'm doing wrong ?
EDIT: Tried to fix messed up example...
You can't do what you're trying to do. Handlers run on Looper threads. Handlers that are created with the default constructor will use Looper thread that it is currently running in. In this case, it is the main Looper thread (or UI thread). So, you're locking on the UI Thread and the Handler unlocks on the UI Thread, but it will never reach that point because you're blocking the UI Thread.
Also, at no point do I see you actually calling the method that posts to the Handler.
My USB Host is receiving sensor data and it is getting updated every 200ms. I would like to read this data in my android app every 200ms. I am able to read it using bufferreader, It reads the data for sometime and then hangs. It is not consistent. I am new to this and may be I am not doing it the correct way. Below please find my code and let me know your suggestions. Thanks in advance.
public void startProcessOne()
{
new CountDownTimer(110,100)
{
#Override
public void onTick(long millisUntilFinished)
{
StringBuilder text = new StringBuilder();
line = "";
try {
FileReader in = new FileReader("/mnt/udisk/TEST.TXT");
BufferedReader br = new BufferedReader(in);
int i=0;
char[] buf = new char[10000];
while((i = br.read(buf,i,100))!= -1)
{
String h = new String(buf);
text.append(h);
text.append('\n');
}
br.close();
}
catch (IOException e) {
//You'll need to add proper error handling here
}
TxtRead.setText(text.toString());
}
#Override
public void onFinish()
{
startProcessOne();
}
}.start();
}
TxtRead.setText(text.toString());
This line is causing the problem. You can't touch UI elements from a background thread. You should instead run those codes in the UI/Main thread.
In your case, I'd personally prefer using Java threads. So, create a background thread to keep running periodically. If you would need to run UI methods from that background thread. You probably need a handler attached to the main thread.
// Instantiate a handler in UI thread
final Handler handler = new Handler();
new Thread(new Runnable(){
// Once you're done and want to break the loop, just set this boolean
private boolean stopped = false;
#Override
public void run(){
while(!stopped) {
// Read from the file
// Whenever you need to update an UI element,
// you should wrap it inside this runnable object
handler.post(new Runnable(){
#Override
public void run(){
// Update UI
TxtRead.setText("new_text");
}
})
try {
// This thread will sleep for 9 seconds
Thread.Sleep(9000);
} catch(Exception e){}
}
}
}).start();
I'm using HockeyApp to catch crash issues from internal testers and a single crash report with this trace came in:
java.lang.IllegalThreadStateException: Thread already started
at java.lang.Thread.checkNotStarted(Thread.java:849)
at java.lang.Thread.start(Thread.java:1059)
at com.myapp.service.ApiService.connect(ApiService.java:258)
at com.myapp.service.ApiService.connect(ApiService.java:250)
at com.myapp.service.ApiService.connectForRecord(ApiService.java:748)
at com.fmyapp.service.ApiService.connectForRecord(ApiService.java:733)
at com.myapp.service.ApiService.getOxiChekList(ApiService.java:703)
at com.myapp.service.ApiService.access$1200(ApiService.java:35)
at com.myapp.service.ApiService$1.run(ApiService.java:420)
at java.lang.Thread.run(Thread.java:818)
After looking over SO it looks like the issue is that the code is calling onStart() after the thread has finished. However the only code in my service which calls onStart() is below. Note that it is started after a NEW thread has been created. This has only happened once so I'm not certain on any repro steps but I'm curious if anyone else knows what could cause this.
Line 256-260 (crash at line 258)
private void connect(ApiMethod apiMethod, Token authToken, long apiRefKey, String[] urlParams, Object... params) {
mConnectThread = new ConnectThread(apiMethod, authToken, apiRefKey, urlParams, params);
mConnectThread.start();
mIsRunning = true;
}
I recently faced this issue,
i checked for whether the State of thread is terminated and re initiated the thread and my problem is solved, hope this will help you
For ex:
if(mythread.getState().equals(Thread.State.TERMINATED)) {
mythread = new Thread(new Runnable() {
#Override
public void run() {
while(status == GameStatus.Running) {
try {
Thread.sleep(1000);
timelapsed += 1;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
Following code is within an android activity class.
The project required a non-stop thread when apps is active and stop when apps is inActive/closed.
I predicted to see a non-stop "Hello World" message display in logCat.However I only saw one-times Hello World messgae .
What wrong of my code,so that I able to see a non-stop "Hello World"
Hope someone advice. Thanks
#Override
protected void onStart(){
super.onStart();
Log.e("onStart","beforeStart");
new HttpRequestTask().execute();
Log.e("onStart","Start");
this.pickButtonThread();
}
private void pickButtonThread(){
new Thread() {
#Override
public void run() {
try {
// code runs in a thread
PickerItemActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// code runs in a UI(main) thread
//isPickButtonEnableDisable();
//new HttpRequestTask().execute();
Log.e("pickButtonThread", "Hello World");
}
});
} catch (final Exception ex) {
}
}
}.start();
}
That's because you don't have any loop inside your run() method, thus it's run just once and it exits. However, declaring an endless loop is not considered a good idea as Android OS might kill it if there's lack of memory.
You could use a Handler using the .postDelayed() method to post messages every X seconds.
private Handler mHandler = new Handler();
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
Log.e("pickButtonThread", "Hello World");
mHandler.postDelayed(this, 1000); // Every second
}
};
I have an app that runs 2 threads in loops. 1st one is updating a graph in 1s interval and the second one is updating another graph at 60s interval. The second task is taking a long time since it is quering some server in the internet 3 times that might not always be available and even if it is it will take up to 5-7s to execute.
What is happening is when I launch the second thread it will pause execution of the first one and that is not what I want, I wish both run concurrently. Here in the Youtube video you can see the results of the app running. http://youtu.be/l7K5zSWzlxI
"thread_updater1s" is running a green graph, large readout, and a timer in the corner so you clearly see it stalls for 11 seconds.
1)First of all why is that happening? how to fix it?
2)I'm aware that I might not launch the threads properly at all. I had hard time understanding how to make something to run in a interval loop in Java and my code worked fine for one graph/tread. Now when I have 2 loops in separate threads I don't know why they are not executing concurrently.
Here is the code:
public class LoopExampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
thread_updater1s.start();
thread_updater2.start();
}// end of onCreate
final Runnable r1s = new Runnable() {
public void run() {
do_1s_updates(); // those are very quick http calls to the local API server
} // to get data nessessary for some plot.
// They have 1s timeout as well but rarely timeout
};
final Runnable r2 = new Runnable() {
public void run() {
do_large_updates(); //This makes 7 long call over the Internet to the slow https
//server once every 60s. Has 10s timeout and sometimes takes as much as
//7s to execute
}
};
Thread thread_updater1s = new Thread() {
#Override
public void run() {
try {
while (true) {
handler.post(r1s);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread_updater2 = new Thread() {
#Override
public void run() {
try {
while (true) {
handler2.post(r2);
sleep(60000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
PS. please be forgiving and informative I only code Java for 15 days so far with absolutely no prior experince or lesson.
You need to make the http requests in the threads (not the posted runnables). Then, when you have the data downloaded, you create a runnable with that data that will update the graph and post that runnable to be executed by the UI thread. Here is an example:
public class LoopExampleActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
thread_updater1s.start();
thread_updater2.start();
}// end of onCreate
Thread thread_updater1s = new Thread() {
#Override
public void run() {
try {
while (true) {
final Object data = getDataFromServer1();
handler.post(new Runnable() {
#Override
public void run() {
updateGraph1(data);
}
);
sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread_updater2 = new Thread() {
#Override
public void run() {
try {
while (true) {
final Object data = getDataFromServer2();
handler.post(new Runnable() {
#Override
public void run() {
updateGraph2(data);
}
);
sleep(60000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Obviously, change that final Object data by the appropriate class that represents your data downloaded.
handler.post pushes the runnable onto the main (UI) thread's message queue for execution on the main thread.
So what you're doing is every sleep interval, you're sending a message to the main thread to run the function. Clearly, the main thread can't run 2 things at once, so that's why one runnable is delayed for the next one.
You probably want to do the work of the runnable in the separate threads - why did you start using a handler? What happens if you call do_1s_updates and do_large_updates directly instead of through the handler & runnable?