I have a ContentObserver registered to android.provider.Settings.System that should observe changes of any audio volume. It is notified as expected when clicking the hardware volume buttons but is not notified when I change the audio volume via AudioManager.setStreamVolume or AudioManager.adjustStreamVolume.
Here's how my ContentObserver looks like:
// this is a Service
this.getApplicationContext().getContentResolver().registerContentObserver(
android.provider.Settings.System.CONTENT_URI,
true, new ContentObserver(new Handler()) {
public void onChange(boolean selfChange) {
Log.d("ContentObserver", "got notified");
}
});
And here my call to AudioManager.adjustStreamVolume:
// this.context is the activities context
this.context.getSystemService(Context.AUDIO_SERVICE).adjustStreamVolume(
AudioManager.STREAM_RING, AudioManager.ADJUST_LOWER,
AudioManager.FLAG_SHOW_UI);
I have read this and that post and the AudioManager and Settings.System documentation and can not find a reason why the Observer is notified when changing the volume with the volume buttons but not when changing it with the AudioManager.
Thanks for the help!
The AudioManager does broadcast an intent
android.media.VOLUME_CHANGED_ACTION`
But this is not part of the official documentation. So this might change in future releases. But you could use this atleast for gingerbread devices.
you can find more about the extras in the intent from here
Related
I'm trying to build a broadcast that every time audio output route is changed it would route it to a device of choice instead (both in calls and when playing media/music).
for example: when getting a call with plugged/Bluetooth headset and then the user decides to click on the speaker icon on the phone, I need the app to route it back to the headset.
I succeeded to change the audio output on a WIRED headset with a click of a button with following code:
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
mAudioManager.setSpeakerphoneOn(false);
and on a Bluetooth headset with the following (not in calls, works on media/music only):
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mAudioManager.startBluetoothSco();
mAudioManager.setBluetoothScoOn(true);
mAudioManager.setSpeakerphoneOn(false);
I have two problems:
When I click on the speaker icon in the call screen to stop using my Bluetooth headset and then click the button on my app to redirct the route to my Bluetooth headset with the above code it doesn't work :(
Didn't manage to find a way to broadcast audio output change in order for the above code to work automatically without a need to press my app's button. only came across the following code that only suppose to work on a Bluetooth headset and not plugged headset and it's don't even work for me on the Bluetooth headset.
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, -1);
switch (state) {
case BluetoothHeadset.STATE_AUDIO_CONNECTED:
Toast.makeText(context, "Bluetooth Connected", Toast.LENGTH_SHORT).show();
case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
Toast.makeText(context, "Bluetooth Disconnected", Toast.LENGTH_SHORT).show();
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
mAudioManager.startBluetoothSco();
mAudioManager.setBluetoothScoOn(true);
mAudioManager.setSpeakerphoneOn(false);
break;
}
}
}
};
Thanks so much in advance for the help!
any answer would help.
I am using blescan with scanfilters to detect beacons it's working very fine in foreground and background up to oreo version but when it comes to android pie it's not able to send pending broadcast in background.
ScanSettings settings = (new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)).build();
final List<ScanFilter> scanFilters = new ArrayList<>();
scanFilters.add(getScanFilter());
BluetoothAdapter bluetoothAdapter;
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
Intent intent = new Intent(this.getApplicationContext(), MyBroadcastReceiver.class);
intent.putExtra("o-scan", true);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
bluetoothAdapter.getBluetoothLeScanner().startScan(scanFilters, settings, pendingIntent);
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int bleCallbackType = intent.getIntExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, -1);
if (bleCallbackType != -1) {
Log.d(TAG, "Passive background scan callback type: "+bleCallbackType);
ArrayList<ScanResult> scanResults = intent.getParcelableArrayListExtra(
BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT);
// Do something with your ScanResult list here.
// These contain the data of your matching BLE advertising packets
}
}
}
Android 9 introduces several behavior changes, such as limiting background apps' access to device sensors and Wi-Fi scans.
These changes affect all apps running on Android 9, regardless of target SDK version.
Sensors that use the continuous reporting mode, such as accelerometers and gyroscopes, don't receive events.
Android 9 Limited access to sensors in background:
Android 9 limits the ability for background apps to access user input and sensor data. If your app is running in the background on a device running Android 9, the system applies the following restrictions to your app:
Sensors that use the continuous reporting mode, such as accelerometers and gyroscopes, don't receive events.
Sensors that use the on-change or one-shot reporting modes don't receive events.
Solution:
If your app needs to detect sensor events on devices running Android 9 while the app is in the background, use a foreground service.
I an example test Android app using Oreo (API 26) and the the code above (slightly modified) to detect beacons. I am using the Pixel 3 XL (with Pie).
I think that the hard part about this is to know for sure if the code in onRecieve() in MyBroadcastReceiver is actually being run upon detection of a beacon when the device is running on battery only (disconnected from Android-studio and Logcat (USB)).
Using Volley (com.android.volley) to submit a HTTP request to a local http server, I was able to demonstrate that it works as documented - ie. I am able to receive the http request when beacon(s) are detected. However, Volley only sends these these requests when Android is awake or when it periodically wakes up and connects to the network - which in my simple tests was about every 15 minutes (plus some variation), but I did get all the beacon ScanResults on my HTTP server, just in delayed up to 15 minutes. I was even able to remove the app from the list of running apps (you know; swiping up to remove the app) and still see that the onRecieve() in MyBroadcastReceiver was receiving BLE ScanResults.
How do you know that the onRecieve() in MyBroadcastReceiver is being killed? I am very interested to know how you know this.
Is there any way within (or non-standard way) to disable email and sms alerts / notifications when an Android application is running? I found a way to mute the phone ringer, but I want to stop the audio / vibrate alerts from occuring. I've seen some bed time clock apps that mute notifications and they work fine.
Any thoughts to how to code this?
According to the API docs:
AudioManager aM = getSystemService(Context.AUDIO_SERVICE);
aM.setRingerMode(AudioManager.RINGER_MODE_SILENT);
aM.setVibrateSetting (AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_OFF)
public void setRingerMode (int ringerMode)
Since: API Level 1
Sets the ringer mode.
Silent mode will mute the volume and will not vibrate. Vibrate mode will mute the volume and vibrate. Normal mode will be audible and may vibrate according to user settings.
Parameters
ringerMode The ringer mode, one of RINGER_MODE_NORMAL, RINGER_MODE_SILENT, or RINGER_MODE_VIBRATE.
public void setVibrateSetting (int vibrateType, int vibrateSetting)
Since: API Level 1
Sets the setting for when the vibrate type should vibrate.
This method should only be used by applications that replace the platform-wide management of audio settings or the main telephony application.
Parameters
vibrateType The type of vibrate. One of VIBRATE_TYPE_NOTIFICATION or VIBRATE_TYPE_RINGER.
vibrateSetting The vibrate setting, one of VIBRATE_SETTING_ON, VIBRATE_SETTING_OFF, or VIBRATE_SETTING_ONLY_SILENT.
I am writing an Android app where the user can take pictures and I am using my own camera functionality instead of Androids built in camera software. It all works fine except I want to be able to take a picture when the user presses the hard camera button. I registered a Broadcast receiver, and it works but Android still opens its camera program over my app. Is there a way to block the built in app from receiving the broadcast?
I am posting my code below.
Any help would be greatly appreciated.
Thankyou
//Listen for camera button to be pressed
cameraButtonListener = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(Intent.ACTION_CAMERA_BUTTON)){
Toast.makeText(getApplicationContext(), "Camera Button Pressed", Toast.LENGTH_SHORT).show();
}
}
};
//register broadcast receiver to listen for camera button
getApplicationContext().registerReceiver(cameraButtonListener,new IntentFilter(Intent.ACTION_CAMERA_BUTTON) );
You can use abortBroadcast() in conjunction with android:priority set to high to "consume" the broadcast. However, this works only if the broadcast is an Ordered broadcast, and I don't know what type is ACTION_CAMERA_BUTTON. More info here.
try this code
if("android.intent.action.ACTION_CAMERA_BUTTON".equals(intent.getAction()))
in register
getApplicationContext().registerReceiver(cameraButtonListener,new IntentFilter(Intent.ACTION_CAMERA_BUTTON) );
I have an app that will speak text messages to the user. I want to make it so that when the user hits a button called "Headphones on" the app will only speak to it when headphones are detected. Is there a command that will allow me to detect if headphones are plugged in or not?
There is a broadcast made when the headphones are plugged in: http://developer.android.com/reference/android/content/Intent.html#ACTION_HEADSET_PLUG
You need to register a BroadcastReceiver to receive this and perform your required actions.
It seems in this case you just want to check if headphone are connected before to start the audio playout, so you should use audioManager.isWiredHeadsetOn() like this:
AudioManager audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
if(audioManager.isWiredHeadsetOn()) {
// Play audio...
}