Android Receive Broadcast on Audio Focus change - android

I am trying to write an app that detects whenever any app on the device starts or stops playing music. My app is not a media player, it's more of a dashboard functionality, so I have no need of requesting audio focus, but I want to know when other apps do so I can update my status text accordingly.
Essentially, I believe that the function AudioManager.isMusicActive() will provide essentially exactly what I want to know, however since I am writing a service that will be always on I would like to avoid needing to poll that on a constant basis. I need the information in near real time, so it would essentially be a 1 second poll in perpetuity.
I'm looking for a way to detect when STREAM_MUSIC is being used by another app.
Some ways I have thought about doing it:
(1) Again, a perpetual poll using either Timer or Handler to constantly poll the isMusicActive() function. Not ideal from a battery or processor management perspective. I could use a flag variable in the UI Activity to control when the poll runs (it isn't really necessary when the UI isn't in the foreground, anyways), but I still think I'm using more processor/battery time than I'd need to.
(2) Listen for a broadcast of some kind, but none of the Android audio broadcasts seem to really fit the bill. (that I could find)
(3) I could, I suppose, request audio focus and just never play any audio and never give it up. Theoretically, since I am starting this in an always on service I believe that should allow my app to sit at the bottom of the LIFO audio focus stack and I would be notified via the AudioManager.OnAudioFocusChangeListener mechanism in basically the opposite way of its intended purpose (i.e. turn on my app when I lose audio focus and turn it off when I gain audio focus back). However, I'm not entirely sure how doing something like this would function in real-life usage. I feel like abusing the audio focus methodology for something like this could very easily result in negative user experiences in situations I haven't even thought of.
(4) Is there a way to use the AudioManager.OnAudioFocusChangeListener (or similar) without needing to request audio focus at all?
Are there any other ways I could go about doing this? Just a pointer in the right direction would be incredibly helpful!

I needed similar thing, so did a bit of research.
Unfortunately, there seems to be no other way to accomplish this except of requesting audio focus in your app.
Material for study:
Check Android source code in frameworks\base\media\java\android\media\ where you can find actual code for requestAudioFocus in MediaFocusControl class.
Other classes in this folder show how they send broadcast events for volume change, bluetooth on/off, etc, but no broadcast event at all related to audio enabled/disabled.
Another information on topic:
http://developer.android.com/training/managing-audio/audio-focus.html
http://developer.android.com/training/managing-audio/audio-output.html
Other than that, there doesn't seem to be any documented way to know when audio hardware starts/stops to play.
I trust that requesting audio focus without actually playing audio should not consume any battery. Only one ugly side effect is that this stops currently played audio.

Related

Android - blocking hardware buttons while locked

I'm looking into making an app that prevents the default action on volume up / down key presses, and would like to get some input to see if I'd be wasting my time trying.
Here's the setup:
I have a Samsung Galaxy S3. I like to listen to music. Often i unintentionally change the volume of whats playing when the phone is locked and in my pocket.
At first i thought it would be simple; having tested a simple override of the onKeyDown() method for retrieving the integer values for the volume keys. Quickly i came to the realization that this would only work if i were to not lock my phone and keep ONLY that app open.
Next i found a few articles on Services, however i believe this also falls short for my needs as it's not a subset of Activity and so doesn't implement onKeyDown(); and unless I'm mistaken, a wake lock actually wakes and/or unlocks the phone?
Should I give up now, or is this actually achievable?
(actually it must be possible as the whole point of this is that i don't have to pay £3 for an app for this one feature. lol)
Note: Running 4.2.1
New to Android, but not to Java.
Steve.
Edit: Just a thought, but if i extended Activity to my own class (and override onKeyDown), and instantiated it in a Service as a static instance, would that custom activity persist while the phone is locked?
Edit2: I found this SO post which suggests using FLAG_SHOW_WHEN_LOCKED. I'll start looking at this when I get home, but I'm still open to suggestions and advice :D
Edit 3:
OK so tell me if i start losing the plot here...
Using a broadcast receiver i will listen for the ACTION_SCREEN_OFF flag. If that gets called, create my custom Activity (with the onKeyDown() Override) and set it to FLAG_SHOW_WHEN_LOCKED to take over my lock screen (i don't care because the screen is off). The receiver then listens for the ACTION_SCREEN_OFF, if called it will then destroy the Activity before showing the screen (or after, I'm not bothered if it flickers).
(possibly even just pause it, and only kill it if it detects an unlock).
Also a big thanks to #StoneBird for getting me this far, sometimes it helps to just hash it out with someone who knows what there talking about (hopefully ^_-).
Try this?
Settings.System
You can start a service and set system volume like every 1 ms to keep it at a steady level. No key checking should be needed since the value is overwritten every 1 ms.
Also, there are free volume keepers on the market so you don't have to pay for that.

Android's AudioManager.getMode() seems unreliable. Same situation produces different results

I am currently working on an audio player that is supposed to pause/stop when losing audio focus, for example when a call comes in.
While I got this working fine by using an OnAudioFocusChangeListener I want to enhance this function to behave differently under different circumstances.
As the application implements a timeout function in case the user has fallen asleep while listening I only want to resume playback when I can be positive that the user is still awake.
I figured I could pretty much ignore notification sounds like those of an incoming email, as these usually are only short clips and my audio continuing to play will not be a nuisance to the user, as it would be during a phone call.
Thus I want to limit pausing/stopping to situation where either a phone call comes in or the user makes a call.
I have seen that AudioManager has some convenient states to signal this, but upon calling AudioManager.getMode() in my OnAudioFocusChangeListener I do not get consistent output.
Sometimes an incoming call does generate MODE_RINGTONE, but often enough to render the function unreliable I get MODE_NORMAL.
I could actually live with not knowing the mode when losing focus as long as I get the correct mode when re-gaining focus, but also this doesn't seem to work reliably.
The only actual device I could test this behavior on is the Galaxy S2, running Android 2.3.6 (the application is API level 10 due to me using MediaMetadataRetriever, thus requires at least 2.3.3).
I have tested the loss and re-gaining of audio focus in various emulated systems, and overall it seems to be working better there, but I also don't really get the same results each time.
Maybe the problem is that I misunderstand what AudioManager.getMode() should return, maybe somebody could clarify this for me:
phone rings -> AudioManager.getMode() should return MODE_RINGTONE on focus loss
user makes or picks up a call -> AudioManager.getMode() should return MODE_IN_CALL on focus loss
doesn't pick up the call -> AudioManager.getMode() should return MODE_RINGTONE on focus gain
user hangs up -> AudioManager.getMode() should return MODE_IN_CALL on focus gain
Is that the way it is supposed to work? At least my tests suggest that this is the way it is supposed to be, but for some reason isn't all the time.
Another way I am trying to solve this problem is by using a PhoneStateListener, but the problem I have with this is that this requires my application to request the permission to read the phone state. As I am sharing my application, currently through SourceForge, later possibly through the Android Market, I would like to avoid using this kind of permissions.
So, coming to an end I would like to ask if the way I understand AudioManager.getMode() is correct and if there is any information on its reliability, as for me the results I get from it are kinda useless.

Persist objects after activity/app is exited

I need to be able to gain access to objects after my activity has been destroyed (or even after the app has been quit).
The object is an AAC decoder and plays in the background if the user hits home, or stays in the app. However, when the activity/app is exited the object is lost. This means that if the aac stream is playing there is no way to stop it (short of restarting the device) and subsequent visits to the app just layers the streams on top of the last one.
I thought about adding the object to a service, however I have no idea how this would work, or if its even a good idea. I also thought that the answer might lay in static variables, however I assume that once an application has been exited (or force quit/killed for memory/whatever) even these objects are lost.
The library I'm using for the aac decoder is http://code.google.com/p/aacdecoder-android (if that helps).
Currently I'm playing the stream in a service completely. This gets around the problem above, however I need to be able to update the UI when the app is running (and when the user goes to the app in the future). So this is a problem. I realise the way around this would be to use a broadcast intent, but I wonder if its more complicated than necessary.
Is there any way around this?
Thank you.
I thought about adding the object to a service, however I have no idea how this would work, or if its even a good idea.
Not only is it a good idea, but it is your only real option. Here is a sample project showing a (fake) audio client sending commands to a (fake) audio service that handles the playback and indicates to Android that the service is part of the user's foreground experience.
I also thought that the answer might lay in static variables, however I assume that once an application has been exited (or force quit/killed for memory/whatever) even these objects are lost.
Once your process is terminated, the object is gone. Of course, so is the audio playback.
A service is effectively a marker, to the OS, indicating that you have code that is still running, so Android is less likely to terminate your process to free up RAM to run other apps. Marking it as part of the foreground user experience further reduces, but does not eliminate, the odds that Android will terminate your process.
I realise the way around this would be to use a broadcast intent, but I wonder if its more complicated than necessary.
It doesn't get much simpler than a broadcast. It's not your only option -- you could use a Messenger or a PendingIntent or a handful of other techniques.
Is there any way around this?
Why would you want to get "around" the right answer?

Audio Signal when Voice Search Dialog is Ready to Accept Input?

The Google Voice Search comes with a significant delay from the moment you call it via startActivityForResult() until its dialog box is displayed, ready to take your speech.
This requires the user to always look at the screen, waiting for the dialog box to be displayed, before speaking.
It would be nice to add a 'ding' sound or some other non-visual cue to when Voice Search is ready to accept speech input.
Is this possible at all?
If so, how do go about doing that?
Ok this will complicate your program, however, if you really want that signal consider implementing the speech recognition by an object instead of calling the intent or making your own activity.
(warning: much of this is speculation including the order of calls)
Perhaps the delay is in instantiating resources before actually listening. If my theory is correct than you could setRecognitionListener(RecognitionListener listener) (the latency passes), create a recognizerIntent object (maybe some more latency passes), finally in (an overridden) startListening(Intent recognizerIntent), call a "PING!" before calling the super method.
It is up to you whether you would like to wrap all this functionality in a new activity, which is probably recommended, or to tack on the latency to the UI.

android apps that alter normal phone operations

so i was wondering if its possible to for an application that i would write to be constantly running in the background and alter regular phone operations. For example this could be something like as soon as you receive a text from anyone you forward it automatically to another number. Is something like this at all possible?
Just to be clear I don't want to solve that particular problem through some other means, just want to know if apps can accomplish that.
Also if that is possible is it possible for an app that i write to alter more immediate and instant things, like an incoming call.
thanks all for reading this, and hopefully a helpful response :)
It depends on how far you want to go, but I would expect that what you want to achieve probably isn't possible.
The Android OS does reserve some actions and prevent them from being doing programmatically. For example, you can display the Dialer with a number filled in but the user has to press the call button to make a call. Similarly, you can display the SMS app with a message already written but it is up to the user to send the message.
I don't know for sure, but I assume this is for security. For example, let's imagine you could write an application which could start a call with no user interaction. I would release my Super-Handy-Dialer application which makes quick calls for you making you life easier, but what it also would do is wait until 2am and call my premium rate phone line every night for 3 hours.

Categories

Resources