Goal: open a bluetooth socket to a currently connected A2DP device, when I know it is connected.
In order to connect the socket, I need the MAC address of this device.
As i currently understand, there is 2 kinds of listener to get the bluetooth state:
1- BluetoothAdapter.getProfileProxy() as described here How to get bluetooth connected devices using BluetoothHeadset API
triggers when bluetooth card is ON / OFF.
allow to get a specific bluetoothProfile (A2DP for example), then the list of the connected devices to this profile, then the mac address of this connected devices.
the device list is ever empty when "onServiceConnected" is called (devices need more time to connected after the bluetooth card startup). So I need to call it after the device connection.
2- A broadcast receiver on BluetoothDevice.ACTION_ACL_CONNECTED as described here How to programmatically tell if a Bluetooth device is connected? (Android 2.2)
triggers when bluetooth device is connected / disconnected.
do not allow to get any information of this device
So I need to use both of them to trigger when A2DP device is connected... and so get the MAC address of this device (then open the btSocket):
Start the btAdapter.getProfileProxy inside the BroadcastReceiver "BluetoothDevice.ACTION_ACL_CONNECTED", but with a 3 seconds delay to allow it to connect.
It is the only (complicated) way to do that?
onCreate{
context.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));
context.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
Log.d(TAG, "Action received\n");
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action))
{
Log.d(TAG, "ACTION_ACL_CONNECTED received\n");
timerHandler.postDelayed(timerRunnableBtConnection, 3000);
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action))
{
Log.d(TAG, "ACTION_ACL_DISCONNECTED received\n");
btAdapter.closeProfileProxy(BluetoothProfile.A2DP, btA2dp);
}
}
private Runnable timerRunnableBtConnection = new Runnable() {
#Override
public void run() {
btAdapter.getProfileProxy(intelloApplication.getAppContext(), mProfileListener, BluetoothProfile.A2DP);
}
};
};
// Define Service Listener of BluetoothProfile
// then create the btSocket on it
private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.A2DP) {
Log.d(TAG, "Bluetooth connected\n");
btA2dp = (BluetoothA2dp) proxy;
List<BluetoothDevice> devices = btA2dp.getConnectedDevices();
Log.d(TAG, "List of " + devices.size() + " device\n");
for ( final BluetoothDevice dev : devices ) {
String address = dev.getAddress();
Log.d(TAG, "Name: " + dev.getName() + " and address: " + address + "\n");
btDevice = btAdapter.getRemoteDevice(address);
try {
btSocket = createBluetoothSocket(btDevice);
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
Log.d(TAG, "...Connecting...");
try {
btSocket.connect();
useBluetooth = true;
Log.d(TAG, "....Connection ok...");
} catch (IOException e) {
try {
btSocket.close();
useBluetooth = false;
Log.d(TAG, "....Close connection.");
} catch (IOException e2) {
Log.d(TAG, "Unable to close socket during connection failure");
Log.d(TAG, e2.getMessage());
}
}
// Create a data stream so we can talk to server.
Log.d(TAG, "...Create Socket...");
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
}
}
}
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.A2DP) {
Log.d(TAG, "Bluetooth disconnected\n");
}
}
};
Related
I am working on to establish a message communication between UWP Application on desktop and the Hololens 1.
According to the implementation of Websockets from Microsoft Documentation Websocket Implementation I could
implement the signalling part to the Nodejs with socket.io Server
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
var PORT = 3000;
var userId = 0;
http.listen(PORT, function () {
console.log('listening on *: ' + PORT);
});
io.on('connection', function(socket){
socket.userId = userId++;
console.log('a user connected, user id: ' + socket.userId);
socket.on('mess', function (msg) {
console.log('message from user#' + socket.userId + ": " + msg);
// Send message with emit"mess" to all client
io.emit('mess', msg);
});
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
Both client (uwp app and the hololens could establish to the Server.
On the computer I could send some data to the server.
The problem I currently have is that the Hololens does not receive a message from the server.
For the communication part I use a wrapper class which provide sending and receiving functions for 2 clients. This wrapper class has been generated to dll inorder to reference in 2 difference projekt (uwp app and unity app for hololens)
// Declare "Using" part here...
namespace SocketWrapperNamespace
{
public delegate void OnReceiveMessengerCallback(string msg);
public delegate void OnDisconnectCallback(bool connect);
public class SocketWrapper
{
public event OnReceiveMessengerCallback OnReceiveMessenger;
public event OnDisconnectCallback onDisconnect;
#if !UNITY_EDITOR
private Uri _uri;
private MessageWebSocket messageWebSocket;
private DataWriter dataWriter;
#endif
// Client can call this function to connect
public void Connect(string uri)
{
#if !UNITY_EDITOR
try
{
Connector(uri);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
#endif
}
private async void Connector(string uri)
{
#if !UNITY_EDITOR
// Code here look pretty much like in the example from microsoft documentation
#endif
}
// Function for client to send message to server
public void SendMessage(string emiter, string message)
{
#if !UNITY_EDITOR
try
{
Emit(emiter, message);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
#endif
}
//Emitter
private async void Emit(string emiter, string message)
{
#if !UNITY_EDITOR
try
{
if (messageWebSocket == null)
{
return;
}
if (dataWriter == null)
{
return;
}
string form = string.Format("42[\"{0}\",\"{1}\"]", emiter, message);
dataWriter.WriteString(form);
await dataWriter.StoreAsync();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
#endif
}
//Disconnect
public void Disconnect()
{
#if !UNITY_EDITOR
// Disconnecting server ...
#endif
}
//Message Arrived Handler
private void WebSocket_MessageArrived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
{
#if !UNITY_EDITOR
try
{
if (OnReceiveMessenger == null)
{
return;
}
using (DataReader dataReader = args.GetDataReader())
{
if (dataReader != null)
{
dataReader.UnicodeEncoding = UnicodeEncoding.Utf8;
string message = dataReader.ReadString(dataReader.UnconsumedBufferLength);
OnReceiveMessenger?.Invoke(message);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
#endif
}
//Websocket Close Handler
private void WebSocket_Closed(IWebSocket sender, WebSocketClosedEventArgs args)
{
#if !UNITY_EDITOR
// Close work here ...
#endif
}
}
On the Hololens I prepare the connection to server and listen to the received message event.
// hololens client call this method to initialize the connection
public void OnStart()
{
socketWrapper = new SocketWrapper();
uri = String.Concat("ws://",server,":3000/socket.io/?EIO=3&transport=websocket");
#if !UNITY_EDITOR
socketWrapper.Connect(uri);
socketWrapper.OnReceiveMessenger += OnMessageArrived_Handler;
socketWrapper.onDisconnect += OnDisconnect_Handler;
#endif
}
//Message Arrived Handler
private void OnMessageArrived_Handler(string msg)
{
// Here I do not received any message from server
}
What mistake did I make her ? I wonder that even though I can connect to the server from hololens but the subscribe part seem not to work ?
Consider the 2 projects are on different location and the same happen to the dll.
I think that I have to setup the SocketWrapper class as Singleton because hololens part instantiate a new Object therefor the subscribing may not work here
Any better suggestion for solve this problem with other implementation would be helpful.
Thanks
I think the best solution now for using WebSocket in C# and Unity environment is WebSocketSharp library.
It has a great implementation and kept up to date for 6 years till now. Also it has 3 examples of how to use it in different scenarios.
I would like to interface with Programmatically Interface with the WiFi Hotspot hosted on my RPI running Windows IoT Core. I figured out host the WiFi Hotspot part, windows 10 iot raspberry pi 3 wifi hotspot but now I would like to get the list of devices connected to this network. Is this Possible?
You can use WiFiDirectConnectionListener to achieve this goal. When other devices connect to host device over the Wifi SoftAP, WiFiDirectConnectionListener will capture a connect request.
private Dictionary<string,DeviceInformation> connectionDeviceList = new Dictionary<string, DeviceInformation>();
WiFiDirectConnectionListener wifiAPListener = new WiFiDirectConnectionListener();
wifiAPListener.ConnectionRequested += WifiAPListener_ConnectionRequested;
private void WifiAPListener_ConnectionRequested(WiFiDirectConnectionListener sender, WiFiDirectConnectionRequestedEventArgs args)
{
try
{
var request = args.GetConnectionRequest();
var devInfo = request.DeviceInformation;
var wfdDevice = await WiFiDirectDevice.FromIdAsync(devInfo.Id);
wfdDevice.ConnectionStatusChanged += WfdDevice_ConnectionStatusChanged;
if (!connectionDeviceList.ContainsKey(devInfo.Id))
{
connectionDeviceList.Add(devInfo.Id, devInfo);
}
}
catch(Exception ex)
{
Debug.Write(ex.StackTrace);
}
}
private void WfdDevice_ConnectionStatusChanged(WiFiDirectDevice sender, object args)
{
try
{
if (sender.ConnectionStatus == WiFiDirectConnectionStatus.Disconnected)
{
if (connectionDeviceList.ContainsKey(sender.DeviceId))
{
connectionDeviceList.Remove(sender.DeviceId);
}
}
}
catch(Exception ex)
{
Debug.Write(ex.StackTrace);
}
}
The name of DeviceInformation is the MAC of you device which you to connect the wifi hotspot, you can get more information by setting a breakpoint. When you drop the connection, the WiFiDirectDevice will invoke ConnectionStatusChanged event.
I am trying to connect two windows phone 8.1 devices via Bluetooth.
I have two buttons, one to discover peers, and the second one to connect.
I am sure I enabled the internet (client & server) and proximity capabilities.
here is the code: (the first button works fine)
private async void Button_Click(object sender, RoutedEventArgs e)
{
PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
var peerList = await PeerFinder.FindAllPeersAsync();
if (peerList.Count > 0)
{
t1.Text = peerList[0].DisplayName + "\n";
}
else t1.Text= "No active Peers";
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
PeerFinder.AlternateIdentities["Bluetooth:Paired"] = "";
var peerList = await PeerFinder.FindAllPeersAsync();
if (peerList.Count > 0)
t1.Text = peerList[0].DisplayName;
try
{
PeerFinder.Stop();
StreamSocket socket = new StreamSocket();
await socket.ConnectAsync(peerList[0].HostName, "1");
...
wireless toolkit code
//j2me code for client mobile
public class TCPConnectSend extends MIDlet implements CommandListener {
Display display;
public TCPConnectSend0 () {
frm = new Form ("TCPConnectSend0");
sendCmd = new Command("Send",Command.SCREEN, 1);
frm.addCommand(sendCmd);
frm.setCommandListener(this);
text = new TextField("text:","",40,TextField.ANY);
frm.append(text);
}
public void startApp() {
if(display==null) {
display = Display.getDisplay (this);
}
display.setCurrent(frm);
try {
conn=(SocketConnection)Connector.open("socket://|ip-address|:80");//socket connection to the server
outs=conn.openOutputStream();
} catch(IOException e) { }
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) { }
public void commandAction(Command c, Displayable s) {
if(c==sendCmd) {
try {
outs.write((text.getString()+"\n").getBytes());
} catch(IOException e) {}
} else { }
}
}
server code
//this receives the socket request from client
class TCPServer
{
public static void main(String argv[]) throws Exception
{
try {
ServerSocket server = new ServerSocket(80);
System.out.println("ip address : "+InetAddress.getLocalHost());
System.out.println("waiting for connection");
Socket s1 = server.accept();
System.out.println("connection established");
BufferedReader br = new BufferedReader(new
InputStreamReader(s1.getInputStream()));
while (true) {
String str1 = br.readLine();
System.out.println("client says :" +str1);
if (str1.equals("quit"))
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//after running this code i m getting a java security exception in my nokia phone any other port no is no responding in the nokia phone
the problem happened because Nokia was blocking the 80 port no for some of its system application so changing of port no along with public ip address did the trick
You should add the public IP of the server in your client code ex.
(SocketConnection)Connection.open( "socket://105.225.251.58" + ":" + "port" );
Note that to use privileged ports like 80, 443, 8080 and generally anything below 1000, you need a code signing certificate(e.g from Thawte) for a real phone.
Otherwise, still to higher un-privileged ports likes 8000 etc
I am developing a mobile application in net-beans that will send and receive SMS, I'm done with sending text but I don't know how to receive SMS in NetBeans mobile application ?
WMA (Wireless Messaging API) is a wireless messaging api defined in MIDP 2.0. These apis are designed to handle text, binary and multipart messages. To make a connection, the application obtains an object implementing the MessageConnection from the Connector class by providing an URL connection string that identifies the address.
/* Make a connection */
public boolean connectSMSServer()
{
try
{
messageConnection messageConnection =
(MessageConnection)Connector.open("sms://:" + port);
messageConnection.setMessageListener(this);
}
catch (Exception e) {
}
}
/* Send text message */
public void sendTextmessage(String address,String message)
{
try
{
//creates a new TextMessage
TextMessage textMessage = (TextMessage)messageConnection.newMessage(
MessageConnection.TEXT_MESSAGE, address);
textMessage.setPayloadText(message);
messageConnection.send(textMessage);
}
catch (Exception e) {
}
}
/* Recieve text message */
public void receiveTextMessage()
{
try
{
Message message = messageConnection.receive();
if (message instanceof TextMessage)
{
TextMessage textMessage = (TextMessage)message;
}
else
{
//Message can be binary or multipart
}
}
catch (Exception e) {
}
}
/* Notify Incoming Message */
public synchronized void notifyIncomingMessage(MessageConnection conn)
{
//notiy thread of incoming message
synchronized (this)
{
notify();
}
}
/* Close Connection */
public void closeConnection()
{
if (messageConnection != null)
{
try
{
messageConnection.setMessageListener(null);
messageConnection.close();
}
catch (Exception e) {
}
}
}
}
When you are coding for Receiving SMS, you need to listen to one particular port. J2ME Application can not read directly from the inbox.