I created App to App Android Sinch Application. When user on call without headphone its working on speaker but if user connect headphone its not automatically connecting to headphone instead of that i need to manually mute speaker and its connecting to headphone. Please check the code i done.
private void enableSpeaker(boolean enable) {
AudioController audioController = getSinchServiceInterface().getAudioController();
if (enable)
audioController.enableSpeaker();
else
audioController.disableSpeaker();
switchVolume.setImageDrawable(ContextCompat.getDrawable(this, isSpeaker ? R.drawable.ic_speaker : R.drawable.ic_speaker_off));
}
private void setMuteUnmute() {
AudioController audioController = getSinchServiceInterface().getAudioController();
if (isMute) {
audioController.mute();
switchMic.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_mic_off));
} else {
audioController.unmute();
switchMic.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_mic_on));
}
}
I think you enabled Speaker in your onCallEstablished method.
Remove enableSpeaker() method from onCallEstablished method and add enableAutomaticAudioRouting() like below.
For more details check sinch documentation Here
#Override
public void onCallEstablished(Call call)
{
AudioController audioController = getSinchServiceInterface().getAudioController();
audioController.enableAutomaticAudioRouting(true, AudioController.UseSpeakerphone.SPEAKERPHONE_AUTO);
}
Related
I am building a video chatting app via the Linphone SDK.
There is an issue that when someone "receives" a video call, the loud speaker is off by default, so users need to use the phone speaker, the one used for phone call, rather than the loud speaker. However, at the same time, the one who gives the call has the loud speaker on by default.
LinphoneManager.getInstance().routeAudioToSpeaker();
I thought this is the code for which Linphone turns on loud speaker, but actually it's not.
How do I turn on loud speaker when users receive video calls by default?
LinphoneCore has two handy method for that:
enableSpeaker(boolean)
muteMic(boolean)
Just create helper functions inside LinphoneManager:
public void enableVoice() {
getLc().muteMic(false);
getLc().enableSpeaker(true);
}
public void disableVoice() {
getLc().muteMic(true);
getLc().enableSpeaker(false);
}
If you don't have an access to LinphoneManager, then the functions above should call:
LinphoneManager.getLc().{method_call};
private AudioManager mAudioManager;
...
public LinphoneMiniManager(Context c) {
mContext = c;
mAudioManager = ((AudioManager) c.getSystemService(Context.AUDIO_SERVICE));
mAudioManager.setSpeakerphoneOn(true);
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
....
btnSpeaker.setOnClickListener {
mIsSpeakerEnabled = !mIsSpeakerEnabled
it.isSelected = mIsSpeakerEnabled
toggleSpeaker()
}
....
}
private fun toggleSpeaker() {
val currentAudioDevice = core.currentCall?.outputAudioDevice
val speakerEnabled = currentAudioDevice?.type == AudioDevice.Type.Speaker
for (audioDevice in core.audioDevices) {
if (speakerEnabled && audioDevice.type == AudioDevice.Type.Earpiece) {
core.currentCall?.outputAudioDevice = audioDevice
return
} else if (!speakerEnabled && audioDevice.type == AudioDevice.Type.Speaker) {
core.currentCall?.outputAudioDevice = audioDevice
return
}/* If we wanted to route the audio to a bluetooth headset
else if (audioDevice.type == AudioDevice.Type.Bluetooth) {
core.currentCall?.outputAudioDevice = audioDevice
}*/
}
}
I've been writing a chat app to work with bluetooth headsets/earphones.
So far I've been able to record audio files via the mic in a bluetooth headset and
I've been able to get Speech-to-text working with the Android device's built in microphone, using RecogniserIntent etc.
But I can't find a way of getting SpeechRecogniser to listen through the Bluetooth mic.Is it even possible to do so, and if so, how?
Current Device: Samsung Galax
Android Version: 4.4.2
Edit: I found some options hidden in my tablets settings for the Speech Recognizer, one of these is a tick box labeled "use bluetooth microphone" but it seems to have no effect.
Found the answer to my own question so I'm posting it for others to use:
In order to get speak recognition to work with a Bluetooth Mic you first need to get the device as a BluetoothHeadset Object and then call .startVoiceRecognition() on it, this will set the mode to Voice recognition.
Once finished you need to call .stopVoiceRecognition().
You get the BluetoothHeadset as such:
private void SetupBluetooth()
{
btAdapter = BluetoothAdapter.getDefaultAdapter();
pairedDevices = btAdapter.getBondedDevices();
BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy)
{
if (profile == BluetoothProfile.HEADSET)
{
btHeadset = (BluetoothHeadset) proxy;
}
}
public void onServiceDisconnected(int profile)
{
if (profile == BluetoothProfile.HEADSET) {
btHeadset = null;
}
}
};
btAdapter.getProfileProxy(SpeechActivity.this, mProfileListener, BluetoothProfile.HEADSET);
}
Then you get call startVoiceRecognition() and send off your voice recognition intent like so:
private void startVoice()
{
if(btAdapter.isEnabled())
{
for (BluetoothDevice tryDevice : pairedDevices)
{
//This loop tries to start VoiceRecognition mode on every paired device until it finds one that works(which will be the currently in use bluetooth headset)
if (btHeadset.startVoiceRecognition(tryDevice))
{
break;
}
}
}
recogIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recogIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
recog = SpeechRecognizer.createSpeechRecognizer(SpeechActivity.this);
recog.setRecognitionListener(new RecognitionListener()
{
.........
});
recog.startListening(recogIntent);
}
I am trying to send all the audio of an application via SCO.
I am able to successfully send the audio,
But when an incoming call comes I need to disconnect form SCO so that the application audio will not interfere with the call,
The problem is that, when I try to reroute the audio to SCO after the call, it does not work.
Here is the code I use to send the audio to SCO:
public class BluetoothManager {
// For Bluetooth connectvity
private static String TAG = "BluetoothManager";
private static BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private static AudioManager aM;
/**
* Set the audio manager of the device.
* #param c: The context this method is called from
*/
public static void setAudioManager(Context c) {
aM = (android.media.AudioManager)c.getSystemService(Context.AUDIO_SERVICE);
}
/**
* Check if a Bluetooth headset is connected. If so, route audio to Bluetooth SCO.
*/
private static void initializeAudioMode(Context context) {
BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
BluetoothHeadset bh = (BluetoothHeadset) proxy;
List<BluetoothDevice> devices = bh.getConnectedDevices();
if (devices.size() > 0) {
enableBluetoothSCO();
}
}
mBluetoothAdapter.closeProfileProxy(profile, proxy);
}
public void onServiceDisconnected(int profile) {}
};
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
}
/**
* Bluetooth Connectvity
* The following methods are associated with enabling/disabling Bluetooth.
* In the future we may want to disable other sources of audio.
*/
private static void enableBluetoothSCO() {
aM.setMode(AudioManager.MODE_IN_CALL);
aM.startBluetoothSco();
aM.setBluetoothScoOn(true);
}
/** Right now, this simply enables Bluetooth */
#SuppressLint("NewApi")
public static boolean enableBluetooth(Context c) {
// If there is an adapter, enable it if not already enabled
if (mBluetoothAdapter != null) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
setAudioManager(c);
initializeAudioMode(c);
Log.e(TAG, "SCO: " + aM.isBluetoothScoOn());
Log.e(TAG, "A2DP: " + aM.isSpeakerphoneOn());
return true;
} else {
Log.v(TAG, "There is no bluetooth adapter");
return false;
}
}
/** Right now, this simply disables Bluetooth */
public static void disableBluetooth() {
// If there is an adapter, disabled it if not already disabled
if (mBluetoothAdapter != null) {
if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
}
} else {
Log.v(TAG, "There is no bluetooth adapter");
}
}
public static void restartBluetooth(){
aM.setMode(AudioManager.MODE_IN_CALL);
}
public static void stopBluetooth(){
aM.setMode(AudioManager.MODE_NORMAL);
}
}
When I call stopBluetooth() correctly the audio of the application is not sent to the headset anymore,
But when I call restartBluetooth() the audio plays NOT form the headset as intended, but from the phone speakers.
Is it possible that the SCO link was brought down after the call ended? If this is the case then the SCO link would also have to be brought up along with routing the audio.
Have you tried calling enableBluetoothSCO() within restartBluetooth()
You probably need to call:
aM.startBluetoothSco();
aM.setBluetoothScoOn(true);
after you set the mode.
inside your restart function initialize everything again, and see if it works. like so:
public static void restartBluetooth(){
enableBluetooth(getApplicationContext());
}
if this works then it means that when the call is ended the last initialization is lost for some reason.
Google Doc say's that
"Phone application always has the priority on the usage of the SCO connection for telephony. If this method is called while the phone is in call it will be ignored. Similarly, if a call is received or sent while an application is using the SCO connection, the connection will be lost for the application and NOT returned automatically when the call ends."
So when call is disconnected you must have to re-establish the connection by calling startBluetoothSco()
For anyone that is still having issues with this, there are a few things that need to be done. The first thing you need to do is to keep track of the phone state. You can see how to do that here:
How to know Phone call has ended?
When the state is idle that means the incoming call has ended. Now if you try to reconnect the bluetooth at this point you'll find it still does not work since it takes a while (roughly 2 seconds) for the call to "release" the bluetooth device.
So you have two option, wait a bit then try to reconnect, or you can add another listener to BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED.
You can then add a global boolean value isIdle that is true when TelephonyManager.CALL_STATE_IDLE or false when TelephonyManager.CALL_STATE_OFFHOOK (Otherwise you'll reconnect to BlueTooth during the incoming call). At this point when BluetoothHeadset.STATE_DISCONNECTED and isIdle is true, then reconnect to Bluetooth.
#Override public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals((BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED))){
int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
switch(state) {
case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
if (isIdle){
//reconnect bluetooth
}
break;
}
}
if(("OFFHOOK").equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE))) {
isIdle = false;
// turn bluetooth off
}
if(("IDLE").equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE))) {
isIdle = true;
}
}
My requirement is to switch audio between Bluetooth and phone speaker as per user selection.
Below is the code snippet:
//AudioTrack for incoming audio to play as below:
int mMaxJitter = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);
new AudioTrack(AudioManager.STREAM_VOICE_CALL,8000,
AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
mMaxJitter, AudioTrack.MODE_STREAM);
//To register broadcast receiver for bluetooth audio routing
IntentFilter ifil = new IntentFilter();
ifil.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
this.registerReceiver(<receiver instance>,ifil);
//To get AudioManager service
AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
//Whenever user select to route audio to Bluetooth
mAudioManager.setMode(AudioManager.MODE_IN_CALL);//tried setting with other mode also viz. MODE_NORMAL, MODE_IN_COMMUNICATION but no luck
mAudioManager.startBluetoothSco();//after this I get AudioManager.SCO_AUDIO_STATE_CONNECTED state in the receiver
mAudioManager.setBluetoothScoOn(true);
mAudioManager.setSpeakerphoneOn(false);
//Whenever user select to route audio to Phone Speaker
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.stopBluetoothSco();//after this I get AudioManager.SCO_AUDIO_STATE_DISCONNECTED state in the receiver
mAudioManager.setBluetoothScoOn(false);
mAudioManager.setSpeakerphoneOn(true);
Issues:
1. I'm able to route audio but Behavior is inconsistent, sometimes it routes to phone speaker even if user choose to route to bluetooth(bluetooth is connected)
2. If audio is routed to phone speaker, volume becomes low(please don't say check the phone volume)
3. Only a few times I could observe audio routing is proper as per choice, if I repeat it becomes weird as I mentioned above.
Android version: Jellybean 4.3
Has anyone faced something similar behavior ?
Thanks!
I got the reason of inconsistent audio routing, it was because I was setting phone speaker false, also I was using inappropriate mode...
below combination worked for me:
//For BT
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mAudioManager.startBluetoothSco();
mAudioManager.setBluetoothScoOn(true);
//For phone ear piece
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
mAudioManager.setSpeakerphoneOn(false);
//For phone speaker(loadspeaker)
mAudioManager.setMode(AudioManager.MODE_NORMAL);
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
mAudioManager.setSpeakerphoneOn(true);
Android version: 4.3
Thanks!
if it still relevant to someone, this is my solution:
(tested on samsung s7 sm-g9307 with android version 6.0.1)
public class AudioSourceUtil {
private static void reset(AudioManager audioManager) {
if (audioManager != null) {
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.stopBluetoothSco();
audioManager.setBluetoothScoOn(false);
audioManager.setSpeakerphoneOn(false);
audioManager.setWiredHeadsetOn(false);
}
}
public static void connectEarpiece(AudioManager audioManager) {
reset(audioManager);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
}
public static void connectSpeaker(AudioManager audioManager) {
reset(audioManager);
audioManager.setSpeakerphoneOn(true);
}
public static void connectHeadphones(AudioManager audioManager) {
reset(audioManager);
audioManager.setWiredHeadsetOn(true);
}
public static void connectBluetooth(AudioManager audioManager) {
reset(audioManager);
}
}
And for the usage by clicking a button (tab in tab layout):
/**
* There are 3 scenarios for the audio source:
* 1. No headphones and no bluetooth device: toggle phone/ speaker
* 2. Headphones connected: toggle headphones/ speaker
* 3. Bluetooth connected: toggle phone/ speaker/ bluetooth
*
* #param tab
*/
private void handleTabAudioSourceClick(TabLayout.Tab tab) {
View view = tab.getCustomView();
ImageView icon = (ImageView) view.findViewById(R.id.imageViewIcon);
int currentAudioSourceIdentifier = (Integer) view.getTag();
if (audioManager.isWiredHeadsetOn() == false && BluetoothManager.isBluetoothHeadsetConnected() == false) {
// No headphones and no bluetooth device: toggle phone/ speaker.
if (currentAudioSourceIdentifier == R.drawable.tab_speaker) {
// Current audio source is earpiece, moving to speaker.
view.setTag(android.R.drawable.stat_sys_speakerphone);
icon.setImageResource(android.R.drawable.stat_sys_speakerphone);
AudioSourceUtil.connectSpeaker(audioManager);
} else {
// Current audio source is speaker, moving to earpiece.
view.setTag(R.drawable.tab_speaker);
icon.setImageResource(R.drawable.tab_speaker);
AudioSourceUtil.connectEarpiece(audioManager);
}
} else if (audioManager.isWiredHeadsetOn()) {
// Headphones connected: toggle headphones/ speaker.
if (currentAudioSourceIdentifier == android.R.drawable.stat_sys_speakerphone) {
// Current audio source is speaker, moving to headphones.
view.setTag(android.R.drawable.stat_sys_headset);
icon.setImageResource(android.R.drawable.stat_sys_headset);
AudioSourceUtil.connectHeadphones(audioManager);
} else {
// Current audio source is headphones, moving to speaker.
view.setTag(android.R.drawable.stat_sys_speakerphone);
icon.setImageResource(android.R.drawable.stat_sys_speakerphone);
AudioSourceUtil.connectSpeaker(audioManager);
}
} else if (BluetoothManager.isBluetoothHeadsetConnected()) {
// Bluetooth connected: toggle phone/ speaker/ bluetooth.
if (currentAudioSourceIdentifier == R.drawable.tab_speaker) {
// Current audio source is earpiece, moving to speaker.
view.setTag(android.R.drawable.stat_sys_speakerphone);
icon.setImageResource(android.R.drawable.stat_sys_speakerphone);
AudioSourceUtil.connectSpeaker(audioManager);
} else if (currentAudioSourceIdentifier == android.R.drawable.stat_sys_speakerphone) {
// Current audio source is speaker, moving to bluetooth.
view.setTag(android.R.drawable.stat_sys_data_bluetooth);
icon.setImageResource(android.R.drawable.stat_sys_data_bluetooth);
AudioSourceUtil.connectBluetooth(audioManager);
} else {
// Current audio source is bluetooth, moving to earpiece.
view.setTag(R.drawable.tab_speaker);
icon.setImageResource(R.drawable.tab_speaker);
AudioSourceUtil.connectEarpiece(audioManager);
}
}
}
Use MediaRouter api's for this:
https://developer.android.com/guide/topics/media/mediarouter
It is designed specially for this.
Something like this:
mediaRouter = MediaRouter.getInstance(VideoCallingApp.getContext());
mediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
.build();
....
public void onStart() {
mediaRouter.addCallback(mediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
super.onStart();
}
#Override
public void onStop() {
mediaRouter.removeCallback(mMediaRouterCallback);
super.onStop();
}
...and when you want to switch audio device then use mediaRouter.getRoutes() and mediaRouter.selectRoute(route) API's.
i'm new to android , i want to program an application for android,
i need some help
i want a way to simply call a function that turn the wifi on/off
and another function that change the profile from silent to general(vibration/ringing)
and from general to silent(ringing/vibration)
any help please???
public class Control{
public void turnVibrationOn(){
.......
}
public void turnVibrationOff(){
.......
}
public void turnWifiOn(){
.......
}
public void turnWifiOff(){
.......
}
}
}
Vibration: Use the AudioManager service.
((AudioManager) getSystemService(AUDIO_SERVICE))
.setRingerMode(AudioManager.RINGER_MODE_VIBRATE)
Wi-Fi: Use the WifiManager service.
((WifiManager) getSystemService(WIFI_SERVICE))
.setWifiEnabled(false)
(And request the proper permission.)