Android - Runnable run() function is not working - java

I am working on an android application extending activity and implementing Runnable.
The problem is that the run() function is not launched and I'm not sure if implementing Runnable make it launch automaticly as AsyncTask?
Here is my code
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener, Runnable {
...
#Override
public void run() {
// mediaPlayer is myMediaPlayer
// progress is my SeekBar
Log.w("Tunesto", "testabababab");
int currentPosition = 0;
int total = mediaPlayer.getDuration();
progress.setMax(total);
while (mediaPlayer != null && currentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = mediaPlayer.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
progress.setProgress(currentPosition);
Log.w("MyApp", String.valueOf(currentPosition));
}
}
}
Obviously if I launch Run fro, the UI Thread it will freeze the screen because of the sleep method, so how should I do to let the Run method to run?
Thank you!

You will have to use AsyncTask in Android.
Steps to perform:
Create a nested class which extends AsyncTask
Implement the doInBackground method, where your logic should reside
Call the execute method on your nested class instance from where you need to call run()
The fact is i'm not sure if it's possible to stop an asyntask?
You can cancel the async task using the cancel() method on the AsyncTask. Refer to Android Documentation for more details on this.
Edit
To move your code inside the run() function to an AsyncTask, you will put anything that is "setting up" UI stuff inside onPreExecute() such as creating a ProgressBar. Then put your work in such as calling sleep() and other things that can't be done on the UI Thread inside doInBackground(). If you need to update your seek bar you can do that in onProgressUpdate() by calling publishProgress() inside doInBackground(). Finally, if you need to dismiss the ProgressBar or do some ending UI stuff you will do that in onPostExecute().
The reason for that explanation is because all methods of AsyncTask run on the UI Thread except for doInBackground().
AsyncTask Docs
Vogella: Background tasks in Android

new Thread(this).start();
Although an anonymous inner class on either the handler or async would be better than making the activity itself Runnable.

Related

AsyncTask executes at the end of the function

I am using AsyncTask so that the function I want executes immediately and does not wait till the end to be executed..
but for some reason I don't why it executes in at the end of all process!
I looked at other solutions and found that Thread should be executed at the end but for AsyncTask it should be executed whenever it is called..
here is my code
private void LogMeIn()
{
string CheckValue;
// Here I call the AsyncTask
new GCM().execute(null,null,null);
//gcmRegID is a public variable and should has GCM value assigned to it by now, but I it is empty as GCM() has not been executed yet
//This is always return empty string
CheckValue = gcmRegID;
}
This is the AsyncTask that wait till the end to be executed
//This is the AsyncTask
private class GCM extends AsyncTask<String, String, String> {
private String resp;
private Context context;
#Override
protected String doInBackground(String... params) {
GCMHelper gcmRegistrationHelper = new GCMHelper (
getApplicationContext());
try {
gcmRegID = gcmRegistrationHelper.GCMRegister("123456789");
} catch (Exception e) {
e.printStackTrace();
}
return gcmRegID;
}
}
I tried to put the call for GCMRegister in onPreExecute but i get an error that it has to be in the main thread
it is like i am going in circles....
the call has to be in the main thread and the main thread will be executed at the end of the function...
it is like no way to get the GCM code in the middle!!!!
How can I make this AsyncTask executes when it called??
Thanks
Without seeing more of your code it's hard for me to tell but I would take a look at where you are calling LogMeIn(). Because your AsyncTask and call to execute are nested in the LogMeIn() function, it won't be called until LogMeIn() is first called.
AsyncTask goes through the following 4 steps in order after calling execute():
onPreExecute()
doInBackground(Params...)
onProgressUpdate(Progress...)
onPostExecute(Result)
These can be added to your GCM class and used however you like. Note that you don't call them directly. AsyncTask does it automatically after calling .execute().
Only the tasks specified in doInBackground(Params...) are executed on a background thread. The rest are all done on the UI(or main) thread. I would suggest putting either a toast or a log inside onPreExecute() and in onPostExecute() to debug where/when GCM().execute is actually being called and then to tell you when the background task is complete. This will give you a better idea of what is going on.
Make sure you aren't trying to update the UI in doInBackground().
Would love to help more but we would need to see more of your code.
#Override
public void onPreExecute() {
super.onPreExecute();
Log.d("GCM", "onPreExecute: called");
}
#Override
public void onPostExecute(String resultOfDoInBackground) {
super.onPostExecute(resultOfDoInBackground);
Log.d("GCM", "onPostExecute: called");
}
AsyncTask keeps a queue of tasks and a thread pool,the thread pool execute the tasks one by one,so if you have too more tasks ,you will find it not execute your tasks immediately.
And in one process ,all your AsyncTask share one thread pool.In this case,you should make one task queue by yourself,you can just use HandleThread to execute a timely task.
Try placing your new GCM().execute(null,null,null); in the protected void onCreate(Bundle savedInstanceState) method. this way it will be called once the app is ran. This way you will have your GCM id before you get to the LogMEIn method.
Try this -
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new GCM().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params);
} else {
new GCM().execute();
}

Display ProgressDialog until AsyncTask finishes, then update UI

This is the flow of my app:
1) The user takes a picture or video
2) The media is saved to internal storage
3) The path is assigned to a custom object
4) The UI is updated to indicate that the user can continue
The UI updates only if the custom object has either an imagepath or a videopath. I've just started using AsyncTask to save to internal storage in a background thread so the app will not hang while saving large files, but I'm having some problems.
What I want to do: Display a ProgressDialog until doInBackground() finishes, then assign the path to my Object, and then continue on the main thread to update the UI.
Right now, the main thread will continue while AsyncTask is still working, and the UI will not update correctly since the path has not yet been assigned to the Object.
I've read about AsyncTask#get(), but I'm not sure how to implement it with the ProgressDialog. I tried, and the main thread didn't seem to wait for the results before continuing.
I'd really appreciate any help. Thank you!
My AsyncTask:
private class SaveMediaTask extends AsyncTask<Integer, Void, String>
{
private ProgressDialog progressDialog;
private int mediaType;
public SaveMediaTask()
{
progressDialog = new ProgressDialog(getActivity(), ProgressDialog.THEME_HOLO_LIGHT);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
this.progressDialog.setTitle("Processing");
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
this.progressDialog.show();
}
protected String doInBackground(Integer... mediaType)
{
//save to internal storage and return the path
return path;
}
protected void onPostExecute(String path)
{
//by the time this runs, the UI has already tried to update itself on the main thread,
//and found that myObject does not yet have a path. Once this runs, it is too late.
myObject.setPath(path);
if (progressDialog.isShowing())
{
progressDialog.dismiss();
}
}
}
How I call it, immediately after the user leaves the camera:
new SaveMediaTask().execute(MEDIA_TYPE_IMAGE);
//WAIT HERE AND DISPLAY PROGRESSDIALOG UNTIL TASK IS DONE
//update UI
Your onPostExecute should notify your activity, that it can continue. So basically:
// Start the task from your activity
new SaveMediaTask().execute(MEDIA_TYPE_IMAGE);
// Method that will be called when task is completed
public void taskComplete() {
// update UI
}
...
protected void onPostExecute(String path) {
myObject.setPath(path);
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
((YourActivity)getActivity()).taskComplete();
}
the main thread didn't seem to wait for the results before
continuing.
the main thread wouldn't wait. This isn't how AsyncTask work. AsyncTask runs in background along with your main thread.
then continue on the main thread to update the UI.
You don't need to continue on the main thread to update the UI once AsyncTask task is done, you could simply execute that post doInBackground task in onPostExecute() after dismissing the progressDialog, i.e progressDialog.dismiss(); because onPostExecute runs in the UI thread.
Also, the good way is to start progressDialog inside onPreExecute() method and dismiss it in onPostExecute without checking if the progessDialog is still showing or not because onPostExecute() would only run if the doInBackground() method is finished doing its job.
What I want to do: Display a ProgressDialog until doInBackground()
finishes, then assign the path to my Object, and then continue on the
main thread to update the UI.
Start ProgressDialog in onPreExecute,
Assign the path to your object in doInBackground
Dismiss ProgressDialog in onPostExecute,
Continue your main thread work in onPostExecute since it runs in UI thread.
You can also update your UI thread while doInBackground is still running by invoking publishProgress(). Each call to this method will trigger the execution of onProgressUpdate() on the UI thread.
Tip: Its a good idea to dismiss progressDialog inside onCancelled() method beside dismissing it in onPostExecute() in case if you ever cancel your task inside doInBackground
You can move your code marked with //update UI to the end of your onPostExecute method. onPostExecute is always called on UI thread and is a good place to update UI to reflect the AsyncTask work results.

How to update UI from a Runnable?

I need to update ui from runnable. My logic goes like below.
I start the runnable from onCreate of the fragment lifecycle. And the runnable instance is responsible to request network. The problem is I don`t know how to update the fragment after runnable instance fetched the data from network.
code to start runnable in fragment in CustomFragment.java.
public void onCreate(Bundle savedInstanceState) {
Log.d(DEBUG_TAG, "onCreate");
super.onCreate(savedInstanceState);
accountMgr.requestAccountInfo();
}
code to start runnable in AccountManager.java
/**
* request Account info from server
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void requestAccountInfo() {
Account act = getCurrentAccount();
Thread t = new Thread(new RequestAccountInfoTask(act));
t.start();
}
/**
* automatically update Account info, like space usage, total space size, from background.
*/
class RequestAccountInfoTask implements Runnable {
private Account account;
public RequestAccountInfoTask(Account account) {
this.account = account;
}
#Override
public void run() {
doRequestAccountInfo(account);
}
}
runOnUiThread() requires Activity reference. There are alternatives. You don't need Activity reference to your Thread. You can always get UI handler with the main looper. Pass other arguments like your interface to update the fragment upon completion of your task.
class RequestAccountInfoTask implements Runnable {
private Account account;
private Handler mHandler;
public RequestAccountInfoTask(Account account) {
this.account = account;
mHandler = new Handler(Looper.getMainLooper());
}
#Override
public void run() {
doRequestAccountInfo(account);
//use the handler
}
}
Anything you run on the instantiated Handler will be on UI thread.
Of course, using runOnUiThread() is totally reasonable.
you can use runOnUIThread method of activity.
here's code may be help you:
class RequestAccountInfoTask implements Runnable {
private Account account;
public RequestAccountInfoTask(Account account) {
this.account = account;
}
#Override
public void run() {
doRequestAccountInfo(account);
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// you can update fragment UI at here
}
});
}
}
}
Please take a look at AsyncTask for updating the UI from a thread:
http://developer.android.com/reference/android/os/AsyncTask.html
Here are the highlights from the above link:
Class Overview AsyncTask enables proper and easy use of the UI thread.
This class allows to perform background operations and publish results
on the UI thread without having to manipulate threads and/or handlers.
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent package such as Executor, ThreadPoolExecutor and
FutureTask.
An asynchronous task is defined by a computation that runs on a
background thread and whose result is published on the UI thread. An
asynchronous task is defined by 3 generic types, called Params,
Progress and Result, and 4 steps, called onPreExecute, doInBackground,
onProgressUpdate and onPostExecute.
You Cannot Update UI from runnable. You Need Handler for Updating UI. See this for more info.
The UI only can be modified by the thread that create it. In tho most cases is by the UI thread. So you need yo update using runOnUiThread method. Good Luck
I recommend using an AsynTask or you can just try this
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getActivity(), "ON UI Thread", Toast.LENGTH_LONG).show();
}
});
I know it's a bit different answer. But I want you to see Android Annotations. Which are very easy to use . I use them only for background and Ui thread. Do every task in background thread by writing #Background over your method name. And do all the UI update in UI thread. I advice you to just check it once. http://androidannotations.org/
Thanks
And as far as your answer is concern . You can not update your UI from runnable. See the asyn task for updating your Ui.
You can use the event bus to do it - http://square.github.io/otto/
It is pretty simple. Just send event from your Thread when you need to update the UI like this:
...
//in the end of your heavy job:
bus.post(new YourEvent());
and in your Activity create method:
#Subscribe
public void onYourEvent(YourEvent event) {
//do what you want there
}
by the way, you can pass any data through event, it is your custom class! Please read manual how to set up this lib, register activity for bus. It is very useful and easy-to-use
You can create a Runnable that then posts to the main thread. From Google's developer pages on Processes and Threads
This implementation is thread-safe: the background operation is done
from a separate thread while the ImageView is always manipulated from
the UI thread.
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
// a potentially time consuming task
final Bitmap bitmap =
processBitMap("image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}

Calling activity from class that doesnt extend Activity

Is there any way to call an activity from something that doesnt extend Activity? without running it on UI-tread. I want toast-messages in my game, like in candy crush. But I have no idea how to call the toast-activity in an efficient way during real-time.
I know you can use context and get activity from that but it does not run very smoothly. Does anyone have experience with how to do this?
Toasts as well as other components that manipulates the user interface must not be used outside of the UI thread.
What you could do in order to solve your issue, is to design a messaging system between the thread managing you game, and your UI thread. In order to do so, you can use a Handler and its messaging facilities (sendMessage, post, postDelayed ...) to send messages or even Runnables to be run on your main thread.
If you create a Handler in the main thread, it will automatically associate itself with your main thread's event loop, thus making every work sent to it be executed in the main thread.
A basic example of what you could do would be :
class MainActivity extends Activity {
// The handler is associated with your Activity's thread
private Handler _handler = new Handler();
// ...
private Thread _worker = new Thread() {
#Override
public void run() {
_handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Some text", Toast.LENGTH_SHORT).show();
}
});
}
};
};
As a shorthand, you could also use Activity.runOnUiThread(Runnable r) that executes the given runnable in the UI thread by default.

Can I do network operations (UI blocking) inside handlers/runnables?

in my mainActivity, which is the sole activity of my application, I am creating the below handler and running a runnable inside it.
I have some misunderstandings about handlers and where they run.
See the code
Handler handler;
#Override
protected void onCreate(Bundle bundle)
{
handler = new Handler();
handler.postDelayed(r , 5000);
}
Runnable r = new Runnable()
{
#Override
public void run() {
FetchServerAndUpdateStatus(); //network stuff in here
handler.postDelayed(r , 5000);
}
}
I assume this code will still run in UI thread and I won't be able to make any network calls in there no ?
If yes, what shall I do ? Create and use a seperate thread ?
If I created a new thread, How can I run the postdelayed method ? The thread does not have post delayed ?
Does not using handler/runnable and using TimerTask and Runnable instead a better approach ? Or, just like the above handler/runnable, that will also run on the UI thread, unless created inside a seperate one.
When you construct a Handler it is bound to the thread it is constructed on.
onCreate() is run on the UI thread so this handler will be bound to the Looper on the main thread, and thus will run on that thread.
If you want a handler you can use on another thread you can construct one.
See the looper docs: https://developer.android.com/reference/android/os/Looper.html
Which has this block:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
synchronized (this) {
this.notifyAll();
}
Looper.loop();
}
}
Add this class and then in your onCreate do the following:
mLooperThread = new LooperThread();
mLooperThread.start();
synchronized (mLooperThread) {
while (null == mLooperThread.mHandler) {
mLooperThread.wait();
}
}
mLooperThread.mHandler.postDelayed(r , 5000);
This will cause the runnable to be run NOT on the UI thread, which is probably what you wanted.
For tasks that need to interact with the UI an AsyncTask may be better since it includes a mechanism to run things that touch Views when the task is done on the UI thread, since anything that touches a View must be done on the UI thread.
The other mechanisms for executing on the UI thread are to post to the view itself:
https://developer.android.com/reference/android/view/View.html#post(java.lang.Runnable)
or
[https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long)](https://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long))
Or to ask the Activity to run it on the UI for you:
https://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)
It depends on what you do with your handler, you didn't show, how you want to obtain m_handler. If you create it with new Handler(Looper.getMainLooper()), it will run on UI thread.
If you want to run code in background (network operations) you should use AsyncTask

Categories