keeping a service and an activity in-sync - Android Software Development

I'm working on a music player and I'm running my MediaPlayer object within a service so that I can run other stuff while the music is playing. For the most part this works. If I leave the activity for any reason (like hitting the "home" key), then go back, I BindService in OnCreate and this usually links me to the already running service and I can pick up where I left off. However, sometimes BindService launches a new service and the original becomes orphaned. Then I've got two songs playing on top of each other and I have to kill the whole process with a task killer to stop the orphaned service. I can't seem to figure out what set of conditions causes this so it's difficult to debug.
Any ideas?

After tons of searching, I found some informative posts over at stackoverflow.com. Seems that if you bind to a service using the default ContextWrapper, you can get a different context with a different instance of an activity. If you use the application context (from GetApplicationContext) for binding, it should always bind to the same service.

Thank you for posting the solution.

Related

[Q] Android app auto starts again when device rotated

Hello all,
I've written a simple audio player app and testing it in Samsung Galaxy S.
It is a simple app with can create playlist and some buttons to play the mp3 file.
However, there's a funny bug in it.
After starting the app, whenever I rotate the phone, the running app will launch another instance of the app. If I rotate again, another instance (3rd) would be started. So u can hear 3 copies of the same audio being played simultaneously.
What could be wrong with it?
Is there some code which can prevent program re-entry?
Thanks.
It's not a bug, that's the way andorid OS works. You need to account for this in OnCreate for your activity. I assume you are spawning off the actual playing of the MP3 in a thread or service. You need to check if the service is already running in OnCreate and attach, else spawn a new one.
Hello Gene,
How do I check if an activity is already running?
I could not find the answer on the android developer page (the topic on application fundamentals).
And no, I'm not converting it to a service yet as this is my first app.
Haven't explore service yet.
Thanks.
I read on another article, a simple way to prevent this is to add overwrite the onConfigurationChanged function
@Override
public void onConfigurationChanged(Configuration newConfig) {
//ignore orientation change
super.onConfigurationChanged(newConfig);
}
and modify the androidmanifest.xml
<activity android:name="selectCategories" android:configChanges="orientation|keyboardHidden"></activity>
But it still launch multiple instance of the app.
Thanks.
This is a good question and should be in an FAQ somewhere.
As already mentioned, changing the display orientation basically restarts your app. Read the Android dev page on Activity lifecycle for more info.
A short answer for your question is: the Bundle parameter for onCreate() will be null when your app is first run. When your app is paused and restarted, that Bundle will be non-null. You can store data in that Bundle by overriding onSaveInstanceState(), then check for that data in onCreate(). It's a good idea to learn how to do this (save/read app data on pause/restart). Once you start testing apps by rotating the display at various times, you'll find a lot of them FC at unexpected places.
This is indeed a topic that keeps surprising people who are new to android (ahem, like me 4-5 months ago ).
The solutions above are perfect, however in certain situations there's another trick that might make your life much easier. I suspect it won't help you in this case, but it might help others who tackle the problem and see this thread.
Certain applications, mainly games, should be fixed in a single orientation. I.E. you won't be playing angry birds on portrait - that game is locked to landscape, as it should be. In order to lock your activity in a certain orientation you add this attribute to the manifest under the Activity tag. So a standard activity might look something like that, combined with the ignore tag from the previous posts:
Code:
<activity android:screenOrientation="landscape" android:configChanges="orientation|keyboardHidden"
android:name="whatever">
The great thing about this combination is that your activity will not restart at all when the phone is rotated. Of course, for a standard activity you'd usually want to support both landscape and portrait, but if you need your app to be in a fixed orientation this is the way to go - no weird FCs or annoying bugs
Hi,
How do I check the bundle?
And also, what to do if the bundle is not null? Just return?
Thanks.
regards
r_p_ang said:
This is a good question and should be in an FAQ somewhere.
As already mentioned, changing the display orientation basically restarts your app. Read the Android dev page on Activity lifecycle for more info.
A short answer for your question is: the Bundle parameter for onCreate() will be null when your app is first run. When your app is paused and restarted, that Bundle will be non-null. You can store data in that Bundle by overriding onSaveInstanceState(), then check for that data in onCreate(). It's a good idea to learn how to do this (save/read app data on pause/restart). Once you start testing apps by rotating the display at various times, you'll find a lot of them FC at unexpected places.
Click to expand...
Click to collapse

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.

Communication between Service & Activity

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.

Thoughts on Multi-tasking and "Exit" in Android. Developers please read and respond.

Thoughts on Multi-tasking and "Exit" in Android. Developers please read and respond.
Having done extensive reading on the topic, I understand why developers don't see the need for an "Exit" option for most Android programs. For behind the scenes management, it isn't required. The problem is that our needs as end-users are different than that and should take precedence.
The classic example of needing an "Exit" option is the web browser. If you have been browsing a while, you may need to back through several pages to get the thing to close, which is a pain in the neck. Another example may be a music player. I might not want it to pick up where I left off when I start it next time.
End-users want to be able to choose from options like these when leaving an application.
1) Pause - exactly what it sounds like. This is pretty much what happens most of the time when leaving an application, but it should set a priority flag of some sort so it is one of the last things to get "ruthlessly killed" to recover memory.
2) Exit - stop everything and reset to a default state so that the next time it is started it is a fresh run.
3) Background run - this is true multitasking by user choice. The app continues doing whatever task I set it to while I go do something else. Much like what happens with music players or Navigation programs when the Back key is used.
4) Home or Back key - it would be handled in the current default manner, letting Android decide what is correct.
I've mentioned it elsewhere, but I believe a proper multi-screen launcher should allow you to start different apps on different screens and go back to the app started on a particular screen automatically when you return to that screen. So for example I could be doing e-mails on screen one and have my music player open on screen 2 and perhaps be reviewing a spreadsheet on screen 3 and go back and forth between them as my music mood changed or I looked something up in the spreadsheet or on the web on screen 4 then went back to my e-mail to include that new information without closing one and opening the other and so on going back and forth. Android could decide if the app is paused or actually running while I go to a different screen, but anything open on a screen should be the last thing to be killed before essential services.
Anyway, those are my thoughts on what an OS needs to be able to do before it can call itself multi-tasking, as well as the kind of control us users want on our phones. After all, they are OUR phones, right?

Writing Global Overlay Help

So the end goal in this project is to view an RTMP stream and interact with the server at the same time.
This is a little hard, because obviously VLC or Mx Player or whatever I'm viewing the RTMP stream with doesn't know how to communicate with the custom server. So I'm trying to make an overlay that will sit on top of the player which has buttons, the buttons can then communicate with the server which will alter the stream and you'll see the result streamed to the player. This is sort of like an interactive HUD if you will.
Problem is that it's difficult to make an overlay which will take actions if they're clicked, but can also pass those actions to the background app (in this case the player) if it opts not to process them. Right now my app creates a service and the service catches the input and displays whatever. This WORKS, but the problem is no matter what I return from "onTouchEvent(MotionEvent)" in the view of the service (true or false) the home screen is frozen. It catches the press but it won't pass it on, even if the function returns "false" - to say it's not handled.
I'm not sure if I'm not passing the touch event on correctly, or is this not even possible? I read somewhere that it's not possible for app A to provide input to app B, but I'm not sure if that is correct (frankly I don't believe it). Basically I want to handle some presses in the overlay and allow some others to go to the active app beneath it.
Does anybody have any input for making this work as expected? I'm creating a view to pass to the window manager with the following flags:
Code:
LayoutParams params = new LayoutParams(LayoutParams.TYPE_SYSTEM_ALERT,
LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
I've tried playing with the flags but to no avail, I cannot get the touches to go through, even if all the onTouchEvent(MotionEvent) function does is return false.
Anybody have any ideas?
I'd be open to alternative implementation ideas too, the point is I need to basically have two communication channels open, one is a player (ie. VLC) for viewing the RTMP stream, which likely would not change, the other would be the command stream, which will control said server, which I am open to change. I considered trying to use the accelerometer in the service instead of an overlay, but I think that would create a bad proof of concept UI (because there's some latency in the video stream), any alternative ways to communicate with the server would be up for discussion! Maybe I can plug an IO device into the USB port or something, like a keyboard? Extra buttons could be of use. It's only a POC, so some clunkyness IS okay.
EDIT:
As you can see above, I used an alert type instead of an overlay type, I guess this is because overlays won't accept focus after a certain Android version number. I'm using 4.0.4 ICS.

Categories

Resources