Android : Audio call using rtpstream - android

I want to develop an application that enables the users to do real time audio chatting with each other. I am using rtpstream to implement this. Following is my code. I am using two phones to test my application. The port number to the audio stream is assigned on run-time randomly. This means I have to send the port number from Phone 1 to Phone 2 on run-time to establish a connection.The problem here is that the communication is only one-sided i.e. Phone 1 can talk to Phone 2 but cannot hear Phone 1's reply. What should I do to make it two sided? Also is there any way to assign the port number to audiostream manually? Any help will be appreciated.
audioGroup = new AudioGroup();
audioGroup.setMode(AudioGroup.MODE_NORMAL);
audioStream = new AudioStream(InetAddress.getByAddress(MyIP));
PORT = audioStream.getLocalPort();
audioStream.setCodec(AudioCodec.PCMU);
audioStream.setMode(RtpStream.MODE_NORMAL);
audioStream.associate(InetAddress.getByAddress(ReceiverIP), PORT);
audioStream.join(audioGroup);
AudioManager Audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
Audio.setMode(AudioManager.MODE_IN_COMMUNICATION);

The right way to do this is to setup RTP Stream first then get the port number on which stream is listening and then send that port in the SDP part of SIP INVITE. Take a look at this example https://github.com/Mobicents/restcomm-android-sdk/tree/master/Examples/JAIN%20SIP

I'm trying to accomplish the same , one possibility is for user1 to share his ip with the user2. Both users can create a audiogroup and and audiostream . the audiostream joins to the other user's audio group.

Related

Show Title (not song or artist but active SIP conversation) on Bluetooth CarKit from Android

So I'm currently developing a SIP dial app and I was wondering how I could change the displayed information on a Bluetooth CarKit. I route the audio to the carkit using :
AudioManager localAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
localAudioManager.setMode(0);
localAudioManager.setBluetoothScoOn(true);
localAudioManager.startBluetoothSco();
localAudioManager.setMode(AudioManager.MODE_IN_CALL);
And I am wondering: How am I able to set the caller info on the bluetooth device? I wasn't able to find this anywhere on SO. To be extra clear this is what I see during an active conversation:
I also use a library for SIP conversations called PortSIP. Maybe they have influence on what to display? I don't know. Any ideas are welcome. I've already tried searching on options for AudioManager, the only option I can imagine that leaves room for metadata is audioManager.setParameters(), but I can't find what the possible key value parameters are for this function.
Update: Also tried to show info like trackinfo, but still didn't succeed. This is the code I've tried:
Intent intent = new Intent("com.android.music.metachanged");
intent.putExtra("track", "test");
intent.putExtra("artist", "atest");
intent.putExtra("album", "btest");
context.sendBroadcast(intent);
I found a post that explanes how to send metadata information from your phone to a connected audio bluetooth device.
If you just want to send metadata information from your phone to a connected AVRCP compatible audio bluetooth device and DON'T want to control your app from the bluetooth device at all, check the post below.
This is the post

Broadcast audiostream to multiple devices

I am using android AudioStream to communicate between 2 android devices on wifi, both ways. Is there any way to broadcast an audio message on multiple devices, in the same time ?
Is using multiple AudioStreams, one for each device, a possible way? I need to broadcast to 40 receivers. Will the message be delayed if I use multiple AudioStreams ?
Do you know other solutions ?
I think the simplest way is to stream all devices using AudioGroup, you just need to create separate AudioStream for each clients and join them to one AudioGroup. That is it.
AudioGroup audio = new AudioGroup();
audio.setMode(AudioGroup.MODE_NORMAL);
AudioStream stream1 = new AudioStream(yourLocalIP);
stream1.setCodec(AudioCodec.PCMU);
stream1.setMode(RtpStream.MODE_SEND_ONLY);
stream1.associate(firstClientIP, anyport);
stream1.join(audio);
AudioStream stream2 = new AudioStream(yourLocalIP);
stream2.setCodec(AudioCodec.PCMU);
stream2.setMode(RtpStream.MODE_SEND_ONLY);
stream2.associate(secondClientIP, anyport);
stream2.join(audio);

Receive audio via Bluetooth in Android

I want to create an Android application that is capable of receiving an audio stream. I thought of using the A2DP profile, but is seems as if Android doesn't support A2DP sink. Looks like there are a lot of people that's searching for a solution for this problem. But what about receiving an ordinary bit stream, and then convert the data into audio in the application? I was thinking of receiving an PCM or Mp3 data stream via the RFCOMM (SPP Bluetooth profile), and then play it using AudioTrack.
First, how do I receive a bit stream on my Android phone via the RFCOMM? And is it possible to receive a bit stream via RFCOMM as a PCM or Mp3 stream?
Second, if it isn't possible to receive a bit stream via RFCOMM as a PCM or Mp3 stream, how do I convert the received bit stream into audio?
Third, how do I convert the received data into audio AND play the audio simultaneously, in "real time"? Can I just use onDataReceived?
To be clear, I'm not interested of using the A2DP profile! I want to stream the data via the RFCOMM (SPP Bluetooth profile). The received data stream will be in PCM or Mp3. I thought of writing my own app, but if anyone knows of an app to solve this I'd be glad to hear about it! I'm using Android 2.3 Gingerbread.
/Johnny
No. Trying to write an Android application that handles this will not be the solution. At least if you want to use A2DP Sink role.
The fact is that Android, as you mentioned it, does not implement the API calls to BlueZ (the bluetooth stack Android uses till Jelly Bean 4.1) regarding A2DP sink capabilities. You have to implement them yourself. I will try to guide you, as I was also interested in doing this my self in the near past.
Your bluetooth-enabled Android device is advertising itself as an A2DP source device by default. You have to change this first, so nearby devices may recognize your device as a sink. To do this, you must modify the audio.conf file (usally located in /etc/bluetooth/) and make sure the Enable key exists and the value Source is attached to this key, so you will get something like :
Enable=Source
Reboot, nearby devices should now recognize your device as an A2DP sink.
Now you will have to interact with BlueZ to react appropriately when an A2DP source device will start to stream audio to your phone.
Android and BlueZ are talking to each other via D-BUS. In fact, Android connects to the DBUS_SYSTEM channel and listens to every BlueZ advertisement, such as events, file descriptors ...
I remember having successfully bound my self using a native application to this d-bus channel and got access to the various events BlueZ was posting. This is relatively easy to achieve using as reference, the BlueZ API available here. If you go this way, you will have to build a native application (C/C++) and compile it for your platform. You must be able to do this using the Android NDK.
If you find it difficult to use D-BUS, you can try this Java library I just found that handles the communication to D-BUS for you : http://jbluez.sourceforge.net/. I have never used it but it is worth a try in my opinion.
What you really have to do is find out when an A2DP source device is paired to your phone and when he starts to stream music. You can retrieve these events through D-BUS. Once somebody will try to stream music, you need to tell BlueZ that your native application is going to handle it. There is a pretty good document that explains the flow of events that you should handle to do this. This document is accessible here. The part you're interested in comes on page 7. The sink application in the given example is PulseAudio but it could be your application as well.
BlueZ will forward you a UNIX socket when you will call the org.bluez.MediaTransport.Acquire method. Reading on this socket will give you the data that are currently streamed by the remote device. But I remember having been told by a guy working on the BlueZ stack that the data read on this socket are not PCM pure audio, but encoded audio content instead. The data are generally encoded in a format called SBC (Low Complexity Subband Coding).
Decoding SBC is not very difficult, you can find a decoder right here.
The ultimate step would be to forward the PCM audio to your speakers.
To prevent you from getting stuck and in order to test your application in an easier manner, you can use the d-bus binary that should be available on your Android system. He is located in /system/bin.
Quick tests you can make before doing anything of the above might be :
Get Devices list :
dbus-send --system --dest=org.bluez --print-reply /
org.bluez.Manager.GetProperties
This returns an array of adapters with their paths. Once you have these path(s) you can retrieve the list of all the bluetooth devices paired with your adapter(s).
Get paired devices :
dbus-send --system --print-reply --dest=org.bluez
/org/bluez/{pid}/hci0 org.bluez.Adapter.GetProperties
This gives you the list of paired devices whithin the Devices array field.
Once you have the list of devices paired to your Bluetooth Adapter, you can know if it is connected to the AudioSource interface.
Get the devices connected to the AudioSource interface :
dbus-send --system --print-reply --dest=org.bluez
/org/bluez/{pid}/hci0/dev_XX_XX_XX_XX_XX_XX
org.bluez.AudioSource.GetProperties
org.bluez.Manager.GetProperties
Hope this helps.
Another work around is using HandsFreeProfile.
in Android, BluetoothHeadset is working on that.
Wait until status changed to BluetoothHeadset.STATE_AUDIO_CONNECTED.
then you can record audio from bluetooth headset.
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setOutputFile(mFilename);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mMediaRecorder.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mMediaRecorder.start();
[Irrelevant but works] This hack serves only mp3 streaming via WIFI hotspot (I use it in my car which has only AUX input):
Install the app AirSong,
Turn on wifi hotspot,
Connect the other device to that hotspot,
Access 192.168.43.1:8088 from the device's browser and you are on.
(wondering why "192.168.43.1" only? because thats the default gateway of any device connected to Android Hotspot)
audio.conf seems to be missing in Android 4.2.2?
To receive pcm audio stream via rfcomm , you can use code flow as a hint explained (Reading Audio file in C and forwarding over bluetooth to play in Android Audio track) , with a change . change freq used while initializing from 44100 to 22050
AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,22050,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_8BIT,10000, AudioTrack.MODE_STREAM);
note:This streaming still consists some noise but your
"receiving an PCM data stream via the RFCOMM (SPP Bluetooth profile), and then play it using AudioTrack."
will work.

How to capture or reroute navigation voice stream

There is a problem when using Google Navigation on Android with a Bluetooth device. Navigation sends the audio for the turn-by-turn instructions over the A2DP stream. I have a Motorola T605 Bluetooth car kit and it supports HFP and A2DP. I often just listen to the old fashioned car radio though. In this scenario I never hear turn-by-turn directions because my live A2DP stream is being sent to the radio AUX input but I am listening to the radio instead. My app has a feature where it reads out SMS messages to me. I have it set up so you can pick the stream you want to use for this. I prefer using AudioManager.STREAM_VOICE_CALL since it uses a dedicated separate speaker on the T605.
I have looked into a few ways to handle this:
1) Reroute notifications to Bluetooth SCO instead of A2DP. I have not fund a way to do this. I am able to send TTS messages I create over this path and it works great (I have an SMS reader built into my app). I tried activating SCO but the turn-by-turn instructions stream moves to the phone internal speaker instead of the voice call stream like I would prefer.
2) Capture the navigation messages and echo them back over the SCO path. I can't find a way to intercept or capture the navigation stream though. Does Google Navigation use the TTS engine or its own methods to create the voice output? It would be great to just get the directions in a text string since I could easily send that to the TTS engine and route it where I want like I do with SMS strings.
You can see my app source here: http://code.google.com/p/a2dpvolume/
Any thoughts?
Unfortunately I think you're SOOL when it comes to rerouting the navigation messages to BT SCO. I would expect the navigation app to use either the TTS or NOTIFICATION stream type to play the messages, and both of those stream types follow the MEDIA routing strategy (for NOTIFICATIONs that is at least typically true when there's no active voice call).
Although the behavior is up to each vendor to decide, my guess is that you'll find that in most implementations streams that follow the MEDIA routing strategy won't ever be routed to BT SCO, except during an ongoing voice call that is routed to BT SCO.
The best you could do in terms of routing is to force the routing to the loudspeaker, or to "anything but A2DP" (which means wired headset if one is attached, or the loudspeaker otherwise).
Here's how you could do that (I haven't verified that this works on every phone out there):
Class audioSystemClass = Class.forName("android.media.AudioSystem");
Method setForceUse = audioSystemClass.getMethod("setForceUse",
int.class,
int.class);
// 1 == FOR_MEDIA, 10 == FORCE_NO_BT_A2DP (FORCE_SPEAKER would be 1).
setForceUse.invoke(null, 1, 10);

How to make Android phone as a bluetooth headset?

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...

Categories

Resources