How to make Android phone as a bluetooth headset? - android

Yes, I know Android has already implemented the Bluetooth Headset
Profile, but it is in Audio Gateway Role, not in HeadSet Role.
What I want to do is develop an application on Android phone which
will act as a bluetooth headset, so it can connect to my laptop by
bluetooth.
When I try to call somebody, I can use my phone to dial him, and my
application will forward the voice through bluetooth to my laptop,
and one other application running on laptop will get the voice data
and forward them to Skype or GTalk or some VoIP program else.
In other words, how can I implement the Headset Profile in Headset
Role on Android phone? Thanks in advance!

From the android side, I think the best solution is to open the connection to the service in your computer:
URL url = new URL("http://192.186.0.1/path/to/service");
URLConnection connection = url.openConnection();
Get it as an OutputStream:
OutputStream out = new BufferedStream(connection.getOutputStream());
and then use a AudioRecord to send though the recorded data:
public static final int DEFAULT_SAMPLE_RATE = 8000;
private static final int DEFAULT_BUFFER_SIZE = 4096;
private static final int CALLBACK_PERIOD = 4000;
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
DEFAULT_SAMPLE_RATE, AudioFormat.CHANNEL_CONFIGURATION_DEFAULT,
AudioFormat.ENCODING_DEFAULT, DEFAULT_BUFFER_SIZE);
recorder.setPositionNotificationPeriod(CALLBACK_PERIOD);
int bytesRead = 0;
ByteBuffer buffer = ByteBuffer.allocateDirect(DEFAULT_BUFFER_SIZE);
while ((bytesRead = recorder.read(buffer, DEFAULT_BUFFER_SIZE)) > 0) {
out.write(buffer.array(), 0, bytesRead);
}
All this should be done on a separate thread of course to avoid crashing the app and a mechanism to handle when the recording stops or the connection is lost. Also, I'm pretty sure it should work over wifi although I am not sure if it will be the same with bluetooth (although most devices with BT have wifi now a days and you get more bandwidth)
I haven't tested this code so I'm not 100% sure it will work.
The next thing will be on the machine to transfer the audio into the desire app, but that's above my experience. I imagine you will have to do a virtual driver or something like that.
Also will have to do the inverse mechanism for the audio sent from the desktop app into the phone (I'm rather interested on that part since would make a nice wireless headset for watching movies as well).
Here are my 2 cents; I am eager to know if it works. ;)

I don't know if i understood the real question or your main goal... but I had posted here how receive and send the sound from your headset via bluetooth in android.
I hope to help you...

Related

When developing on Android, how can I interface with USB DAC without preventing other applications from playing sound on it?

I have a headphone that connect to my phone via type-c. It has USB DAC in it, connected to type-c with USB protocol.
To control its sidetone volume, I do:
UsbInterface usbInterface = theDevice.getInterface(0);
UsbDeviceConnection connection = usbManager.openDevice(theDevice);
connection.claimInterface(usbInterface, true);
byte[] buffer = intTo2Bytes(volume);
connection.controlTransfer(0x21,0x01,0x0100,0x0200,new byte[]{0x00},1,100);
connection.controlTransfer(0x21,0x01,0x0200,0x0200,buffer,2,100);
connection.controlTransfer(0x21,0x01,0x0100,0x0500,new byte[]{0x00},1,100);
connection.controlTransfer(0x21,0x01,0x0201,0x0500,new byte[]{0x00,0x00},2,100);
connection.controlTransfer(0x21,0x01,0x0202,0x0500,new byte[]{0x00,0x00},2,100);
connection.releaseInterface(usbInterface);
connection.close();
I captured those addresses and commands on my USB port via wireshark, when I connect the headset to my Windows laptop and change the sidetone volume via setting. They works, as I can hear my voice in my headset.
But after I do that, other applications are not able to play sound on this device.
How can I change sidetone volume like showed above (or with other API in case I didnt know them) and still let the sound play properly?
Any protential help appreciated.

Buffering Issues Pi Pico with HC-05 Bluethooth Module

This is probably my misunderstanding of the Bluetooth SPP profile or even Bluetooth itself, but I am trying to get data transferred from an Android app to a Raspberry Pi Pico, and I can get it to work in some respect, however it seems to buffer the data randomly. The Android app sends a string every second and it seems to run OK some times, and then sometimes it pauses for some amount of seconds and then it catches up with all of the data. I have a subsequent issue that the readline doesn't read a line, it reads each character and the \n as well, but that's a side issue:
I have looked to see if there are any settings on the HC-05 to see if there's a buffer on that, and the only thing I can think of is upping the baud rate, but I don't see 9600 being an issue with so few characters.
It's almost acting like the pico isn't powerful enough.
The connection is made like this:
UUID BLUETOOTH_SPP = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(deviceAddress);
socket = device.createRfcommSocketToServiceRecord(BLUETOOTH_SPP);
socket.connect();
dataOut = new DataOutputStream(socket.getOutputStream());
Data is sent with this
dataOut.writeBytes("1"+speed.intValue()+"\n");
dataOut.flush();
With the receiver python code looking like this:
from machine import Pin, UART
bt_module = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))
while True:
if (bt_module.any()):
command = bt_module.readline()
print(command);

How to play audio through Bluetooth speaker even when headset is plugged in?

I have my phone connected to a Bluetooth speaker and the headphones plugged in. Now I'd like to play audio through the Bluetooth speaker.
When I set the audio stream to AudioManager.STREAM_MUSIC it just plays over the headphones.
It doesn't matter if it plays on the headphones as well but I need it to play on the Bluetooth speaker.
How is this possible? The app SoundAbout manages to do that so there must be a way.
EDIT: When I plug in the headphones and only afterwards connect to the Bluetooth speakers all audio plays through the Bluetooth speakers which I want. But I can't expect the user to find that out and before having to show them a complicated message I'd rather find out a way to make the sound always play through BT speakers when connected to some.
Thanks
(Note this is not the same question as this: How to Play audio through speaker even when headset is plugged in?
I want it to play on Bluetooth speakers, not on the integrated speaker of the phone.)
Solution
Suppose you already tested STREAM_RING on your new instance of media player and not directly setting stream type, and it didn't work out, You need a correct profile for your bluetooth device.
Take a look at this article
Read the "Implementing HAL" section, there is alot of source for different profile that you may be able to use.
There is also an easy solution which is to change your device profile to HEADSET in your getServiceConnected() method, it will turn into a Stay connected device but the output will become mono! As I recall, Which is a shame for speakers, A2DP also may not be supported in some hardwares and still interrupted by wire headsets.
I suggest to create a new profile and use it, a little bit tricky working with HAL but will worth it,
Sorry that I can not provide a source code for you at the moment.
If you have your routing logic within your application then based on that you can decide on which output the audio to be played.
I have a test app written for the exact purpose.
My Github Link
You can also route audio as you want based on a requirement.You can refer this github link for routing
Bluetooth connection may work with below state is true .
After receive BluetoothA2dp.STATE_CONNECTED, you can play music as normal.
Java Code Examples for android.bluetooth.BluetoothA2dp.STATE_CONNECTED
public BluetoothHandsfree(Context context, CallManager cm) {
mCM = cm;
mContext = context;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
boolean bluetoothCapable = (adapter != null);
mHeadset = null; // nothing connected yet
mA2dp = new BluetoothA2dp(mContext);
mA2dpState = BluetoothA2dp.STATE_DISCONNECTED;
mA2dpDevice = null;
mA2dpSuspended = false;
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mStartCallWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
TAG + ":StartCall");
mStartCallWakeLock.setReferenceCounted(false);
mStartVoiceRecognitionWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
TAG + ":VoiceRecognition");
mStartVoiceRecognitionWakeLock.setReferenceCounted(false);
mLocalBrsf = BRSF_AG_THREE_WAY_CALLING |
BRSF_AG_EC_NR |
BRSF_AG_REJECT_CALL |
BRSF_AG_ENHANCED_CALL_STATUS;
if (sVoiceCommandIntent == null) {
sVoiceCommandIntent = new Intent(Intent.ACTION_VOICE_COMMAND);
sVoiceCommandIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
if (mContext.getPackageManager().resolveActivity(sVoiceCommandIntent, 0) != null &&
BluetoothHeadset.isBluetoothVoiceDialingEnabled(mContext)) {
mLocalBrsf |= BRSF_AG_VOICE_RECOG;
}
mBluetoothPhoneState = new BluetoothPhoneState();
mUserWantsAudio = true;
mPhonebook = new BluetoothAtPhonebook(mContext, this);
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
cdmaSetSecondCallState(false);
if (bluetoothCapable) {
resetAtState();
}
}
please find below links : with sample codes it may help you.
Java Code Examples for android.bluetooth.BluetoothHeadset
Programmatically connect to paired Bluetooth speaker and play audio
You need to instantiate a new object of class MediaPlayer and use the following method on it
amediaplayer.setAudioStreamType(AudioManager.STREAM_RING)
Do not forget to check authorization to use bluetooth, you are unable to send anything to speaker via bluetooth without user privilege as you know.
Audiomanager overrides and routes audio to the latest connected device(either wired headset or bluetooth headset). In android, we do not have any option to override this setting unless it is a system app and route the audio wherever we wish to route. However, you can use reflection apis and override this setting. Audiomanager suspends bluetooth connection route(if already connected)if wired headset is connected and vice versa. You can look at the code here.
Hence using reflection apis you can toggle bluetooth audio route by invoking this method.

Access data from SCO Socket

I have 2 Android phones and I have managed to convert one of them as Headset (Yes, I did root the phone for that).
When an incoming call is received to the phone, the headset-emulated phone is able to take headset related actions like - pick call, disconnect call, etc. However, only functionality that's missing is the transfer of Audio from Phone to headset-emulated-device.
Does anyone have prior experience in establishing SCO connection between 2 android phones and access voice data ?
(As of now, I am not concerned of Sound quality).
I came across A2DP, but it's only uni-directional. Only SCO is bidirectional voice data transfer.
Any help or pointers will be highly appreciated.
I have done this with reflection. It only worked on certain devices though. Not all. Although I didn't root the device.
Class cls = Class.forName("android.bluetooth.BluetoothDevice");
Method method = cls.getDeclaredMethod("createScoSocket", (Class[])null);
BluetoothSocket scoSocket = (BluetoothSocket)method.invoke(device, null);
scoSocket.connect();
Also there is the AudioManager.startBluetoothSco() and AudioManager.setBluetoothScoOn(true) methods that you have to use when playing your audio.

How do i send information via a setup bluetooth connection

So im working around with bluetooth and trying to figure out how to send two strings via a bluetooth connection. From one android device to another.
I found this guide http://developer.android.com/guide/topics/connectivity/bluetooth.html
but it talks alot about setting up the connection. So i went straight down to the chapter about Managing a Connection. The reason i do this is that in the apps i create i plan to setup the bluetooth connection before opening the apps (via the phones usual bluetooth setup) and then open the apps and send when it is necessary.
So my question is how do i find the bluetooth socket that should be setup? Since that should be what im searching for to create the sending and recieving threads?
Hope this is enough information, else tell what more you need and ill try and answer to the best of my ability.
Best Regards Drakthal
The usual bluetooth setup only pairs between devices, it doesn't create a data connection between them (And even if it would, you wouldn't be able to access this Socket object because it's not created in your process).
After Bluetooth is turned on, you can call BluetoothAdapter.getBondedDevices() to get a set of the paired devices. You can then iterate over them, and initiate a connection to the one you want. You can't avoid the connection creation :( If you want a simplified example, you can look here (An answer I posted a while ago, regarding the whole pairing/connecting/sending/receiving subject with bluetooth).
Once you acquired an open connection, sending the 2 string is easy.
String s1 = "A", s2 = "B";
byte[] buf1 = s1.getBytes(), buf2 = s2.getBytes();
OutputStream os = connection.getOutputStream();
os.write(buf1);
os.write(buf2);
os.flush();
connection.close();

Categories

Resources