How to switching audio between Bluetooth audio devices on android using programmatically - java

It's let me confused for a long time.
I have two bt audio devices connected on android phone, and I want to switch specific bt audio device using programmatically.
I search keyword about a2dp, media router and audioManager than seems can't do this thing...
I only way found the function is:
BT devices=> A and B connected on an Android phone.
And right now the media play to A and I want to switch to B
Step1: A, B unpair on Android phone.
Step2: A pair on Android phone.
Step3: B pair on Android phone.
The media play output is B,
seems lastest pair Bluetooth device is media play output.
Can anyone give me some advice or direction?
Thanks, guys

Documentation says it can only be connected to a single A2DP device at a time, so you should be able to switch between devices by connecting to device you want to use.
You can connect to device by using BluetoothSockets.
EDIT:
I found other solutions, one which I find reliable. Both of them rely on method reflections.
First one is from this post.
1. Get BluetoothA2dp proxy from serviceListener
bluetoothManager.adapter.getProfileProxy(this, serviceListener, BluetoothProfile.A2DP)
private val serviceListener = object : BluetoothProfile.ServiceListener {
override fun onServiceDisconnected(profile: Int) {
if (profile == BluetoothProfile.A2DP) {
bluetoothA2dp = null
}
}
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile?) {
if (profile == BluetoothProfile.A2DP) {
handler.post(btSearchRunnable)
bluetoothA2dp = proxy as BluetoothA2dp
}
}
}
Get "connect" method from reflection.
private val connect = BluetoothA2dp::class.java.getDeclaredMethod("connect",BluetoothDevice::class.java)
Invoke method with proxy as first argument and device as second.
connect.invoke(bluetoothA2dp,device)
Other method used reflection to get createRfcommSocket to circumvent issue with one parameter which you can't normally access. I can post link to it, but problem I had with it is that always lagged main thread, always threw me an error and connected unpredictably.

Related

Is it possible to identify the USB communication mode programatically?

Is there a way to programatically identify the currently USB working mode?
I mean, some function that would return either if the device is at Host, Device or Accessory mode.
Not the best answer, but once you have a UsbManager you might be able to figure it out. Usually this UsbManager is created using a Context I believe, but it looks like you are switching modes so you hopefully can get a UsbManager instance, m in this case:
UsbManager m = createManagerSomehow
For accessory mode, this only has one callback. If this returns one then you know it is Accessory.
m.getAccessoryList()
So I'm thinking somehting like this might work:
if(m.getAccessoryList().size() > 0)
accessoryMode = true;
And for Host, if you have a UsbDevice device, or String deviceName you could use the same UsbManager m function to see if it contains that device.
if(m.getDeviceList().containsValue(device))
hostMode = true;
or
if(m.getDeviceList().containsKey(deviceName))
hostMode = true;
and I don't know about what Device is, but if none of the above are true then you know it is just a Device. You don't really need this boolean variable below, because you have the other two. It's just here to help with my explanation via state logic.
if(!hostMode && !accessoryMode)
deviceMode = true
Hope this helps. Check out UsbManager for more documentation and just search the page for Host and Accessory.
http://developer.android.com/reference/android/hardware/usb/UsbManager.html
NOTE: I am a little confused when you say you switch the modes in your comment. It conflicts with the Accessory call I make above and might not work, but what I would do then (if you don't need deviceMode) then just check if the usb device is a HOST mode and if not you know it is in application mode...

Java desktop bluetooth client can not find services

I am new to bluetooth programming, so please keep that in mind.
I am trying to connect to a pulse sensor from a desktop pc, specifically the Zephyr HxM BT. I am not using any device specific drivers, the Java bluetooth library I'm using is Bluecove, and my bluetooth stack is BlueSoleil.
From my understanding, the way I proceed is
1) Scan for BT devices
public void startSearch() throws BluetoothStateException{
System.out.println("Inquiry started");
localdevice.getDiscoveryAgent().startInquiry(DiscoveryAgent.GIAC, this);
}
This works fine, it discovers my pulse belt and calls
public void deviceDiscovered(RemoteDevice arg0, DeviceClass arg1)
2) Search a device for services
Once a device has been discovered, it should be added to the DiscoveryAgent's list of cached devices, this is my first problem as the cache (and preknown devices) is always empty even though I've discovered my belt.
So the way that I do this now is to either keep my own list of devices, or simply start a service search directly from deviceDiscovered.
I am still a bit unsure if I'm using the correct parameters, but from reading the BT device manual and the javax.bluetooth documentation on DiscoveryAgent.searchServices:
public int searchServices(int[] attrSet,
UUID[] uuidSet,
RemoteDevice btDev,
DiscoveryListener discListener)
throws BluetoothStateException
My code:
public void searchServices(RemoteDevice device){
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID("1101",false); //Serial Port
System.out.println("Searching for services on " + device.getBluetoothAddress() );
try{
agent.searchServices(null,uuidSet, device,this);}
catch (BluetoothStateException e){
System.out.println("BluetoothStateException caught.");
}
}
I've set the attributes parameter to null, because the documentation states that this will have it search for services with the default attributes, however I've also tried to use only ServiceID (0x0003) as attribute with no luck.
This is where I'm stuck, I pass the correct BT device into the function, and it starts searching but never give me any results, it just searches forever for all I know, no exception, no calls to
public void servicesDiscovered(int arg0, ServiceRecord[] arg1)
or
public void serviceSearchCompleted(int arg0, int arg1)
So I guess my questions are:
- Am I doing something wrong? Any suggestions?
- What are the other approaches to connecting to a BT device, and what
information do I have to know about the device to do that?
Here is some information that I think is relevant from the device manual:
The following steps have to be undertaken to connect to a HxM device.
1) Activate the Bluetooth service of the device/computer wanting to connect to the HxM
2) Scan for Bluetooth devices in range
3) Pair with the HxM device found in range
4) Discover Services of Paired HxM
5) Connect to serial port of HxM device
The diagram above shows that the Bluetooth HxM typically communicates with a mobile device over the Bluetooth
link. The HxM only supports one link at a time and uses the Bluetooth SPP (Serial Port Profile) to communicate
with other devices with the following low-level protocol:
• 115,200 baud
• 8 data bits
• 1 stop bit
• No parity
Any suggestions are very much appreciated
edit: I just want to add that I'm testing the code with a console input loop, so the program is not immediately terminated after calling searchServices, it should have time to complete unless I'm misunderstanding async tasks
I just wanted to update this and say that I found the problem, it seems that I had to use a short UUID instead of a long. I should have tried both of these options before I deemed myself stuck, but I didn't think it would make any difference.

Bluetooth android server client with a headset

I'm trying to create a server on android that will listen on incoming connections ,such as a specific headset i have.
I've read many tutorials, posts in StackOverflow and the one from Android|Developer , and i don't seem to understand a few things .
1) UUID , is it a specific address for each Bluetooth device ? or is it a shared key that need to be in the server and the client in order to create a connection ? my guess is the latter cause there the MAC address as well ...
2) When i pair my Headset with my phone , does the headset saves the MAC\UUID of the last paired device ?
3) Does the Bluetooth chips even works in that way ? The phone connects immediately to a paired device as it turned on, So my guess is that it opens a Socket for each paired device and waits for it to turn on , is that true ?
4) Is it possible to accomplish what im trying ? Meaning creating a BluetoothServerSocket that will accept a connection from the head set ?
code example for the server side:
//This may b needs to be the UUID of the headset ? or special one ? or what ?
UUID myUUID = UUID.fromString("0000111e-0000-1000-8000-00805f9b34fb");
private final BluetoothServerSocket mServerSocket;
private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(Activity.APP_NAME, myUUID);
mServerScooket = tmp;
//Im hoping that this will block until the specific headset will be turned on
socket = mServerSocket.accept();
Thanks in advance.
1) UUID ,is a specific ID for Bluetooth communication. When you create your bluetooth socket in Android, listenUsingRfcommWithServiceRecord(Activity.APP_NAME, myUUID); ask Android to redirect bluetooth connection which match with the UUID to your app.
2) I'm not sure. It depends on the type of connection the headset can make. When you want to use it, do you need to select it in Android, or you can just put it and it works ?
3) I don't know. But you can have a look to Android source code ;)
4) If the bluetooth headset can create a connect socket, yes, it is possible
Hope this helps ;)
1) yes UUID is specific to each device and in order to connect to a device you need to have its UUID.
as shown in the Bluetooth chat example by Android SDK
2) depends on the hardware for example
chip sets like the HC-06 does saves the last paired device UUID
while the HC-05 dose not ...
3) The headsets that Ive tested (Samsung made) Acts as a server.
so by initiating a BluetoothSocket with the UUID of the headphone u can connect to it.
4) Yes it is possible to connect to a Bluetooth head set answered in the post : Using the Android RecognizerIntent with a bluetooth headset
Special notes :
Best way to listen to oncoming connections without any wakelocks that I found is by registering the BluetoothDevice.ACTION_ACL_CONNECTED Broadcast and check the name\mac\UUID of each incomming connection.
Thanks to Hoan Nagayu for the help.

Android use device flash as torch

There is a need to use the built in device camera flash as a torch.
Unfortunately I don't have access to an Android device so I can only use the Android emulator.
How can I validate that my code does work?
I have been trying several times to update my app with different ways to access the camera flash and each time the app was crashed.
My app minimum OS version is 2.2,
At the moment I'm using the following code
private void turnFlashOn() {
camera = Camera.open();
Parameters p = camera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
}
private void turnFlashOff() {
camera = Camera.open();
Parameters p = camera.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
}
Haven't tested it yet.
What is your way to use the camera flash?
Thanks!
The first two errors here is that you have called Camera.open() twice and never close it. You need to open it in onResume() and close it in onPause(), and in between operate on the Camera handle you obtained.
You can debug on emulator and mock camera class (with jmockit) , but you will have to be careful - not every camera on real devices supports torch mode ( or have a flash at all) - so you will have to check whether camera object supports this.
Once you got your code working correclty, you will still have to test it on real device
( hint: you can recruit testers on android developers mailing lists if you ask politely and provide signed APK somewhere on the web so people can install it )

USB Communication, Endpoints in Monodroid/Android

I have a USB device that I'm attempting to communicate to with my Android 4.1 device using the MonoDroid API, and I've run into some issues setting up a proper connection. First, the steps taken to arrive at what I "think" may be an issue:
Filter my device by vendor and product ID with an intent filter in
my AndroidManifest file. This works well, as when I plug in my
device my app requests to launch by default, so permissions should
correct.
Grab my USB device from an Activity that my intent filter sends the program after discovering said device: UsbDevice device = (UsbDevice)this.Intent.GetParcelableExtra(UsbManager.ExtraDevice);
After checking that there is only one interface present, I grab the associated interface by issuing: UsbInterface intf = device.GetInterface(0);
Check the number of endpoints and grab them. There's 2, as this is an input and output device: UsbEndpoint endpoint_IN = intf.GetEndpoint(0);
UsbEndpoint endpoint_OUT = intf.GetEndpoint(1);
Grab a connection to the device using the UsbManager: UsbDeviceConnection connection = device_manager.OpenDevice(device);
However, and I noticed that the endpoint at index 0 of the interface (endpoint_IN above) has UsbAddressing enumeration type "DirMask", where endpoint_OUT has type "Out"; I'd expect endpoint_IN to be "In", which is not the case. What is "DirMask?" The inline documentation states "Documentation for this section has not yet been entered", and the online docs reflect the same: http://api.xamarin.com/?link=T%3aAndroid.Hardware.Usb.UsbAddressing
Could this be my issue? I'm just not really sure. I tried to implement the rest of the communication procedure, but haven't been able to yield any results. For example, the following code should input a command to receive one reading:
Byte[] sys_command = Encoding.ASCII.GetBytes("!001:SYS?\r");
Java.Nio.ByteBuffer sys_command_buffer = Java.Nio.ByteBuffer.Wrap(sys_command);
Java.Nio.ByteBuffer output_buffer = Java.Nio.ByteBuffer.Allocate(4);
UsbRequest request_out = new UsbRequest();
request_out.Initialize(connection, endpoint_OUT);
connection.ClaimInterface(intf, forceClaim);
request_out.Queue(output_buffer, 4);
connection.BulkTransfer(endpoint_IN, sys_command, sys_command.Length, TIMEOUT);
if (connection.RequestWait() == request_out)
readings.Text = output_buffer.GetFloat(0).ToString();
Any insight?
I had the interface endpoints backwards, all things considered. That is, I was attempting to read/write to the wrong interface.
In case anyone else stumbles on this, the DirMask type means look at the Direction attribute of the endpoint instead of the Type attribute. If the Type is DirMask, the Direction could be UsbAddressing.In or Out.
And the Direction of In is the out endpoint, and vice versa (which I'm guessing is why you had them backwards).

Categories

Resources