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
}
};
Related
So I'm attempting to create background task that needs to be run every hour in an Android app. Its a rather heavy task that takes around 5 - 10 minutes to finish, and right now it runs on the UI thread which of course isn't good, because it hangs the whole application. I've attempted the following in my MainActivity onCreate:
new Thread(new Runnable() {
private Handler HeavyTaskHandler = new Handler(Looper.getMainLooper());
public void run(){
final TextView updatedTxt = findViewById(R.id.txt);
updatedTxt.post(new Runnable() {
#Override
public void run() {
updatedTxt.setText("Performing cleanup..");
}
});
HeavyTask(); // <-- This method runs for 5 - 10 minutes
updatedTxt.post(new Runnable() {
#Override
public void run() {
updatedTxt.setText("Done..");
}
});
HeavyTaskHandler.postDelayed(this, HeavyTaskCycle);
}
}).start();
I have two issues with the above
It works fine the first time, and the task is performed in the background well without hanging the UI thread. However, after this first time and the next time(s) it is run, the UI thread hangs again when it is run. What am I missing?
Notice that before the HeavyTask() method is called i try to set a TextViews text to "Performing cleanup.." .. This never shows, only the "Done.." which happens after the HeavyTask() method is done. How can i ensure that the message also appears before?
I ended up doing the following from MainActivity which doesn't hang the application
private void CreateCleanUpThread()
{
CleanUpThread = new Thread(new Runnable() {
public void run(){
try {
while(true) {
performingCleanup = true;
final TextView updatedTxt = findViewById(R.id.updated_txt);
runOnUiThread(new Runnable() {
#Override
public void run() {
updatedTxt.setText("Performing database history cleanup..");
}
});
HeavyTask(); // <-- This method runs for 5 - 10 minutes
runOnUiThread(new Runnable() {
#Override
public void run() {
updatedTxt.setText("Done..");
}
});
performingCleanup = false;
Thread.sleep(CleanUpCycle); // 1 hour wait time
}
} catch(Exception ex) {
System.out.println("Error in CreateCleanUpThread : " + ex.getMessage());
}
}
});
}
// onCreate in MainActivity
...
CleanUpThread.start();
Certainly not the best way, but it works and will do for now. Should be moved to a service instead i think.
I created one handler to repeat a task repeatedly and I also want to destroy it within that handler once a condition has been met.
pinHandler = new Handler();
Now I created two functions separately to start and stop the task.
void startRepeatingPins() {
mPinSetter.run();
}
Runnable mPinSetter = new Runnable() {
#Override
public void run() {
try{
System.out.println("PinIndwx count is :"+pinIndexCount);
if(pinIndexCount==(plist.size()-1))
{
stopUpdatingPins();
pinIndexCount=0;
//pinHandler.removeCallbacks(mPinSetter);
System.out.println("Handler stopped by itself.");
}
else
{
updatePoint(plist.get(pinIndexCount));
pinIndexCount++;
}
}
finally {
pinHandler.postDelayed(mPinSetter, pinInterval);
}
}
};
private void stopUpdatingPins()
{
pinIndexCount=0;
pinHandler.removeCallbacks(mPinSetter);
System.out.println("Called the stop function.");
}
Now, the issue is that, if I call the stopUpdatingPins function , the handler stops but when I try to stop it automatically from within the handler, it just doesn't stop. Although the stopUpdatingPins function does get called.
Change You startRepeatingPins() like this, You should not directly call the run. If your run like this then there is no point of removing this from Handler. So attach Runnable with Handler.
void startRepeatingPins() {
pinHandler.post(mPinSetter);
}
You added post delay in finally that means you are stopping at first if loop and starting again in finally, So it's never stopping. So Change your runnable like this,
Runnable mPinSetter = new Runnable() {
#Override
public void run() {
System.out.println("PinIndwx count is :"+pinIndexCount);
if(pinIndexCount==(plist.size()-1))
{
stopUpdatingPins();
pinIndexCount=0;
//pinHandler.removeCallbacks(mPinSetter);
System.out.println("Handler stopped by itself.");
}
else
{
updatePoint(plist.get(pinIndexCount));
pinIndexCount++;
pinHandler.postDelayed(mPinSetter, pinInterval);
}
}
};
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.
I have a situation in an Android app where I want to start a network activity (sending out some data) which should run every second. I achieve this as follows:
In the onCreate() I have the code:
tv = new TextView(this);
tv.postDelayed(sendData, 1000);
The sendData() function:
Handler handler = new Handler();
private Runnable sendData=new Runnable(){
public void run(){
try {
//prepare and send the data here..
handler.removeCallbacks(sendData);
handler.postDelayed(sendData, 1000);
}
catch (Exception e) {
e.printStackTrace();
}
}
};
The problem come in like this: When user presses the back buttons and app comes out (UI disappears) the sendData() function still gets executed which is what I want. Now when user re-starts the app, my onCreate() gets called again and I get sendData() invoked twice a second. It goes on like that. Every time user comes out and starts again, one more sendData() per second happens.
What am I doing wrong? Is it my new Handler() creating problem? What is the best way to handle this? I want one sendData() call per second until user quits the app (form application manager).
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
Toast.makeText(c, "check", Toast.LENGTH_SHORT).show();
handler.postDelayed(this, 2000);
}
}, 1500);
Perhaps involve the activity's life-cycle methods to achieve this:
Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler.post(sendData);
}
#Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendData);
}
private final Runnable sendData = new Runnable(){
public void run(){
try {
//prepare and send the data here..
handler.postDelayed(this, 1000);
}
catch (Exception e) {
e.printStackTrace();
}
}
};
In this approach, if you press back-key on your activity or call finish();, it will also stop the postDelayed callings.
Why don't you create service and put logic in onCreate(). In this case even if you press back button service will keep on executing. and once you enter into application it will not call
onCreate() again. Rather it will call onStart()
You can simplify the code like this.
In Java:
new Handler().postDelayed (() -> {
//your code here
}, 1000);
In Kotlin:
Handler().postDelayed({
//your code here
}, 1000)
Please check the below its working on my side in below code your handler will run after every 1 Second when you are on same activity
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
handler = new Handler(handlerThread.getLooper());
runnable = new Runnable()
{
#Override
public void run()
{
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
Handler h = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==0){
// do stuff
h.removeMessages(0); // clear the handler for those messages with what = 0
h.sendEmptyMessageDelayed(0, 2000);
}
}
};
h.sendEmptyMessage(0);
I think you could experiment with different activity flags, as it sounds like multiple instances.
"singleTop"
"singleTask"
"singleInstance"
Are the ones I would try, they can be defined inside the manifest.
http://developer.android.com/guide/topics/manifest/activity-element.html
You should set andrid:allowRetainTaskState="true" to Launch Activity in Manifest.xml. If this Activty is not Launch Activity. you should set android:launchMode="singleTask" at this activity
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?