3

Let say I have bluetooth dongle on my PC.
How can I send data to my PC directly.
I don't want to use the phone a middle man.
(which is normally used when debugging Wear over bluetooth)
Can I pair Android Wear with PC directly, and then transmit any data?

tcboy88
  • 1,063
  • 1
  • 9
  • 23

2 Answers2

1

You would need to reverse engineer the Bluetooth protocol between the Android Wear watch and the Wear App on the phone. Given that the Wear App is used to update the OS Wear software on the watch, Google can change the protocol at any time. So while you might be able to sniff the traffic and duplicate the behavior of the Wear App to be able to talk to the watch, you are just one update away from having to reverse engineer it all over again.

Morrison Chang
  • 11,691
  • 3
  • 41
  • 77
  • so there is currently no easy way to do it? what about newer Android watches with Wifi? Can I connect both my PC and Wear to the same network, and then make a simple TCP server on my PC, and use Wear to connect to the that TCP server? This is easy on a phone but I am not sure about watch. But given that many people said Wear's OS is basically same as the phone. – tcboy88 Jul 23 '15 at 07:36
  • WearOS while based on Android doesn't have everything like WebView and at one point didn't allow HTTP connection see: http://stackoverflow.com/questions/24717538/does-android-wear-support-httpurlconnection-getting-eofexception. As WearOS has been updated since that question, I don't know if the answer has changed or not. Leaning toward not as radio uses up the precious battery on the watch. – Morrison Chang Jul 23 '15 at 14:00
  • http://stackoverflow.com/questions/31352144/how-to-make-http-requests-over-wifi-directly-from-android-wear in this answer he mentioned it is possible to use network call IF the watch is disconnected from the phone. – tcboy88 Jul 23 '15 at 16:21
  • @tcboy88 great find - the only cost is the pairing device (phone/tablet) needs to be unreachable so you'll need a spare device and you may not be able to use adb to debug at the same time. – Morrison Chang Jul 23 '15 at 17:03
0

I have tried it and confirmed it works on Android Wear 5.1 (both version 1.1 and latest version 1.3).
Proof: https://www.youtube.com/watch?v=yyGD8uSjXsI
I am not sure if Google will patch this soon because it seems like some loophole.

You need a android watch with WiFi such as Samsung Gear Live, Moto360, LG Urbane etc. For your information, LG G Watch has no WiFi support. Then first you need to pair your watch to your phone, then go to your watch, enable WiFi and select any WiFi spot. Then the watch will ask you to insert your password on the phone. After that, it will connect to the WiFi.

Then now you should go to your android phone, and UNPAIR the watch. This is because we want to force the watch to use WiFi connection directly. Or else it will always use bluetooth via the phone as middleman.
You can double check the watch is using WiFi by running an Android Wear browser and browse any random pages.

Then in your code (server/client model), just use socket normally.
For example, I use aysnctask for network connection as below. You should get sensor data by register listener, there are many examples so I don't post here.

class ConnectServer  extends AsyncTask<Void, Void, Void> {

    public ConnectServer() {
        super();
    }

    @Override
    protected Void doInBackground(Void... params) {
        sendToServer();
        return null;
    }

    public void sendToServer(){
        Socket socket = null;
        BufferedWriter out = null;
        try
        {
            socket = new Socket(IP_ADDRESS, 5000); // IP address of your computer
            out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            while(isSending)
            {
                //x,y,z,w is from android sensor 
                out.write(String.format("%.3f",x)+
                    ","+String.format("%.3f",y)+
                    ","+String.format("%.3f",z)+
                    ","+String.format("%.3f",w)+"/");
                out.flush();
                Thread.sleep(INTERVAL); // 50ms is quite good
            }

            out.close();
            socket.close();
        }
        catch (Exception e)
        {
            Log.e("socket",""+e.toString());
            e.printStackTrace();
        }
        finally
        {
            if (socket != null)
            {
                try
                {
                    socket.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            if (out != null)
            {
                try
                {
                    out.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

For Server, I am using .net Async Socket inside Unity, but it should be the same for any .net applications. The code is not optimized or error checked thoroughly, but you get the idea.

using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Text;

public class AsyncServer : MonoBehaviour {
    private byte[] data = new byte[1024];
    private int size = 1024;
    private Socket server;
    private Socket client;
    float x, y, z, w;

    void Start () {
        server = new Socket(AddressFamily.InterNetwork,
                  SocketType.Stream, ProtocolType.Tcp);

        IPAddress ipAd = IPAddress.Parse("YOUR IP ADDRESS");
        //IPEndPoint iep = new IPEndPoint(IPAddress.Any, 5000);
        IPEndPoint iep = new IPEndPoint(ipAd, 5000);
        server.Bind(iep);
        server.Listen(5);
        server.BeginAccept(new AsyncCallback(AcceptConn), server);

    }

    void AcceptConn(IAsyncResult iar)
    {
        Socket oldserver = (Socket)iar.AsyncState;
         client = oldserver.EndAccept(iar);
        Debug.Log("Accepted client: " + client.ToString());
        client.BeginReceive(data, 0, size, SocketFlags.None,
            new AsyncCallback(ReceiveData), client);
    }

    void SendData(IAsyncResult iar)
    {
        Socket client = (Socket)iar.AsyncState;
        int sent = client.EndSend(iar);
        client.BeginReceive(data, 0, size, SocketFlags.None,
                    new AsyncCallback(ReceiveData), client);
    }

    void ReceiveData(IAsyncResult iar)
    {
        Socket client = (Socket)iar.AsyncState;
        int recv = client.EndReceive(iar);
        if (recv == 0)
        {
            client.Close();
            Debug.LogError("Waiting for client...");
            server.BeginAccept(new AsyncCallback(AcceptConn), server);
            return;
        }
        string receivedData = Encoding.ASCII.GetString(data, 0, recv);
        //Debug.Log("len: " + recv + ", " + receivedData);

        {
            var s = receivedData.Split(',');
            if (s.Length == 4)
            {
                float xx = float.Parse(s[0]);
                float yy = float.Parse(s[1]);
                float zz = float.Parse(s[2]);
                s[3] = s[3].Replace("/","");
                float ww = float.Parse(s[3]);
                Debug.Log("len: " + recv + ", " + xx + ", " + yy + ", " + zz + ", " + ww);
            } 
        }

        client.BeginReceive(data, 0, size, SocketFlags.None,
            new AsyncCallback(ReceiveData), client);
    }
}
motoku
  • 1,571
  • 1
  • 21
  • 49
tcboy88
  • 1,063
  • 1
  • 9
  • 23