I have an Activity that plays some audio from within a ListActivity. The user can also click on the list item and go to a more detailed view of that data. I want the audio to keep playing during that transition from one activity to another and keep playing once the detail activity is active BUT I also need to pause the audio if my activity is being paused or stopped for any other reason.
My issue is that I currently pause the audio in onPause() in the ListActivity because I want the audio to be paused when the user navigates away from my activity. E.g. when they press Home or Back. However, I don't want the audio to pause when my detailed view activity gets started. onPause() is called in both instances, so how can I distinguish between the two cases?
Shouldn't you be doing that in a service instead? Wouldn't it be easier? Then you can stop the service when one or another activity is pausing or exiting (depending on which one you want). You could also check if it's started, and stop accordingly whenever you want.
Or sorry if I didn't understand your question. I see you have a lot of points here on SO, so perhaps I'm just confused.
--- edited since your third comment:
A Intent to B: send Intent with name of music.
B onCreate: get name of music from Intent. Set flag x to true.
B onResume: start playing music if from A or resumes from last known position if resuming from B.
B back button: override and set x to false. Actually, you'd cover all points where your activity finishes.
B onPause: stop the music if(x), store last known position of music in memory and stop service.
Here I assume that you want music to keep playing even when returning to A (that's what you said, that's the problem), not just up to B. Setting x is important early on, IMO, because if any other activity (phone call, anything) appears, activity will stop playing the music immediately (user expects that) on onPause. According to Android guidelines, you know that you're getting back to A only if user presses back button or if you finish() your activity. You can fine tuning checking the position of activities in your task (don't remember how to do that right now).
Personally, I also wouldn't want to resume playback on A (say, B->call->home->A, applying step 3 to A, too), because a disruption in the logical flow of things happens there.
CAVEAT: I would make sure that there is no other way. I would try to see if you can 1) know in advance which activity is about to be displayed. 2) get any music service to hook up to your task (is that even possible?).
Anyway, just use my solution if you can't find a clever way to do that. That would be my suggestion. Good luck.
Related
When a user enters an activity on my app I want to perform some logic during onStart and possibly launch a second activity before letting the user see the first activity (think of this as a pin protected activity)
I have a small issue where the contents of the first activity are shown for a second before the second activity is started. This happens when the user uses the home button to get out and in to the app. Is there a way to prevent the first activity to be visible at all before performing the logic validation?
This is more of a "design" solution to your problem and not clear if it'll work for you. I had something similar in the app I'm working on. What I did instead, was to create an interstitial Activity that resembled the same starting state (i.e. not yet completely loaded) of the Activity (Pin-protected Activity in your case) that is about to be started. Once I'd made my appropriate decision about whether or not I could go on, I just navigated to that initial Activity. In your case, I could see you making the decision on this interstitial Activity, and then navigating to the Pin-protected Activity or to the other one if conditions were not met properly.
The only downside to this approach is that the app does a quick flash with the additional Activity, but I think the increased separation of logic is worth it.
I'm having a hard time managing a back button in my app. If I'm not mistaken, the back button default function should return the user to their previous activity. But when I'm changing from one activity to another I call finish() in the listener. Because of the killed previous activity, pressing back button causes the app to exit.
Is there any way to preserve the previous activity and kill it only after the current activity has changed?
BTW, I know how to override the back button. But if I have a lot of activities, is it efficient to write an override for every activity that doesn't have previous acvitity already killed? I'm developing an RPG and I'm pretty sure there will be a lot of activities.
You're setting yourself up for a really bad time. You want to use as few activities as possible. In a game you really don't want to manage all of that data going back and forward between * amount of activities.
You need models to manage the game data, and your view activity can receive this data from a view controller. You don't want to kill you main view activity and you don't want to keep a bunch of activities in memory. Read a few chapters from this book. Good luck!
http://danielrparente.files.wordpress.com/2013/01/rpg_design_patterns_9_26_05.pdf
I'm making a simple e-book reader app, and an activity can be called by many cases.
I'd like to distinguish callee activity to know its origin action in case of
From my another activity: this can be easily solved by
StartActivityForResult from calling activity.
Called by back button click from other package app after share action ("whoops, I missed to click share button, and then back.").
Switched by user's multitasking choice.
Called by user click at the start screen: this might be known by MAIN entry point at the android manifest.
How to know above cases?
I have no idea why you would need to do this but...
1.From my another activity: this can be easily solved by StartActivityForResult from calling activity.
Yes, as long as the calling Activity is your own as you can't guarantee any 3rd-party code will use startActivityForResult(...). You can, however, use getCallingPackage() and getCallingActivity() in other cases.
2.Called by back button click from other package app after share action ("whoops, I missed to click share button, and then back.").
When the user presses the BACK button your Activity isn't being "called" - it's simply being resumed or re-started. The original calling app/Activity/method will still hold true - there is no way to ascertain that this has happened as the normal Activity life-cycle methods (onStart() and onResume()) are always called even when an Activity is first created.
3.Switched by user's multitasking choice.
If you mean using the "Recent" apps view, the same applies for my answer to 2. above.
4.Called by user click at the start screen: this might be known by MAIN entry point at the android manifest.
In this case onCreate() will be called although if your Activity is simply stopped for whatever reason, it may simply be restarted depending on the launch mode you use.
In short, I can't see you being able to gather much in the way of any accurate information as to how your Activity becomes active.
I am not too sure about the actual way for the above question as I am too a new guy in android.
But to the best of my knowledge... called by back button and switched by user's multitasking leads the activity to enter pause state.
So you can access it from "onPause" method in your activity.
My application has some background music playing on a loop, using a MediaPlayer. I stop the music in the onPause of the Activity so it doesn't keep on playing if the user leaves the application by pressing the Home key, or if they receive a phone call, etc.
However, I now need the music to continue playing seamlessly when the user moves to certain other activities. That is, if they press button A then I add activity A to the stack and the music should continue; however if they press button B then I add activity B to the stack and the music should stop. Similarly the music should continue if they press the phone's Back button to return from activity A to the original activity.
I've tried starting the MediaPlayer again in the onResume of Activity A, but there's quite a noticeable gap in the music during the transition.
At the moment I've got onPause triggering a half-second delay before fading the music out over another quarter of a second; this can be cancelled from within another activity's onResume. This means the music stops just about quickly enough when the user's leaving the app; however when the user switches activities I still get a slight pause in the music on some slower devices. Furthermore it feels like a really dirty hack.
Is there a better way?
[Edit: if it helps, the MediaPlayer is held in a static class that I can access from anywhere in the application.]
The simplest solution that I can think of offhand if I needed to get this done would be to set a static flag variable in my global Application object (let's call it sStartingNewActivity). Wherever I'm starting an intent new activity (or pressing "back" from an activity that isn't the entry point, overriding the onBackPressed method), I'd set that value to true, and have onPause not stop the music if that flag is set. I'd set the value back to false in every activity's onCreate. I don't think a 1-2-second-pause-before-fadeout is a bad way to go, though -- that would actually behave pretty similarly to how it works when the user presses the "home" button in an iOS app that has background music.
EDIT: You can also try a service-based solution that "sniffs" for whether your activities are running by having your activities listen for a specific broadcast; there's some sample code online that I haven't tried but it's an interesting approach).
I've been trying to figure out how to stop all threads when my application is paused (when the 'Home' button is pressed) and I just can't figure it out.
Here's what I have: one main activity containing a tab host, every tab host has a list, when one item in the lists is clicked a new activity with details is started. Each list is within its own activity which starts an updater thread that makes sure the list content is always up to date.
Here's what I've tried: I've tried using the onPause(), onResume(), onStop() and onDestroy() events. The problem is that if I use either the main activity of the activity that holds a list to monitor for those events, they get called every single time an item from the list is clicked, as well as when the 'Home' button is actually pressed, so there's no way to distinguish between the situations.
Am I missing something? How is this usually done?
This is a pretty good indication that your design is flawed. You shouldn't ever have threads laying around that you can't account for or that don't finish themselves.
Each list is within its own activity
which starts an updater thread that
makes sure the list content is always
up to date
This kind of thing should be done in a service.
they get called every single time an
item from the list is clicked
This is how those events work. As soon as your activity is no longer visible (ie your new activity comes in front), it goes to onPause() and possibly onStop(). You have to account for this. You can't fight it, or work around it.