I have a notification being fired through AlarmManager and the notification also
plays a sound.
Obviously, it may happen that the alarm is fired when the app is in the background, and I would like to let the user cancel the sound when pressing the lock button - i.e. listening for ACTION_SCREEN_OFF.
Therefore I wonder if it's possible to start a service and listen for ACTION_SCREEN_OFF?
I have seen Listening for ACTION_SCREEN_OFF but that solution of having a BroadCastReceiver only seems to work when the app is in the foreground. Right?
For instance if you are trying to do ACTION_SCREEN_OFF then you would define your broadcast receiver in your Activity that started the alarm for instance.
public class SomeListener extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//Turn off sounds
}
}
Then in the manifest provide something of the sort like this within the activity that uses the listener.
<intent-filter>
<action android:name="android.hardware.usb.action.ACTION_SCREEN_OFF" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.ACTION_SCREEN_OFF"
android:resource="#xml/my_filter" />
Where the extra my_filter class could provide additional meta-data. In this case it was a check against a Serial or UUID of the device so not to launch on all USB connects. But you should be able to do something similar.
When the action occurs, this should fire the listener within your application, as I understand it anyways. This feature works for launch of application on USB connect for me in the past. Even without having had the application open in the first place.
Related
I'm making an Android TV and Amazon Fire TV app that uses WAKELOCK to prevent the TV device from going to sleep. What I need to do though is release the WAKELOCK when the screen gets turned off, e.g. when someone presses the power button on the TV, as in this case the Amazon Fire TV Stick etc stay active although the TV is powered off.
I then need to re-add the WAKELOCK when the TV is powered on. What is the accepted best practice for handling this?
EDIT: as per comment I'm updating this response with the most effective method.
In a nutshell you can achieve this in two ways:
Check if the HDMI gets disconnected (mainly works on phones, keep reading for TV)
Check if the audio channel becomes noisy. As per Android documentation (https://developer.android.com/guide/topics/media/mediaplayer.html#noisyintent) you can do something like the following (change with ):
"You can ensure your app stops playing music in these situations by handling the ACTION_AUDIO_BECOMING_NOISY intent, for which you can register a receiver by adding the following to your manifest:
<receiver android:name=".MusicIntentReceiver">
<intent-filter>
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
</intent-filter>
</receiver>
This registers the MusicIntentReceiver class as a broadcast receiver for that intent. You should then implement this class:
public class MusicIntentReceiver extends android.content.BroadcastReceiver {
#Override
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().equals(
android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
// signal your service to stop playback
// (via an Intent, for instance)
}
}
}
Im making a SIP application for android 2.3.3. I can call someone and my "incoming call screen" is shown when some calls me. But when my app is running on the background and someone calls me , the "call screen" isn't been launched. so how can I make it launch like a normal incoming call.
FIXED:
Manifest: add the following code in application tag
<receiver android:name=".ReceiverTest" android:enabled="true">
<intent-filter>
<action android:name="com.example.INCOMING_CALL" />
</intent-filter>
</receiver>
Receiver class: when I receive a call, it will open my Incomingcall page
public class ReceiverTest extends BroadcastReceiver{
#Override
public void onReceive(Context arg0, Intent arg1) {
...
Intent nextPage= new Intent("com.example.IncomingPage");
nextPage.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
arg0.startActivity(nextPage);
...
}
}
If you are using an Activity your app is not running the background. When a new activity is brought to the top of the stack your application is paused and placed in the background. To allow your application to receive any type of notification try running a service or create a broadcast receiver to pick up the intents you want to listen for. This allows your app to process while it is not on the top of the stack.
UPDATE
So you have registered a broadcast receiver... this is good... but... If you registered it in your activity and the activity is killed, so is the reference and vm of your application and the intent is not received. Try making your broadcast receiver independent of the activity (ie make it be invoked by the system using the manifest). Then your broadcast receiver can receive intents even when your application is dead, and launch what you need.
The alternative is make a service that registers your receiver - a service can run in the background but then you have to worry about making your service light enough to never be killed (more tricks to this). The best best is option 1 (way less overhead).
I'm using a service. In that service my code should get executed when the user changes to silent mode, i.e. as soon as the user changes to silent mode, my code needs to get executed.
How can I do this?
You don't want use a service. Instead you want to use a BroadcastReciever that filters for the android.media.RINGER_MODE_CHANGED Intent.
You might want to take a look at this project as it deals with the phone being silenced. It probably has some source code that will be useful to you.
You can register to listen to the BroadcastAudioManager.RINGER_MODE_CHANGED_ACTION.
In your manifest file you can register the intent like this
<intent-filter>
<action android:name="android.media.RINGER_MODE_CHANGED" />
</intent-filter>
And then recieve the intent at method
public void onReceive(Context context, Intent intent)
of class that extends BroadcastReceiver class
I have a little confusion with broadcast receivers. I have a broadcast receiver which is triggered upon TIME_SET and TIMEZONE_CHANGED actions (the code is given below). What I was wondering is, can OnDateTimeChanged (see the code below) be triggered simultaneously (and its execution overlaps) when both TIME_SET and TIMEZONE_CHANGED actions are triggered or is one always going to be triggered after the other? Based on some simple experiments I did, I got the impression that the two executions of OnDateTimeChanged are triggered consecutively with no time overlap but I cannot be 100% sure of this. If anyone has an idea I'll be very happy.
<!-- Excerpt from manifest -->
<receiver android:name=".OnDateTimeChanged">
<intent-filter>
<action android:name="android.intent.action.TIME_SET"/>
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
</intent-filter>
</receiver>
// Broadcast receiver class
public class OnDateTimeChanged extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// Do some work here
}
}
BTW, both TIME_SET and TIMEZONE_CHANGED can be triggered when under Settings - Date&Time you switch to the Automatic mode and this changes both the time and the timezone.
-Ali
Logically, they would all execute simultaneously. Physically, only one can occupy a core at a time and might finish before another starts. Under identical conditions,the behavior might appear to be consistent. The documentation itself describes it as, "All receivers of the broadcast are run in an undefined order, often at the same time."
If you want to give other receivers a chance to run, you can call Thread.yield().
This question already has answers here:
Checking if an Android application is running in the background
(35 answers)
Closed 4 years ago.
I have implemented a BroadcastReceiver which is triggered by the AlarmManager. The AlarmManager is initialized on BOOT_COMPLETED. So i have to declare the receiver in the manifest.
My problem is that i want the BroadcastReceiver only to do something when none of my own activities are in the foreground (aka the user is not interacting with my application). I pull information from a remote server and don't want to notify the user if he is currently in my application anyways.
So far i have not managed to find a way to determine if my application is in the foreground. Is there a way to do such thing? The ActivityManager tells me if my application is running but not whether it is in the foreground.
The problem is pretty much the same as described here: Inform Activity from a BroadcastReceiver ONLY if it is in the foreground
SOLUTION:
After evaluating several solutions i want to quickly outline what i think is the best method to deal with activities in the background/foreground.
The preferred way is to register a broadcast receiver in the onResume method of your activity and to deregister it on the activities on onPause. Any service or other background element will than need to send a broadcast intent with a specific action that your activity will intercept.
If your activity is in the foreground it will have its intent receiver registered and is able to directly deal with the intent send from your service. If it is not in the foreground it will not receive the intent but the service that invokved the broadcast will know that nobody intercepted its broadcast intent and will be able to deal with that itself. Eg it could than launch the desired activity, show a notification etc.
The following answer: "Is application running in background", summarizes solutions available for background/foreground checking.
Note:
Previously this answer suggested to use ActivityManager.getRunningAppProcesses(), however that method appeared to be not completely reliable and its usage is discouraged. Check the link above for the details.
Your activity can track its own state as to whether it is in the foreground (set boolean to true in onStart(), to false in onStop()). Alas, that boolean is not provided to you by Activity automatically.
ActivityManager#getRunningAppProcesses() returns a List of RunningAppProcessInfo. Each RunningAppProcessInfo has a field called importance. importance equal to RunningAppProcessInfo.IMPORTANCE_FOREGROUND seems to show which activity is actively being observed by the user. There is also RunningAppProcessInfo.IMPORTANCE_VISIBLE which is lower but might be worth checking out.
check out my solution for determining if an activity is in the foreground: http://www.mannaz.at/codebase/android-activity-foreground-surveillance/
It should be easy to revert the logic from "in the foreground" to "not in the foreground".
I have implemented a BroadcastReceiver which is triggered by the AlarmManager. The AlarmManager is initialized on BOOT_COMPLETED. So i have to declare the receiver in the manifest.
My problem is that i want the BroadcastReceiver only to do something when none of my own activities are in the foreground (aka the user is not interacting with my application). I pull information from a remote server and don't want to notify the user if he is currently in my application anyways.
So far i have not managed to find a way to determine if my application is in the foreground. Is there a way to do such thing? The ActivityManager tells me if my application is running but not whether it is in the foreground.
There doesn't seem to be a direct way to determine if one of your activities is the current running foreground activity. However, you can get the desired effect by using an ordered broadcast and two broadcast receivers. One broadcast receiver needs to be registered in OnResume() and unregistered in OnPause(). The 2nd broadcast receiver will be declared in your manifest as you've already done. Set the android:priority for your receivers such that if the dynamically registered receiver is registered, it will receive the intent first, then you can eat the intent so that the broadcast receiver you registered in your manifest is never notified.
You can test if the window has focus - but as stated in dev docs this is not the same as if activity is in foreground.
I'd use ActivityLifecycleCallbacks to get much cleaner solution.
It can be insecure, read this before you decided to use example below in production. It works in 'home development' for my device and OS version.
public class App extends Application implements Application.ActivityLifecycleCallbacks {
private boolean inForeground;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityResumed(Activity activity) {
inForeground = activity instanceof YourActivity;
}
public boolean isInForeground() {
return inForeground;
}
Register App in AndroidManifest:
<application
android:name=".App" />
And the final piece of the puzzle:
public class YourReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
App app = (App) context.getApplicationContext();
if(app.isInForeground()){
// do some stuff
}
}
}