Communication between Service & Activity - Android Software Development

Hello
I want to create an Android App. In the last days i read a lot of Android API Documentations, Tutorials and "how do do's". Now I'm really confused, because on one hand, it's nice to have so many possibility, but on the other it confuses me, whats the best way to do it. So I played a little with Activity life-cycle.
Now I'm going to start to build my first 'real' App.
This App should download initial data from a Webservice, process these data with a database, download more data related to results from a database, save these data again to database, and make it accessible in the Acitvity.
So please correct me if I'm wrong from this point on:
I assumend that a Android Service is the best way, to process these Data in a background-worker-thread.
So far so good. So I read about the Android Handler which seems to be a pipeline, so Threads can work on the Handler message queue. I can Access the Service from within my MainActivity over the ServiceConnection.onServiceConnetcted where I recieve a simple Binder which gives me access to my Service. From there i can put Messages in the Message queue from the HandlerThread. But how I can tell my Acitivity from within the Service, that it has finished Processing and send the Data to it?
I read that I don't have to use AIDL since the Service is running in the same Process. But How can I do it then? I tried to call onBind() in the Service, hoping OnServiceConnected will be triggered in the Acitvity which initially Binds these Services, but it doesn't seem to work. I also tried to "hack" the Funktionality, by spending my Service a singleton member "MyMainActivity" with corresponing static setMainActivity(MyMainActivity activity), calling it in the ServiceConnector onServiceConnected, with the same result: Runtime Error
I even don't think I understand the functionality behind these HandlerThread.
will it loop infinitly waiting for HandlerMessages while draining the Battery, or is it on a wait() status since it recieves a message?
I read the Android API about Services but for me, it seems that they only describe to Access the Service from the Activity, and not the other way round.
If I call a method of my Service within my Activity over the ServiceBinder, which has a return value, but was started in another Thread in my Service, how will my Activity know that it processes finish? 'busy waiting' on a boolean member of my Service doesn't seem to be the way to go. If I do that, like I saw in a tutorial, I don't see a reason not to do the work in the Activity Thread itself.
I read also about an AsyncTask, but this doesn't seem to be practicable for me, because I have to do different work related to JSON Objects I get.
Please you expirienced Android guys: show me the way.

You probably don't need a full-fledged service if you just need a background thread. Services can run independent of an activity and reconnect, etc. If you don't intend for the thread to be stand-alone, then just use a class that implements Runnable. Since you seem to have a handle (no pun intended) on handlers, this won't be too hard. Just post a message to your handler from your thread to let the activity know what's going on.

Related

I am writing a program on my htc and have a problem with multithreading and timers

Hi I didn't know where I could get help on this topic but seeing as some of the guys in here have made such excellent programs I thought you might be familar with c# on windows mobile.
here is my problem.
I have a task I need to do every x seconds I want to be able to start and stop this repeating task immediately.
I have attempted to solve this by creating a class which holds the taks I want to do, in this class I have put a windows.forms.timer with the task as its timer.tick event. this task has a method called start() which sets the timer going.
to start the process in my main thread i create a new thread which creates an instance of my class(mentioned above) and calls its start method.
The problem is the tick event never seems to fire is this because its in a seperate thread to the one which has focus, is it because it doesnt have an asociated form?
is there a better way to do this?
I want an object I can create which I can call methods to start and stop a repeating task.
many thanks,
I hope some one can help.
(sorry if this is completely the wrong place to post this)
Have you set the timer.Enabled = true?
Instead of windows.forms.timer try system.threading.timer!
comparison of timer classes in .net
Why have you put this in a thread, so you can abort it midway through processing its tick event?
Is there a better way you could do this than adding the complexity of threads? Perhaps add a bool to you class and your tick event can check at safe points if it is false (and exit)?
My initial thought to the problem as you have outlined it is that your thread is finished after completing its Start() method, so the tick event never gets called (as the timer no longer exists). You would need to keep the thread alive (without interfereing with your timer).
Windows.Forms.Timer is a bad choice for this as it uses the calling thread - so if you add a System.Threading.Thread.Sleep() (or some other blocking action) to keep your thread alive, your timer wont work. System.Threading.Timer is a better choice as it uses its own thread.
Hi thanks so much for the info I will have a look at threading timers.
I have put it in its own thread so I can abort it early because each "tick" could be between 5-15 mins and the task takes between 1 second and 5 mins so I wanted to be able to make sure the task is started at regular intervals and have the ability to stop the process immediately.
I was just thinking that neither timers or using a bool will allow me to stop the process immediately, is it safe to use thread.abort? i.e. if part of the task is to update a field could it be stopped half way through and corrupt the data?
if it is unsafe is there a safe thread abort i.e. abort as soon as the thread has finished updating any fields or database records(this thread wont update database but its good to know)
also to the point you raised about the thread finishing when my start() method finishes I kept that going using a while loop and a bool i.e.
while(keepGoing)
{
}
this seemed like a really horrid thing to do but do I have any other choice?
I think my design is not good my app basically wants to start off this running process when it loads but needs to be able to interupt it when some data changes.
(as an extra question does any one know if sqlce 3.5 has built in thread safety or will I have to lock functions that access data in my database?)
Threads can be somewhat unpredictable. Thread.abort calls an exception, so as far as i know if you have something like
var1 = "blah";
that would finish - var1 would not be corrupt. But, if you were doing something more complicated such as your database example you cant be sure when it will cut you off. Of course, you can catch the ThreadAbortException, and do some checking if required.
As for your while loop, that almost certainly blocked the thread and is why your timer did not work. Windows forms timers are based around events and will not typically run while one of your methods is still working, unless it yields somehow. Infact, on a single cpu device like your phone that loop would probably block a System.Threading.Timer because while(true); results in 100% cpu usage.
This is a quick example of how I would impliment your timer requirement - mostly stolen from the msdn page on System.Threading.Timer.
Code:
private void ThreadMethod()
{
System.Threading.ManualResetEvent resetEvent = new System.Threading.ManualResetEvent(false);
int interval = 10 * 1000;
System.Threading.Timer timer = new System.Threading.Timer(new System.Threading.TimerCallback(timer_Tick), resetEvent, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
while (true)
{
resetEvent.Reset();
timer.Change(interval, System.Threading.Timeout.Infinite);
resetEvent.WaitOne();
DoStuffThatTakesOneToFiveMinutes();
}
timer.Dispose();
}
private void timer_Tick(object timerObject)
{
System.Threading.ManualResetEvent resetEvent = (System.Threading.ManualResetEvent)timerObject;
resetEvent.Set();
}
private void DoStuffThatTakesOneToFiveMinutes()
{
MessageBox.Show("hi");
}
ThreadMethod can just be directly called from your thread.
timer.Change starts the timer off. The Infinite means it is not a repeating timer.
resetEvent.WaitOne() simply waits for the event to be triggered. The nice thing about doing it that way is your processing is done by the calling method, and you can be sure at what point in your process. (Well, as much as you can with it all running inside a larger thread.)
Edit:
Infact, that timer.Dispose() is pointless as it will never get called. Probably a good idea to call it if you catch the threadabortexception though.
Also, I think var1 (first example) would simply not change, but im not sure. I dont think it would get corruped either way.
Thanks so much for this information it looks excellent. So if I want to tidy up some stuff on exit I see on msdn it says the finally block will exitcuted before exit or I could catch the abortexception as you suggest, where would I put this code would it be inside the threadMethod? or does it go somewhere else?
also imagine this example I am updating a record in my database, I throw the abort exception and it stops the process midway, is there a way in code to say ignor this exception and continue? i.e. when updating database i could set a bool and then check this bool in the finally or catch block and if its true say ignor this and continue and then outside my thread I could do a check on the thread to see if its still running if it is then i wait for x amount of time and try the abort again?
what would be a good way to notify the calling thread that the thread with the timer is still running as the isAlive property is not included as part of the compact framework, I suppose I could have a bool in the calling thread which the timer thread could change in the finally catch block when the abort exception is passed, but this would mean passing the calling thread to the called thread is there any problems doing this?
sorry this is quite a complicated situation I have made for myself, I really appreciate the help.
Im afraid we have hit the limit of my knowledge on threads and exceptions.
My thought was you could wrap the database parts in a try-catch, at least allowing you to handle the abort gracefully. As far as I know you can not continue the thread at the point it stopped - you can merely ignore it and carry on after the catch. Of course, exceptions are not meant to be used on a trial basis, they are more worst case.
Events may suit you a bit better, as they do not halt the flow. That way your thread could keep track anytime it is doing something important like database access - and the event would only close if safe.
You should be able to have your thread access a bool in the parent object, aslong as you are careful with synchronization. Making sure all parts that read/write to it use lock should be sufficient.
http://www.blackwasp.co.uk/CSharpEvents.aspx
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
Thanks again isangelous,
I have thought that events would be a good idea but found them a little confusing, I will have another look and see if I can use them somehow.(thanks for the link)
btw I used the code you provided and tweaked it a bit to get my first problem working, i put the contence of the threadmethod inside a try block catch the abort exception and then call timer.dispose(), seems to work quite nicely so far, although I dont think i have managed to abort half way through a process, it always seems to be before or after but seeing as I dont use any of the variables after its stopped I assume all would be safe anyway.
to make the updating database part safer I was thinking that I would also put that in another thread and if its running when I send the abort exception I would wait until it is free and then stop the timer, what do you think? does sending an exception to a thread halt all its created threads as well? because if so my plan wont work.
btw im alomst 100% confident that actually calling abort using my app while it is updating is impossible but I dont want there to be a bug present I know about.
anyway thanks again you have given me loads of things to try.

[Q] Android Service

An Activity that started a service finished. That means the process the Activity run in has finished. So all of threads the process created would stop. But why the thread serving the Service that the Activity started through startService() method is alive?
I'm not sure what you're asking. A service will continue to run until it ends itself, even if the activity that launched it ends.
Gene Poole said:
I'm not sure what you're asking. A service will continue to run until it ends itself, even if the activity that launched it ends.
Click to expand...
Click to collapse
I'am sorry, if I'am extremely obvious. SDK says a service is not a process and is not a thread, but it runs in the same process as the application it is part of. What is it? Why can it keep running after the process finished? I'am a little confused.
"Process" with respect to the JVM is just an execution context within the virtual machine. In the typical case as I understand it, an app, activity, service, etc. can exist in the process space and can interact with each other, but not necessarily depend on each other.
jiyeyuran said:
An Activity that started a service finished. That means the process the Activity run in has finished.
Click to expand...
Click to collapse
No. You are confused and you think "Activity" = "Application".
jiyeyuran said:
I'am sorry, if I'am extremely obvious. SDK says a service is not a process and is not a thread, but it runs in the same process as the application it is part of. What is it? Why can it keep running after the process finished? I'am a little confused.
Click to expand...
Click to collapse
It cannot continue after the process finished.
This simply means: the process has not finished! :facepalm:
Read here.
Application = Activities + Services + Receivers + Providers.
When the first one is called, the Application process is created.
When the last one has finished, the Application process is no longer.
So if you start an Activity, a process is created.
Then you call a Service from the Activity, it gets added to the same process (unless you specify a different process, check the docs link I gave you).
When your Activity finishes and the Service is still alive, the process will live on.
Thank you very much. Your explain is very clear. Without specially indicating, a service from the Activity and the Activity will run in the same thread. But if startService and bindService work at the same service, you need to very take careful of using them. For example, if you start a service with startService call and bind the service twice, then you unbind the service, an exception will be waiting for you.
I have spent my weekend in finding out the service mechanism. Hope you can understand my poor English.
jiyeyuran said:
Thank you very much. Your explain is very clear. Without specially indicating, a service from the Activity and the Activity will run in the same thread. But if startService and bindService work at the same service, you need to very take careful of using them. For example, if you start a service with startService call and bind the service twice, then you unbind the service, an exception will be waiting for you.
I have spent my weekend in finding out the service mechanism. Hope you can understand my poor English.
Click to expand...
Click to collapse
I don't understand if you are asking a question or not.
Read the link I gave you, it has a brief and simple description to understand when you need to use an Activity or a Service (or a Broadcast Receiver or Content Provider, yeah).
What are you trying to accomplish, anyway?
Our teacher ask us to develop a SmartHome Manage software on the android platform. The application can turn on and turn off some appliances in home like frigo, tv, window, etc. It can also receive the telephone messages, so we may need to download voice files from the service runing at a computer. Obviously, android service is a good choice to spawn a thread for downloading voice files. As cutomers can take other service operations during the period of downloading voice file, the service may be binded many times before it is unbinded. I wonder if it will cause problems when a service is binded repeatedly before unbinded? Which aspects we need to take care of when we use android service?
Android SDK says when binding a servcie, onCreate() (if service don't start) and onBind() will execute. When you bind again, the onRebind() will excute if the return value of onUnbind() is true. But the problem is that when I bind secondly, the first unbind haven't returned yet. As a result, the onRebind() method cann't be executed. Does it cause problems?

How to interrupt ACTION_CALL

I'm a new android developer working on an extremely simple app and I just need a quick pointer! My app, once started, needs to call a certain phone number. This part was simple and works fine. However, I need that call to end after a specific amount of time (10 seconds is the number I'd like).
At this point I'm unsure how to proceed. I've tried spawning a thread that simply waits for 10 seconds, and then tries to call finishActivity() on the activity that I originally started. However, I'm assuming that one thread can't control another threads activities, so this clearly doesn't work. I've also tried a few other methods and none of them seem to work, or they simply crash my app.
If someone can even give me just a high level overview of what I need to do that would be great! My next thought is to spawn a timer thread and use RPC to call a function that will activate finishActivity() in the thread that is running the activity.
Any information you guys can provide me with will be fantastic!
The API won't let you, however, you could try to switch ON airplane mode and the switch it OFF, the inconvenience of this is that all your active connections will be droped (3G, GRPS, Bluetooth, WiFi)
Are you sure its not possible? Using various callbacks I've sent finishActivity() to the action with success. The problem is that there are no callbacks that occur around the time that I want the call to end.
Since it does work with callbacks, I was tempted to have finishActivity() be called when the app is backgrounded. That way after 10 seconds I can just hit the home key and it will close the app down entirely? Not exactly what I want, but could work for now.
Due to the fact that it can be finished during a call back I think it must be possible, I'm just not sure how to go about achieving it. Does anyone have any ideas?
Try the following code:
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Class clazz = Class.forName(tm.getClass().getName());
Method m = clazz.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony it = (ITelephony) m.invoke(tm);
it.endCall();
But you need to get ITelephony.aidl from Android sources and compile it.

[Q] Debugging help needed

I have a user of my app who is having a problem running it. My code launches another activity in the same app, and he is saying it is stopping before it should & returning to the previous activity, and he doesn't see any Force Close warnings.
I have run my code in the emulator & on my phone, I can't reproduce the error. We both run Android 2.2 on our phones, his is an HTC EVO & mine is a HTC Wildfire, as far as I can tell his specs are better than mine so shouldn't cause an issue - I deliberately chose a low spec for for my dev work so the code ought to run on anything.
As a bit of an Andoid dev noob (but been coding for years), is there any easy way I can make a special build of the app to send to him that would log any errors that happen ? I'd like to get a stack dump as well if possible, as I'm not sure exactly what routine in the activity its crashing out in. The activity that crashes is Gallery with 9 images in it, he can't flick through them or select one. I'm stumped as to whats causing it, any assistance would be gratefully received.
Thanks.
Why not point to your app and let others here try it on their phones? It could simply be other apps installed on his phone interfering with your app.
Long time programmer here too and when I get to where you're at (and I"m sure you've put some hours into this LOL), I go back to STEP 1.
I comment-out any and all code but the bare minimum; break it down to the Intent, startActivity and maybe a Toast message in the second activity. Even parse down your XML files to bare minimum.
See if that works. Then, ADD BACK ONE LINE OF CODE AT A TIME Run program and make sure it works. Yeah, it's painful, but in my 20 years of coding, I've learned to put my pride aside and to not "pretend" all the code I've written is correct.
Sometimes on bigger projects, I"ll change or add a couple of lines of code, run a back up and test. Rinse and repeat LOL. That way, I know I"m only a couple of lines of code from what "used" to work.
Good Luck!
Thanks both of you.
old_dude - Its a paid app. Only £0.99 but I don't think people would pay to help me. There is a free version of the same app (with less functionality) that this guy can get to work. If your really interested the 2 versions are -
Plink Log - Free Version
Plink Log Pro - Paid version
Rootstonian - agreed thats the approach I'd normally take if I was having problems on my dev phone or the emulator. The problem is that its OK on my HTC Wildfire/Android2.2 but on this guys HTC EVO/Android2.2 its having problems. I dont really want to keep sending him .apks with 1 or 2 lines extra enabled just to see if that fixes his specific issue. I was hoping there was something I could code to catch whatever crashes the activity & log it somewhere for me to analyse. When I do PC dev work, I have a global exception handler that catches anything I dont explicitly handle, and dumps the full call stack into a Log File I can read later.
I think I'll just have to take the existing app & put loads of debug code into it to save messages into a log file & see what bits of code are being called & what isn't & then get him to email me the results.
Thanks for the ideas guys, its always useful to get input from another perspective.
Dave
Hmmmm, just discovered setDefaultUncaughtExceptionHandler - might be able to use that with printStackTrace. Sounds interesting.

send intent only if activity is already running

Hello,
I have a service that is running at all times. When it receives a certain intent I want it to pass this along to an activity that I have so that the activity can be updated. However, I don't want to resume the activity if it is stopped/paused. If the activity is stopped, I want it to stay that way and then I'll just check my content provider when the user chooses to return to that activity. Sending this intent seems to automatically end up calling onStart and onResume and bring the activity back into focus. So I'm wondering if there is a way to only send the intent if the activity is already running. Also, if this is not possible, are there any other suggestions you guys have?
I figured there would some flag I could add to the intent to make it do what I want but I haven't found anything useful.
There's even a question about this in the developer.android.com faq but the answer is not very helpful.
How can I check if an Activity is already running before starting it?
The general mechanism to start a new activity if its not running— or to bring the activity stack to the front if is already running in the background— is the to use the NEW_TASK_LAUNCH flag in the startActivity() call.
Click to expand...
Click to collapse
Than you so much,
Samuel Maskell
Edit: Removed explanation as to why the post is somewhat vague. See below.
You drew so much more attention to your potentially "secret" project by saying all that. If you had just given your question with a little context and not mentioned all that people would understand it and answer without thinking anything of it
well I wrote the post and felt that it was a little vague so I added a sentence to explain why. I'm not trying to draw attention to it. I don't feel like the post is hard to follow at all but perhaps I will remove the stuff about the project and keep it solely about the problem.
And please don't take this the wrong. I feel like what I just said sounds really bitter but I'm just trying to explain myself.

Categories

Resources