2

I am writing an android app and I need to be able to do certain things periodically/continuously. I am coming from a C/C++ embedded firmware background and this new-fangled way of doing things is going to take some getting used to. It seems that there is no such thing as a "main loop" in Android, that everything is event-driven... I also understand that by default all code you write operates on the GUI thread, and I should probably make a new thread to execute the equivalent of a "main loop"...

So far what I have is an implementation of the AsyncTask class who's "doInBackground" method contains an infinite loop (my main loop), I create an instance of this class and run it immediately when my app starts. The problem I am having is in the interaction between this thread and the user interface... when something occurs in my main loop thread and I want to update the GUI understand that I must call "publishProgress", which is executed on the GUI thread. There are a few problems with this, primarily that many things I have tried to do in this "onProgressUpdate" method do not work, or do not occur in a predictable amount of time.

My question, is there a better way to accomplish what I am trying to do? In general, what do most people do when they have code that they want to run periodically and/or continuously while their application is running, code that must interact with the user interface in a timely manner (by timely I mean with zero delay).

Thank you.

public class MainLoopThread extends AsyncTask<Void, Void, Void>
{
    @Override
    protected Void doInBackground(Void... arg0)
    {
        while(true)
        {
            //Do stuff

            //Update GUI
            publishProgress();
        }   
    }

    protected void onProgressUpdate(Void...voids)
    {
        //Update GUI
    }
}
CHollman82
  • 576
  • 1
  • 8
  • 28
  • 1
    Could you clarify what you are trying to do? What does an execution cycle of your task do? Why is your progress update of type Void and not some data type that actually contains progress information for updating the UI? – tiguchi Jun 27 '12 at 20:30
  • Also, what do you mean under "when my app starts"? Sorry if I'm too self-confident, but since you came from another platform I suspect you're missing some Android fundumentals. Didn't you mean "when my `Activity` starts"? – Vit Khudenko Jun 27 '12 at 20:41
  • Nobu: My app will be communicating over bluetooth to a handheld instrument running a hard real-time operating system that I also designed... the communication cycle must occur in a timely manner. Also, there are various other things that need to occur based on time, not on user input, that would be more suited to a cyclic executive model than to an event-driven model. – CHollman82 Jun 27 '12 at 20:46
  • Arhimed: Yes and no. I do understand that an android app consists of one or more activities, and my app currently has 4 distinct activities. However, ideally this "main loop" that I am trying to make would run all the time, regardless of which activity is active... so I would want to start the loop with the first activity and not interrupt it at all when the activity changes (necessarily, there may be an activity or two that doesn't need the main loop to be running) – CHollman82 Jun 27 '12 at 20:49
  • 1
    I guess a better question to ask is how are games made on Android? Most games are not event-driven but use a cyclic executive instead... most games have things going on all the time, regardless of any input the user might supply, how is that managed on Android? My real problem is, when the activity starts I get an event and capture it with the onCreate() method... when that method ends where does the code "go"? Nowhere? I need to have code executing all the time, in a loop, the flow of code can't just disappear into no-mans land as it appears to do. – CHollman82 Jun 27 '12 at 20:53
  • Sorry for so many comments, there is a character limit... coming from my background I understand that the processor has a program counter register that contains the address of the next instruction to execute... whenever the program is running there IS a next instruction to execute. When debugging and you do a "step" you always step somewhere... on android if I step past the end of the onCreate() method it doesn't go anywhere, what is going on there? – CHollman82 Jun 27 '12 at 20:55
  • http://developer.android.com/intl/zh-CN/guide/components/activities.html#Lifecycle - OS calls a series of lifecycle callbacks, all on the main UI thread. The final callback on the way to a fully running/started Activity is `onResume()`. – Vit Khudenko Jun 27 '12 at 21:12
  • Note that on Android we are working within a framework (meaning we have no full control of what the app is doing), so there is always main UI thread running, but its owner is the OS. Sometimes OS calls callbacks that our app implements, if we don't start a background thread from callbacks (or some component that implies using a background thread), then once callback is finished there is no our code running. – Vit Khudenko Jun 27 '12 at 21:18
  • Oh I see, so when I step past the end of an event handler method and then the debugger tells me that I am nowhere it's because really it is running code that I have no access to... I'm very new to this type of environment and am used to writing code that runs "on silicon", that is, directly on the processor with no middleware in between. A follow up question then, is it possible to gain access to the processor registers in an Android app? I have no use-case in mind right now, just a curiosity. – CHollman82 Jun 28 '12 at 12:48
  • @CHollman82: I believe Java API does not allow to access such low level things as the processor registers because that would violate security considerations and the main idea of Java to be a hardware independent platform. However Google also provides ANDK (Android Native Development Kit) where you can program at a lower level: http://developer.android.com/intl/zh-CN/tools/sdk/ndk/index.html. I've never tried it though. – Vit Khudenko Jun 28 '12 at 12:59

2 Answers2

1

It is unclear what you are trying to do, however just let me say using AsyncTask in this way may have negative consequences.

AsyncTask internally uses a thread pool pattern for running the stuff from doInBackground(). On Android OS before 1.6 and starting from 3.0 the pool size is just 1, meaning no parallel computations for a bunch of AsyncTasks. More details on this here.

So, this may result that only this current AsyncTask is running, while others even if started will have to wait untill the current one is done.

Depending on your needs for things to be done periodically Android exposes:

  • AlarmManager
  • Handler - it allows to post a runnable on UI thread with a delay or periodically
  • Timer + Activity.runOnUiThread(Runnable action) inside of TimerTask

UPDATE: basing on your comments it looks like you need a Service, that starts a thread that periodically sends broadcasts with the data for UI. Then your UI (Activity) registers broadcast receivers to catch those broadcasts, extract the data and use for UI updates.

Community
  • 1
  • 1
Vit Khudenko
  • 28,288
  • 10
  • 63
  • 91
  • just added the UPDATE section – Vit Khudenko Jun 27 '12 at 21:08
  • Thanks Arhimed, I will look into the Service class and if it does the job I need I will select this as the accepted answer – CHollman82 Jun 28 '12 at 12:44
  • @CHollman82: I know that a combination of Service + broadcasts + receivers + Intents + Activities could be a bit tricky to implement from zero especially if you are new in Android. Usually it takes time to adopt Android, it is cool but challenging at the same time. – Vit Khudenko Jun 28 '12 at 13:08
  • @CHollman82: Since I've not posted a direct solution you can express your appreciation simply by upvoting the answer (wihtout accepting it as a solution). :) – Vit Khudenko Jun 28 '12 at 13:10
0

So your saying that onProgessUpdate() isn't working? That seems weird because it should. Another option that you have is just to make a Thread that loops. The trick is that if you want to update the UI thread you will have to make a call to view.post() and give it a runnable that will actually perform the update. The idea here is that you must schedule an update on the UI thread, you can't just take it and say NOW!

Frank Sposaro
  • 8,511
  • 4
  • 43
  • 64
  • It works, it just doesn't work predictably or reliably... I've seen things occur out of order, for example, or with unacceptable delays. – CHollman82 Jun 27 '12 at 20:49
  • Yeah. That's probably because of the order of how the touch events get consumed. We've made a news app that had a listview with scrolling rows for each category and it was really funky to use. We ended up scrapping that in favor for a ViewPager of ListViews instead. Much better and smoother. – Frank Sposaro Jun 27 '12 at 20:52