Android WiFi Direct Demo Issues - android

im testing the new technology wifi direct and im having some issues using
the wifi direct demo from the samples that come with the android-sdk.
So, I have two devices A and B, both with android 4.0.3.
First, from device A, I send a file to B. Nothing wrong here, B
receives the file.
Then A disconnects from B.
Now, from device B I try to send a file to A.
But the device that receives the file is B, instead of A.
To fix, i need to turn off and on both devices...
Also, sometimes when i click disconnect and try to
connect again, connection fails and i have to disable and
enable wifi direct...
Anyone else experiencing this?
Is it because the new technology is not mature yet or maybe
something wrong with my build/driver/etc or maybe this demoapp
doesnt support two-way sharing.
Any ideas and/or explanations would be apreciated.

When providing a WifiP2pConfig instance to the connect() function, you can set the groupOwnerIntent property of this configuration object as follows:
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = "..."; // insert ip here
config.groupOwnerIntent = 0;
config.wps.setup = WpsInfo.PBC;
manager.connect(..., config, ...);
From the android reference:
This (the groupOwnerIntent) is an integer value between 0 and 15 where
0 indicates the least inclination to be a group owner and 15 indicates
the highest inclination to be a group owner.
Furthermore, the demo probably repeatedly sends the file to the same device because there is always made a socket connection to the ip-address obtained from:
WifiP2pInfo.groupOwnerAddress
If you would like to support bidirectional communication, the first step in setting this up would be sending the ip-address of the non group owner to the group owner.
As far as the disconnect/reconnect problem goes, I seem to have the same inconsistencies with Android 4.0.2 devices.

I have been trying for a while to transfer files between two devices using wifi direct. I have use the Android SDK WifiDirectDemo as base. My experience:
GO address is always the same (at least in Samsung Nexus), but this is not really a problem, because you can use this to know who is the server (or client).
Another strange thing was that MAC address of devices were different when you got it from Android WifiManager and when you read it from "/proc/net/arp" file.
At the end I did it, and you can see the code here.
I hope it helps you!

I have been struggling with the same problem lately. I suppose this is an OS issue. To give you a brief background, I have installed Wi-Fi Direct application to both devices with different OS versions, one with OS 4.0.1 and one with OS 4.0.2. The connection fails from time to time when I disconnect and reconnect the devices. It goes same while searching for devices too. But the thing is, this only happens on the device with OS 4.0.2. Other device does not crash or disconnect.
While searching for that problem, I have found the links below. People discussed about that and they share the same idea. Apparently this is an OS 4.0.2 issue. I am not sure if it is the same for OS 4.0.3 but there is no problem with the previous version OS 4.0.1 for sure.
Here are the links:
http://code.google.com/p/android/issues/detail?id=24402
http://osdir.com/ml/android-platform/2012-01/msg00226.html

Related

Android only: C# .net-MAUI, not Xamarin(!), sending UDP?

Situation:
VS 2022, 17.0.4
Maui App,
net6.0-android
AndroidManifest.xml contains also:
android.permission.INTERNET
android.permission.CHANGE_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
Connected mobile Phone:
Samsung SM-G960F (Android 10.0 - API 29)
OS: Windows 11, latest patch.
All firewalls are down (for testing purpose only!)
While debugging the develop computer is only connected to a Wifi network; computers ethernet card is disabled.
Mobile phone is connected to this dev computer via USB cable (to be able to debug) and to the same Wifi network as the computer.
App starts and works fine, app can be debugged. No issue at all - except:
After the application is fully initialized and ready to accept user interactions -> Click on button -> Desired method is called -> Code is worked out -> The code should make a simple UDP call but it does not (or the packet does not reach the UDP listener due to missing configuration?).
The UDP receiver works fine and is capable to receive UDP packets.
My mobile phone and the UDP receiver app are using the same port.
I read/found already that in the previous cross-platform framework, means “Xamarin (Android SDK 12)”, some permissions must be set (I did, see above) and that the multicastlock must be set over the WifiManager …
I tried this in my MAUI app. But could not find anything guiding me nor figured it out by myself.
My MAUI sending code:
var dataToBeSend = "What ever ...";
var data = Encoding.UTF8.GetBytes(dataToBeSend);
var UdpClient = new UdpClient();
// UdpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
UdpClient.ExclusiveAddressUse = false;
UdpClient.EnableBroadcast = true;
// UdpClient.Client.Bind(new IPEndPoint(IPAddress.Parse("255.255.255.255"), BroadcastPort));
// UdpClient.Client.Bind(new IPEndPoint(IPAddress.Any, BroadcastPort));
UdpClient.Send(data, data.Length, "255.255.255.255", BroadcastPort);
As said: very easy and straight forward.
Notice that I also tried binding UDP code …
So please can someone be so kind to guide me or give me a hint?
Thank you very much in advance!
ANSWER:
After two days I found a solution - and would like to share it because may be it helps someone else.
The code to make the UDP call msut be placed in a THREAD (not task!)
codesnippet:
var communication = new Communication();
var udpThread = new Thread(new ThreadStart(communication.FireUDPCall));
udpThread.Start();
The firewalls can stay turned on / active!

connection resets when using set_configuration in PyUSB

I've recently updated my android phone to Marshmallow. Unfortunately for me, that broke my python code.
using PyUSB, I can get the device to enter accessory mode. Unfortunately, I can no longer read/write to the device, as now using set_configuration() resets the connection, causing the device to exit accessory mode and re-enter MTP mode.
dev = list(usb.core.find(find_all=True))[0]
dev.ctrl_transfer(0xc0,51,data_or_wLength=2)
dev.ctrl_transfer(0x40,52,wIndex=0,data_or_wLength='SAMSUNG')
dev.ctrl_transfer(0x40,52,wIndex=1,data_or_wLength='SAMSUNG_Android')
dev.ctrl_transfer(0x40,52,wIndex=2,data_or_wLength='16DIGITSERIALNUM')
dev.ctrl_transfer(0x40,52,wIndex=3,data_or_wLength='AOA')
dev.ctrl_transfer(0x40,52,wIndex=4,data_or_wLength='Whatever')
dev.ctrl_transfer(0x40,52,wIndex=5,data_or_wLength='4')
dev.ctrl_transfer(0x40,53)
time.sleep(5)
dev = list(usb.core.find(find_all=True))[0]
dev.set_configuration() ## Aaaaaand we're back to MTP...
I can't find any way around this; no references to this problem. Only solution I can some up with is to learn C and use libusb directly, assuming the PyUSB module is to blame...
Well, this isn't a good solution, but just in case anyone else just happens to come across this problem and find this:
The problem is with the specific backend (libusb0), which sends a message to reset configuration or something like that if an interface is already claimed. In some devices (mine, for example), this causes a programmatic reset of the connection.
My workaround involves using thelibusb1 backend when re-acquiring the device in accessory mode, since it doesn't cause a reset. But since libusb1 won't let me do control transfers, I need to switch between backends.
from usb.backend import libusb0, libusb1, and then be0,be1 = libusb0.get_backend(),libusb1.get_backend().
Then just specify the backend as a parameter to usb.core.find

USB-Webcam on Android 4.4+

I am into a new project which requires me to use a USBconnected "Webcam".
The whole fun should run on Android 4.4.
my little story was:
I try multiple apps which do this - all work on both my testing devices
adapting some NDK lib that directly uses /dev/video0. This didnt work due to read-permission that was not granted in a new File("dev/video0").canRead() check. Although my unix permissions are correct, this seems to not work due to some new check on Android 4.4. (the whole thing was suggested here: Connect Android phone to a USB Web camera )
next: discover the UsbAccessory API that supposedly easens a lot of the above.
´find no documentation or anything about how to correctly handle a webcam
I still try, but don't come further than finding no device via
usbManager.getAccessory();
I've also tried to discover devices by filtering for a USB_ATTACHED broadcast but nothing triggers.
So I am starting to ask myself how the hell do others find the devices & communicate with them to get the pictures?
Anyone has sources from which i could learn, or a tutorial or something?
Little update from my side:
- I've gotten access by using the Android USB Host API e.g. UsbDevice instead of UsbAccessory.
- I have the connection and everything setup fine, and can now send binary data to my webcam and supposedly receive.
I can now send controlCommands via connection.controlTransfer(...) or use a "UsbRequest" in order to receive data.
However, I couldn't find any documentation to "make the camera submit pictures" to me. My Endpoint is of type XFER_INT (=interrupts).
I am continuing to try sending out various commands (e.g. binary values) but haven't had any success so far.

any way to discover Android devices on your network?

I want to be able to discover Android devices on my network and possibly retrieve some device information about them. This is very easy with Apple devices since they run Bonjour services. However, I can't seem to find any similar service running on Android.
This must work without modifying the Android device, installing some service, or opening some port. It's meant to work with vanilla Android devices in the way that Bonjour helps you find vanilla Apple devices. Even being able to just verify that the device is running Android would be sufficient.
Chosen Answer: Although it's not the top rated answer (yet), please take a look at the response by Luis. As he mentions, you can use a DNS lookup (using your local DNS server) to discover Android devices. I have found this to have a 100% success rate, as Android forces devices to use a hostname of android-_____. This is apparently difficult to change on the phone, even if it is rooted. So I think this is a pretty accurate method. Thanks, Luis!
Example:
$ nslookup 192.168.1.104 192.168.1.1
Server: 192.168.1.1
Address: 192.168.1.1#53
104.1.168.192.in-addr.arpa name = android-711c129e251f14cf.\001.
Sample Code: If you wanted to implement this in Java (e.g., to run on Android), you can't easily use getHostName() because it uses the external DNS servers. You want to use the local DNS server on your router, for example. Luis mentions below that you could modify the DNS servers of the Wifi connection, but that could possibly break other things. Instead, I've found the dnsjava library to be extremely helpful to send targeted DNS requests. Here is some sample code using the library:
String ipAddress = "104.1.168.192";
String dnsblDomain = "in-addr.arpa";
Record[] records;
Lookup lookup = new Lookup(ipAddress + "." + dnsblDomain, Type.PTR);
SimpleResolver resolver = new SimpleResolver();
resolver.setAddress(InetAddress.getByName("192.168.1.1"));
lookup.setResolver(resolver);
records = lookup.run();
if(lookup.getResult() == Lookup.SUCCESSFUL) {
for (int i = 0; i < records.length; i++) {
if(records[i] instanceof PTRRecord) {
PTRRecord ptr = (PTRRecord) records[i];
System.out.println("DNS Record: " + records[0].rdataToString());
}
}
} else {
System.out.println("Failed lookup");
}
} catch(Exception e) {
System.out.println("Exception: " + e);
}
This gives me the output:
DNS Record: android-711c129e251f14cf.\001.
Bingo.
There is an very simple approach that gave me positive results in few different devices.
When a device connects to your router it receives an IP (i.e. DHCP) and registers a name in DNS. The name that is registered seems to be always in the form android_nnnnnnnn.
Of course, you can name any computer with the same approach and trick the check, resulting in false positives ...
Also, I can't ensure that all device suppliers are following the same approach, but I've found it to work correctly in a few devices from different brands (including different SDK levels) that I've tested.
--EDITED--
How to do it
It depends on where you would be running the code to discover the Android devices. Assuming that you would be running the code in an Android device:
First discover devices responding to ping in your network. You can use the code in my answer to this post: execComd() to run a ping command.
Get the name of responding devices using the code:
InetAddress inetAddress = InetAddress.getByName(string_with_ip_addr);
String name = inetAddress.getCanonicalHostName();
--EDIT 2--
Proof of concept
The method below is just a proof of concept for what I've wrote above.
I'm using isReachable() method to generate the ICMP request, which is said to only work with rooted devices in many posts, which is the case for the device used for testing it. However, I didn't give root permissions for the application running this code, so I believe it couldn't set the SIUD bit, which is the reason why some claim that this method fails. I would like to do it here from the perspective of someone testing it on a non-rooted device.
To call use:
ArrayList<String> hosts = scanSubNet("192.168.1.");
It returns in hosts, a list of names for devices responding to ping request.
private ArrayList<String> scanSubNet(String subnet){
ArrayList<String> hosts = new ArrayList<String>();
InetAddress inetAddress = null;
for(int i=1; i<10; i++){
Log.d(TAG, "Trying: " + subnet + String.valueOf(i));
try {
inetAddress = InetAddress.getByName(subnet + String.valueOf(i));
if(inetAddress.isReachable(1000)){
hosts.add(inetAddress.getHostName());
Log.d(TAG, inetAddress.getHostName());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return hosts;
}
Regards.
Android is not going to be as easy as iOS. There is no Bonjour equivalent.
Android 4.0, Ice Cream Sandwich, introduced Wi-Fi Direct Peer to Peer networking. At first I hoped it might be able to be scanned in the the way your thinking, but it helps Android devices communicate without an access point, so they're not really "on your network". Besides, ICS runs on only a fraction of Android devices.
Rather than an active netscan approach, you're left with a passive monitoring approach. If your network is secure, sniffing the encrypted packet is possible, but inconvenient. You'll have to
put your network interface into monitor mode
capture the 4-way handshake
decrypt it using the network's pre-shared key
this will give you the key you need to decrypt traffic
If you want to see this in action, Wireshark supports WPA decryption.
Once you're able to view the Wi-Fi traffic, you will notice Android devices tend to communicate with certain Google servers and their HTTP connections have User Agent strings that can be identified.
This is the basis for a workable passive solution.
Tenable Network Security offer products that seem to take this type of approach.
Another Idea
#Michelle Cannon mentioned Libelium's Meshlium Xtreme whose approach will not get you all the way there (not without good up to date MAC address range tables). But it could be part of reaching a lesser goal.
You can:
Detect all wireless devices
Eliminate Apple devices using the MAC's Organizationally Unique Identifier (OUI)
Tell it's a mobile device by by monitoring signal strength to determine it's moving (and mobile devices will tend to show up and go away)
You may be able to use the MAC OUI as a hint it's Android
You may be able to use the MAC OUI as a hint it's not Android (but a laptop or wireless card, etc.).
This may be workable if your willing to detect devices that are probably Android.
DHCP Fingerprinting
#Michelle Cannon suggested DHCP fingerprinting. I wasn't sure at first but I have to thank him for suggesting what's looking like the best bet for simple passive scanning. As a cautionary tail, I'd like to explain why I was late to the party.
There are things we know, thinks we don't know, and things we think we know but are wrong.
In a lot of ways, it's good that Android uses the Linux kernel. But it's not good if you want to discover Android devices on your network. Android's TCP/IP stack is Linux's therefor Android devices will look like Linux devices or so I thought at first. But then I realized Linux has a lot of build configuration parameters so there could be something distinctive about Android when seen on a network, but what?
DHCP fingerprinting uses a the exact DHCP options requested by the device plus timing. For this to work you generally need an up to date fingerprint database to match against. At first it looked like fingerbank was crowed sourcing this data, but then I noticed their files hadn't been updated for almost a year. With all the different Android device types, I don't think it's practical to keep updated fingerprints for a single project.
But then I looked at the actual DHCP signatures for Android and I noticed this:
Android 1.0: dhcpvendorcode=dhcpcd 4.0.0-beta9
Android 1.5-2.1: dhcpvendorcode=dhcpcd 4.0.1
Android 2.2: dhcpvendorcode=dhcpcd 4.0.15
Android 3.0: dhcpvendorcode=dhcpcd-5.2.10
Linux normally uses dhclient as their DHCP client, but Android is using dhcpcd. Android has a strong preference for using software licensed with the BSD style where possible and dhcpcd uses a BSD license. It would seem dhcpvendorcode could be used as a strong indicator that a mobile device is running Android.
DHCP monitoring
A client uses DHCP to get an IP address when joining a network so it's starting without an IP address. It gets around this problem by using UDP broadcasts for the initial exchange. On Wi-Fi, even with WPA, broadcast traffic is not encrypted. So you can just listen on UDP port 67 for client to server traffic and 68 for the reverse. You don't even need to put your network interface into promiscuous mode. You can easily monitor this traffic using a protocol analyzer like Wireshark.
I preferred to write code to monitor the traffic and decided to use Python. I selected pydhcplib to handle the details of DHCP. My experience with this library was not smooth. I needed to manually download and place IN.py and TYPES.py support files. And their packet to string conversion was leaving the dhcpvendorcode blank. It did parse the DHCP packets correctly, so I just wrote my own print code.
Here's code that monitors DHCP traffic from client to server:
#!/usr/bin/python
from pydhcplib.dhcp_packet import *
from pydhcplib.dhcp_network import *
from pydhcplib.dhcp_constants import *
netopt = {
'client_listen_port':"68",
'server_listen_port':"67",
'listen_address':"0.0.0.0"
}
class Server(DhcpServer):
def __init__(self, options):
DhcpServer.__init__(
self,options["listen_address"],
options["client_listen_port"],
options["server_listen_port"])
def PrintOptions(self, packet, options=['vendor_class', 'host_name', 'chaddr']):
# uncomment next line to print full details
# print packet.str()
for option in options:
# chaddr is not really and option, it's in the fixed header
if option == 'chaddr':
begin = DhcpFields[option][0]
end = begin+6
opdata = packet.packet_data[begin:end]
hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
print option+':', ':'.join([(hex[i/16]+hex[i%16]) for i in opdata])
else:
opdata = packet.options_data.get(option)
if opdata:
print option+':', ''.join([chr(i) for i in opdata if i != 0])
print
def HandleDhcpDiscover(self, packet):
print "DHCP DISCOVER"
self.PrintOptions(packet)
def HandleDhcpRequest(self, packet):
print "DHCP REQUEST"
self.PrintOptions(packet)
## def HandleDhcpDecline(self, packet):
## self.PrintOptions(packet)
## def HandleDhcpRelease(self, packet):
## self.PrintOptions(packet)
## def HandleDhcpInform(self, packet):
## self.PrintOptions(packet)
server = Server(netopt)
while True :
server.GetNextDhcpPacket()
This code is based on pydhcplib's server example because it listens for client requests, like a server.
When my Nexus 7 Android 4.2 tablet connects, this interesting information is captured (redacted):
DHCP REQUEST
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff
DHCP DISCOVER
vendor_class: dhcpcd-5.5.6
host_name: android-5c1b97cdffffffff
chaddr: 10:bf:48:ff:ff:ff
The host name seems to have a fixed format and is easily parsed. If you need the IP address you can monitor the server to client traffic. Note: only the initial exchange, when an new client first shows up without an IP address, is broadcast. Future lease extensions, etc., are not broadcast.
Reverse DNS Lookup
#Luis posted a great solution that demonstrates how simpler is better. Even after seeing Android's DHCP client was setting host_name to android-5c1b97cdffffffff, I didn't think to ask the router for it's list of names using reverse DNS lookups. The router adds the host_name to it's DNS server so you can still access the device if its IP address changes.
The host_name is expected to remain listed in the DNS for the duration of the DHCP lease. You could check if the device is still present by pinging it.
One drawback to depending on host_name is there are ways this could be changed. It's easy for the device manufacturer or carrier to change the host_name (though after searching, I've been unable to find any evidence they ever have). There are apps to change host name, but they require root so that's, at most, an edge case.
Finally there's an open Android Issue 6111: Allow a hostname to be specified that currently has 629 stars. It would not be surprising to see configurable host_name in Android Settings at some point in the future, maybe soon. So if you start depending on host_name to identify Android devices, realize it could be yanked out from under you.
If you're doing live tracking, another potential problem with Reverse DNS Lookup is you have to decide how frequently to scan. (Of course this is not an issue if you're just taking a one-time snapshot.) Frequent scanning consumes network resources, infrequent leaves you with stale data. Here's how adding DHCP monitoring can help:
On startup use Reverse DNS Lookup to find devices
Ping devices to see if they are still active
Monitor DHCP traffic to detect new devices instantly
Occasionally rerun DNS Lookup to find devices you might have missed
If you need to notice devices leaving, ping devices at desired timing resolution
While it's not easy (nor 100% accurate), there are several techniques that make it possible to discover Android devices on your network.
AFAIK, Android system doesn't provide any zeroconf app/service on it's built-in system app/service stack. To enable the auto-discovery on the actual device attached to local network, you need either install some third-party zeroconf app or develop your own app/service and install it on the actual device, some API options are:
JmDNS (for Apple's bonjour protocol)
Cling (for Microsoft's UPnP protocol)
Android NSD API (introduced since Android 4.1)
I am not quite clear about your requirements, if you want something similar (i.e. auto discover and connect) on vanilla Android devices, you can probably use Wi-Fi direct which is now available on some later device running Android 4.0, however, it requires both devices support Wi-Fi Direct and only create an ad-hoc P2P connection with Wi-Fi turned off, much like a bluetooth connection with a longer range:
For Wi-Fi Direct API support, check out official guide - Connecting Devices Wirelessly.
I am looking at this an thinking
http://www.libelium.com/smartphones_iphone_android_detection
pay special note to this
Do the users need to have an specific app installed or interact somehow to be detected?
No, the scan is performed silently, Meshlium just detects the "beacon frames" originated by the Wifi and Bluetooth radios integrated in the Smartphones. Users just need to have at least one of the two wireless interfaces turned on.
Long time ago I use to use an app called stumbler on my mac to find wifi networks, I think this is similar
Other ideas
Well if I need to determine android phones on a local network how would I do it. Absent of a dns service running I only have a couple possibilities
The SSID if its being broadcast - can't tell me anything The ip address - android lets you have a lot of control over host naming so I guess you could define a specific ip range to your android devices. -not to useful.
Alternately lets say I see an unknown device on the network, if bluetooth is turned on then I am broadcasting a bluetooth device signature SDPP that I can use to deduce my device type.
If I were running a service that supported android and I wanted to discover specific android devices on my network, then I could just register the mac addresses for those devices and watch for them on the network.
Other than that you would need to run either a bonjour (dns-sd) or upnpp dameon on the device.
Updated Response
Sorry, I haven't understood the original question correctly. Only your comment made it really clear to me that you do not want to have to install anything on the target devices but you just want a way of discovering random phones in your network.
I'm not sure if this would really be possible in the way you want it. Without having any network discovery service running on Android you will not find the device in first place. Of course you can use some low-level network protocols but that would only give you an indicator that there's something but not what it is (being an Android device, a PC, a whatever else).
The most promising approach would be to check for preinstalled apps that have network functionality of some kind. E.g. Samsung devices have Kies Air (if the user enables it), Motorola are using UPnP for their Media Server and HTC has something own as well, if I remember correctly. However, there's no app that is installed on all Android devices of all vendors and carriers. So you can't rely on solely one of those but would need to check for various different services using their specific protocols and behaviors in order to get additional information about the device. And, of course, the user would have to enable the functionality in order for you to use it.
Old response
An additional alternative to yorkw's list is AllJoyn by Qualcomm. It's an open source cross-platform discovery and peer-to-peer communication framework I've used in the past myself already.
Though Qualcomm is a big sponsor of AllJoyn this does not mean that you need a Qualcomm chipset in your define. In fact AllJoyn works on any chipset including Intel and nVidia. It doesn't require rooted phones or any other modifications to the Android framework and just works "out of the box" using Wi-Fi and/or Bluetooth as pairing methods.
I am learning a lot from this topic.
there is also something called dhcp fingerprinting, apparently different devices act differently to the kind of network scans we've been discussing such as those using NMAP a linux scanner. Maps of the behavior from these probes are available on the internet.
http://www.enterasys.com/company/literature/device-profiling-sab.pdf
https://media.defcon.org/dc-19/presentations/Bilodeau/DEFCON-19-Bilodeau-FingerBank.pdf
http://community.arubanetworks.com/t5/ArubaOS-and-Mobility-Controllers/COTD-DHCP-Fingerprinting-how-to-ArubaOS-6-0-1-0-and-above/td-p/11164
http://myweb.cableone.net/xnih/
Here's a one liner that pings all of the machines on your network (assuming your network is 192.168.1.x) and does a reverse lookup on their names:
for i in {1..255}; do echo ping -t 4 192.168.1.${i} ; done | parallel -j 0 --no-notice 2> /dev/null | awk '/ttl/ { print $4 }' | sort | uniq | sed 's/://' | xargs -n 1 host
Requires GNU parallel to work. You can install that on OSX using "brew install parallel"
From this you can just look at the devices named android-c40a2b8027d663dd.home. or whatever.
You can then trying running nmap -O on a device to see what else you can figure out:
sudo nmap -O android-297e7f9fccaa5b5f.home.
But it's not really that fruitful.

Android Bluetooth IOException:connection refused

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.

Categories

Resources