I am developing a voice chatting app based on webRTC using android libjingle.I want to reconnect users by using ice restart when they change their network from wifi to 4g or vice versa, or are disconnected. I have a question about implementing it by using libjingle. I will write down how to implement ice restart function based on what I understood so let me know there is anything wrong.
Q: As I understand, at first I need to set ice start option to be true in the MediaConstraints option without removing peer connection 객체 used for the first connection like below:
mediaConstraints.optional.add(new MediaConstraints.KeyValuePair("IceRestart", "true"));
Secondly, I need to update MediaConstrants using the peer connection 객체(used for the first connection)'s updateIce method like below:
peerConnection.updateIce(iceServers, mediaConstraints);
And finally is it right to send an offer, which is the same with basic webrtc network?
I want to double check whether I understand well. And if there is something wrong in what I've written, please let me know!!
For doing ice restart, sender should send SDP file with different ice-pwd or ice-ufrag.
IceRestart option forces PeerConnection to update those values.
Steps should be:
Put additional constraint:
cons.mandatory.add(new MediaConstraints.KeyValuePair("IceRestart", "true"));
Generate sdp file:
pc.createOffer(new WebRtcObserver(callbacks), cons);
Set resulted sdp to PeerConnection:
pc.setLocalDescription(new WebRtcObserver(callbacks), sdp);
Send it to remote peer.
So steps 2-4 are the same as for regular offer.
Related
So my android app is behaving as a beacon, means, it will be advertising and other BLE devices will be connecting to it. Well, this is how our project is working so please don't raise questions on this as why am i using my app as a beacon and not as a scanner. Anyways, It behaves as a beacon and starts advertising and now I want to know that if a device connected to it. I cant find a way how to do this.
Of course, I am using this flutter package. beacon_broadcast 0.3.0
This is my code.
void startAdvertising() {
BeaconBroadcast beaconBroadcast = BeaconBroadcast();
beaconBroadcast
.setUUID(advertisingUUID)
.setMajorId(1)
.setMinorId(100)
.start();
}
First, Flutter is just a UI toolkit and has no support for other system APIs such as Bluetooth.
You should therefore look what the official Android APIs offer in the first place. Usually when using BluetoothLeAdvertiser for advertising, one often also adds an instance of BluetoothGattServer in order to handle connections. If you have created a BluetoothGattServer using openGattServer, you will get a onConnectionStateChange callback whenever a device connects or disconnects. So that answers your question how an Android app can get notified when a device connects. You probably also want to use the same API to add a GATT service so that the other device can communicate with your app. Other alternatives is to use the GATT client API if it's the other device that has a GATT server, or you might want to use the L2CAP CoC API.
Note that if Bluetooth is turned off/disabled/restarted, your BluetoothGattServer object will automatically die and you need to recreate it. To get notified when this happens, use a state change intent receiver for BluetoothAdapter.ACTION_STATE_CHANGED as explained in this example https://stackoverflow.com/a/9694138/556495 to recreate your BluetoothGattServer (and advertiser) when state is changed to STATE_ON.
Now, since you want to use Flutter but Flutter uses Dart, you cannot directly consume the Android APIs. Instead you need to write a bridge/plugin, to bridge your Dart code and Java code. See https://docs.flutter.dev/development/platform-integration/platform-channels for a tutorial how to do this. If you're lucky, someone else might have already created such a package that does exactly what you want. Unfortunately, the beacon_broadcast package you found, only implements BluetoothLeAdvertiser and not BluetoothGattServer, as can be seen by the source code here: https://github.com/pszklarska/beacon_broadcast/tree/master/android/src/main/kotlin/pl/pszklarska/beaconbroadcast.
Background
A long time ago I was tasked with making a android app for the Wii Balance Board, after some screwing around I found that android no longer supported L2CAP. More research lead to understand that it was being re-added in Android 10. With Android 10 out I've been trying to give it a crack now.
Problem
So my simple goal at the moment is to create a connection with the Wii Balance Board.
My approach for connection is:
Start discovery
Add discovered bluetooth devices to list
When you click on a device it then tries to open a socket as such:
bluetoothSocket = btDevice.createInsecureL2capChannel(port);
As mentioned on the WiiBrew site I'm using psm value 0x13 for input and 0x11 for output.
I then use bluetoothSocket.connect and proceed to receive a IOException (timeout error)
I've also tried using both createL2capChannel and createInsecureL2capChannel with same results
I was able to successfully pair to the device using btDevice.createBond() and then using the phones BT address backwards for .setpin() and the Wii Balance Board simply acts as a "dumb" input device. (not sure if pairing is needed/good idea)
The above is a simplified flow of how I'm trying to connect. I've also tried using BalanceBoard.java from Paul Burton's fitscales repo updating all of the old bluetooth code, again I still get the timeout.
Have you looked at the bt_stack logs?
Here is mine from trying to open a socket with a wiimote:
04-05 12:25:04.949 E/bt_stack(4895): [ERROR:btif_sock_l2cap.cc(244)] SOCK_LIST: free(id = 4) - NO app_fd!
04-05 12:25:04.949 I/bt_stack(4895): [INFO:btsnoop.cc(323)] clear_l2cap_whitelist: Clearing whitelist from l2cap channel. conn_handle=65535 cid=65:0
04-05 12:25:04.949 E/bt_l2cap(4895): L2CA_FreeLePSM: Invalid PSM=19 value!
04-05 12:25:40.141 I/bt_stack(4895): [INFO:btsnoop.cc(323)] clear_l2cap_whitelist: Clearing whitelist from l2cap channel. conn_handle=1 cid=66:64
04-05 12:25:55.736 I/bt_stack(4895): [INFO:btsnoop.cc(323)] clear_l2cap_whitelist: Clearing whitelist from l2cap channel. conn_handle=2 cid=67:65
I believe this is where the problem lies, Im only a novice so Im not sure what can be done about it. I know the old ways of connecting passed the fd as a parameter to the bluetooth socket constructor but I dont think this is possible anymore
I used Linphone sdk to develop an android SIP phone, every thing is good but on some wifi network cant receive call and server return USER_NOT_REGISTERED error.
for example :
at first after registration:
User A and user B can make call to each other successfully.
after about ten minute, when user A make outgoing call to user B , server say user B in not registered and wise versa.
User A and B is registered because can hear server message.
server is asterisk.
I repeat this test with csipsimple and it work without problem.
my app now is complete and port it to csipsimple is not easy.
is there any way to fix it?
No, there are no even moderate complexity way fix it.
That is internal issues in registration on linphone. It is common and well-known at least 5 years, but linphone dev team not care much.
You can try fix linphone core, or just use sip ping(asterisk qualify= option) in attempt to not loose connection.
You can try the enableKeepAlive set to true after the creation of the core.
Core core;
core = Factory.instance().createCore(......);
core.enableKeepAlive(true);
im trying to control a bluetooth bracelet with vibration function via HFP (hands free profile) in Android. I've been able to connect to the bracelet and access the input- and outputstream.
My goal is to simulate an incoming call so that the bluetooth bracelet starts vibrating (which seems to be the only way to do that). To do this, im using AT commands. In the bluetooth specs at https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=238193 on page 22 you can see the handshake to establish service level connection.
I need to establish this connection to use the "+CIEV" command (see handshake page 48).
But when my bracelet returns the command "AT+CIND=?" I dont know how to respond. I can't find any hints on how to answer with the "CIND:" command. Also I dont know how to send the acknowledgement (is it just "OK"?).
That might even be the completely wrong way to do this. Every suggestion is appreciated. I only found one post on stackoverflow that helped me in some way, rest of the posts I found were unanswered.
By the way, im using a smartphone with Android 4.1.2. The bracelet supports HFP and HSP. Thanks in advance.
UPDATE 10/29/2014
===== Connection through RFCOMM Socket established at this point =====
// read AT+BRSF=0 from device
byte[] buffer = new byte[200];
mBluetoothSocket.getInputStream().read(buffer);
Log.d(TAG, new String(buffer).trim());
//write answer BRSF: ...
mBluetoothSocket.getOutputStream().write("+BRSF=20\r".getBytes());
mBluetoothSocket.getOutputStream().write("OK\r".getBytes());
// read AT+CIND=? command
buffer = new byte[200];
mBluetoothSocket.getInputStream().read(buffer);
Log.d(TAG, new String(buffer).trim());
//write answer CIND: ...
mBluetoothSocket.getOutputStream().write("+CIND: (\"battchg\",(0-5)),(\"signal\",(0-5)),
(\"service\",(0,1)),(\"call\",(0,1)),(\"callsetup\",(0-3)),
(\"callheld\",(0-2)),(\"roam\",(0,1))".getBytes());
mBluetoothSocket.getOutputStream().write("OK".getBytes());
// read AT+CIND?
buffer = new byte[200];
mBluetoothSocket.getInputStream().read(buffer);
Log.d(TAG, new String(buffer).trim());
Following the procedure of the protocol, I should receive the "AT+CIND?" command and then I could send the command "+CIND: 5,5,1,0,0,0,0", but...I dont receive the "AT+CIND?" command. Actually im not receiving anything. Am I missing something? Sending an "OK" doesnt change anything btw...
I was fiddeling with exaclty the same problem. After days of trial and error, I finally got it to work.
I think it depends on the speed at wich you answer the HF's commands, as well as on the correct line-endings ("COMMAND").
Here is my DroidScript which works. It's not cleaned up, but it works.
https://gist.github.com/t-oster/68a568ac4c4e133f67ac
Also, the one example I found that seemed to almost work, it's expecting the responses to be top and tailed with crlf:
"\r\n+BRSF=20\r\n"
"\r\nOK\r\n"
Still struggling with the rest of it myself.
refer to bluetooth hfp 1.5 spec in which you can understand CIEV response
normally when not in any call setup, response can be +CIND = 1,0,0,0,5,0,5
Note these values are based on the hfp spec, on incoming call return +CIEV: ,
ind- indicator for callsetup and value as 1 and then RING commands to the bracelet
Alright here's the deal. I got two Galaxy Nexus phones both with bluetooth enabled.
I've written a bluetooth connection management app that I use for device discovery and connectivity. It also outputs all the available UUIDs the devices can support.
Looking from http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm the following standard UUIDs are exposed from Galaxy Nexus devices.
0x1116 - NAP
0x112f - PBAP (Phonebook Access Profile)
0x111f - HFP (Hands free)
0x1105 - OPP (Object Push Profile)
0x1112 - HSP (Headset Profile)
0x110c - AVRCP
0x110a - A2DP
I am trying to connect via the OPP profile (UUID 00001105-0000-1000-8000-00805F9B34FB) and push objects (files) between the devices. I've gone though the entire Android API documentation on how to discover, pair/bond (threading etc.) and manage all bluetooth connections. I've managed to successfully connect and talk to a legacy board device via the SPP (0x1101) profile.
However, when I try to use socket.connect() between the two galaxy nexus phones, the pairing dialog shows up and I click Pair button on both devices. After that, I immediately get a Connection Refused IOException. Note that after pairing has occurred once I never get asked again which makes sense since the secure link is cached.
If I can't connect to these standard profiles using these standard UUIDs why are they exposed? How can I connect from my app to any of these profiles and interact with them? Is it because my app is not somehow trusted? What's weird is that even the Share functionality on Android does not work at all either. Is this something completely broken on Android?
Please avoid giving me hints to use the "well known UUID SPP one 0x1101" like the docs say. This is not what I want. I have a fairly good understanding of how this stuff works and I am looking for a real solution or explanation of the problem.
I've seen the typical "reflection" solution but I do not understand why is this still a problem on Android? Why do people use reflection to make this work? Can we file a bug on Android to fix this?
If those UUIDs are standard any app should be able to connect and interact with them. Why is this an issue and why do I get this exception?
Thanks in advance.
UPDATE
So for some reason the object push in the Android system started working. I actually attempted to connect via my app and it was not working. Then, I went to the Contacts app and tried to share a contact which magically worked. Then, I went back to my app and it now it works...wow. That is very weird and there must be an explanation to this.
I ran into this same issue and managed to find a solution that worked for me.
In my case I using three different test devices (Nexus 5, Galaxy S4, Note 2) and for some reason, the Note 2 wouldn't connect to my Bluetooth module yet the other two would.
The reasoning I've found is that Bluetooth drivers vary, and slightly different connection methods are needed to create a connection between different devices.
The three methods I use are called 'Secure', 'Insecure' and 'Reflection method'/'hax'.
switch(connType)
{
case Secure:
tmpSocket = device.createRfcommSocketToServiceRecord(_uuid);
break;
case Insecure:
tmpSocket = device.createInsecureRfcommSocketToServiceRecord(_uuid);
break;
case Hax:
Method createSocket = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
tmpSocket = (BluetoothSocket)createSocket.invoke(device, Integer.valueOf(1));
break;
}
In my case, the Secure mode worked for both the Nexus 5 and Galaxy S4 however it didn't work for the Note 2.
After some testing I discovered the Note 2 only works using 'Insecure' mode, so to cater to this, I basically attempt a connection and cycle through the different modes if necessary. When attempting a different connection mode I simply prompt 'retrying connection'. So, if the connection fails using secure, then I will attempt using Insecure and then using the reflection method.
I haven't run into the case where one of these three methods haven't worked.
Have you tried using a nonstandard profile? i.e. a custom UUID just for your app. This will also help you know your are (most likely) only connecting to your own app rather than some other app that is registered with the same profile.
From my experience, Bluetooth pairing is very buggy for the first pair attempt. However, using a custom UUID helps this somewhat.
The reflection method (I think) was originally an attempt to fix a bug with a specific device, however I think some people found success in using it elsewhere as well. The device was called the Spica or something similar.
As one of the comments also posted, I would also try connecting again after failing.
Basically write code that plans to fail the first attempt, but then the code tries to connect again in 5 seconds if there was a failure.
These are imperfect solutions but Bluetooth implementation on Android is also imperfect (IMHO). Hope that helps
EDIT
Based on the question update and comments:
I agree something is definitely buggy. Part of the problem I think is the BT drivers vary and each has a different BT stack with different quirks. I also found a question that makes use of both the reflection method AND custom UUID, AND other standard methods. This seems extreme to me but it does cover the most ground. Unfortunately as app developers we have no control over the low level stack/code/drivers.
I have found with my two Bluetooth sharing apps that the first pairing is always tricky.
I'm glad to know it's not just me.