Skip to content

Commit 320b3ec

Browse files
Alexander LucasAndroid (Google) Code Review
authored andcommitted
Merge "Initial commit of wireless connectivity/discovery class." into jb-dev
2 parents bba948d + 969c243 commit 320b3ec

File tree

6 files changed

+1080
-0
lines changed

6 files changed

+1080
-0
lines changed
45.3 KB
Binary file not shown.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
page.title=Connecting Devices Wirelessly
2+
3+
trainingnavtop=true
4+
startpage=true
5+
next.title=Using Network Service Discovery
6+
next.link=nsd.html
7+
8+
@jd:body
9+
10+
11+
<div id="tb-wrapper">
12+
<div id="tb">
13+
14+
<h2>Dependencies and prerequisites</h2>
15+
<ul>
16+
<li>Android 4.1 or higher</li>
17+
</ul>
18+
19+
<h2>You should also read</h2>
20+
<ul>
21+
<li><a href="{@docRoot}guide/topics/connectivity/wifip2p.html">Wi-Fi Direct</a></li>
22+
</ul>
23+
24+
25+
</div>
26+
</div>
27+
28+
29+
<p>Besides enabling communication with the cloud, Android's wireless APIs also
30+
enable communication with other devices on the same local network, and even
31+
devices which are not on a network, but are physically nearby. The addition of
32+
Network Service Discovery (NSD) takes this further by allowing an application to
33+
seek out a nearby device running services with which it can communicate.
34+
Integrating this functionality into your application helps you provide a wide range
35+
of features, such as playing games with users in the same room, pulling
36+
images from a networked NSD-enabled webcam, or remotely logging into
37+
other machines on the same network.</p>
38+
<p>This class describes the key APIs for finding and
39+
connecting to other devices from your application. Specifically, it
40+
describes the NSD API for discovering available services and the Wi-Fi
41+
Direct&trade; API for doing peer-to-peer wireless connections. This class also
42+
shows you how to use NSD and Wi-Fi Direct in
43+
combination to detect the services offered by a device and connect to the
44+
device when neither device is connected to a network.
45+
</p>
46+
<h2>Lessons</h2>
47+
48+
<dl>
49+
<dt><strong><a href="nsd.html">Using Network Service Discovery</a></strong></dt>
50+
<dd>Learn how to broadcast services offered by your own application, discover
51+
services offered on the local network, and use NSD to determine the connection
52+
details for the service you wish to connect to.</dd>
53+
<dt><strong><a href="wifi-direct.html">Connecting with Wi-Fi Direct</a></strong></dt>
54+
<dd>Learn how to fetch a list of nearby peer devices, create an access point
55+
for legacy devices, and connect to other devices capable of Wi-Fi Direct
56+
connections.</dd>
57+
<dt><strong><a href="nsd-wifi-direct.html">Using Wi-Fi Direct for Service
58+
Discovery</a></strong></dt>
59+
<dd>Learn how to discover services published by nearby devices without being
60+
on the same network, using Wi-Fi Direct.</dd>
61+
</dl>
62+
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
page.title=Using Wi-Fi Direct for Service Discovery
2+
parent.title=Connecting Devices Wirelessly
3+
parent.link=index.html
4+
5+
trainingnavtop=true
6+
7+
@jd:body
8+
9+
<div id="tb-wrapper">
10+
<div id="tb">
11+
<h2>This lesson teaches you to</h2>
12+
<ol>
13+
<li><a href="#manifest">Set Up the Manifest</a></li>
14+
<li><a href="#register">Add a Local Service</a></li>
15+
<li><a href="#discover">Discover Nearby Services</a></li>
16+
</ol>
17+
<!--
18+
<h2>You should also read</h2>
19+
<ul>
20+
<li><a href="#"></a></li>
21+
</ul>
22+
-->
23+
</div>
24+
</div>
25+
26+
<p>The first lesson in this class, <a href="nsd.html">Using Network Service
27+
Discovery</a>, showed you
28+
how to discover services that are connected to a local network. However, using
29+
Wi-Fi Direct&trad; Service Discovery allows you to discover the services of nearby devices directly,
30+
without being connected to a network. You can also advertise the services
31+
running on your device. These capabilities help you communicate between apps,
32+
even when no local network or hotspot is available.</p>
33+
<p>While this set of APIs is similar in purpose to the Network Service Discovery
34+
APIs outlined in a previous lesson, implementing them in code is very different.
35+
This lesson shows you how to discover services available from other devices,
36+
using Wi-Fi Direct&trade;. The lesson assumes that you're already familiar with the
37+
<a href="{@docRoot}guide/topics/connectivity/wifip2p.html">Wi-Fi Direct</a> API.</p>
38+
39+
40+
<h2 id="manifest">Set Up the Manifest</h2>
41+
<p>In order to use Wi-Fi Direct, add the {@link
42+
android.Manifest.permission#CHANGE_WIFI_STATE}, {@link
43+
android.Manifest.permission#ACCESS_WIFI_STATE},
44+
and {@link android.Manifest.permission#INTERNET}
45+
permissions to your manifest. Even though Wi-Fi Direct doesn't require an
46+
Internet connection, it uses standard Java sockets, and using these in Android
47+
requires the requested permissions.</p>
48+
49+
<pre>
50+
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
51+
package="com.example.android.nsdchat"
52+
...
53+
54+
&lt;uses-permission
55+
android:required="true"
56+
android:name="android.permission.ACCESS_WIFI_STATE"/&gt;
57+
&lt;uses-permission
58+
android:required="true"
59+
android:name="android.permission.CHANGE_WIFI_STATE"/&gt;
60+
&lt;uses-permission
61+
android:required="true"
62+
android:name="android.permission.INTERNET"/&gt;
63+
...
64+
</pre>
65+
66+
<h2 id="register">Add a Local Service</h2>
67+
<p>If you're providing a local service, you need to register it for
68+
service discovery. Once your local service is registered, the framework
69+
automatically responds to service discovery requests from peers.</p>
70+
71+
<p>To create a local service:</p>
72+
73+
<ol>
74+
<li>Create a
75+
{@link android.net.wifi.p2p.nsd.WifiP2pServiceInfo} object.</li>
76+
<li>Populate it with information about your service.</li>
77+
<li>Call {@link
78+
android.net.wifi.p2p.WifiP2pManager#addLocalService(WifiP2pManager.Channel,
79+
WifiP2pServiceInfo, WifiP2pManager.ActionListener) addLocalService()} to register the local
80+
service for service discovery.</li>
81+
</ol>
82+
83+
<pre>
84+
private void startRegistration() {
85+
// Create a string map containing information about your service.
86+
Map<String,String> record = new HashMap<String,String>();
87+
record.put("listenport", String.valueOf(SERVER_PORT));
88+
record.put("buddyname", "John Doe" + (int) (Math.random() * 1000));
89+
record.put("available", "visible");
90+
91+
// Service information. Pass it an instance name, service type
92+
// _protocol._transportlayer , and the map containing
93+
// information other devices will want once they connect to this one.
94+
WifiP2pDnsSdServiceInfo serviceInfo =
95+
WifiP2pDnsSdServiceInfo.newInstance("_test", "_presence._tcp", record);
96+
97+
// Add the local service, sending the service info, network channel,
98+
// and listener that will be used to indicate success or failure of
99+
// the request.
100+
mManager.addLocalService(channel, serviceInfo, new ActionListener() {
101+
&#64;Override
102+
public void onSuccess() {
103+
// Command successful! Code isn't necessarily needed here,
104+
// Unless you want to update the UI or add logging statements.
105+
}
106+
107+
&#64;Override
108+
public void onFailure(int arg0) {
109+
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
110+
}
111+
});
112+
}
113+
</pre>
114+
115+
<h2 id="discover">Discover Nearby Services</h2>
116+
<p>Android uses callback methods to notify your application of available services, so
117+
the first thing to do is set those up. Create a {@link
118+
android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener} to listen for
119+
incoming records. This record can optionally be broadcast by other
120+
devices. When one comes in, copy the device address and any other
121+
relevant information you want into a data structure external to the current
122+
method, so you can access it later. The following example assumes that the
123+
record contains a "buddyname" field, populated with the user's identity.</p>
124+
125+
<pre>
126+
final HashMap&lt;String, String&gt; buddies = new HashMap&lt;String, String&gt;();
127+
...
128+
private void discoverService() {
129+
DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
130+
&#64;Override
131+
/* Callback includes:
132+
* fullDomain: full domain name: e.g "printer._ipp._tcp.local."
133+
* record: TXT record dta as a map of key/value pairs.
134+
* device: The device running the advertised service.
135+
*/
136+
137+
public void onDnsSdTxtRecordAvailable(
138+
String fullDomain, Map<String,String> record, WifiP2pDevice device) {
139+
Log.d(TAG, "DnsSdTxtRecord available -" + record.toString());
140+
buddies.put(device.deviceAddress, record.get("buddyname"));
141+
}
142+
};
143+
...
144+
}
145+
</pre>
146+
147+
<p>To get the service information, create a {@link
148+
android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener}. This
149+
receives the actual description and connection information. The previous code
150+
snippet implemented a {@link java.util.Map} object to pair a device address with the buddy
151+
name. The service response listener uses this to link the DNS record with the
152+
corresponding service information. Once both
153+
listeners are implemented, add them to the {@link
154+
android.net.wifi.p2p.WifiP2pManager} using the {@link
155+
android.net.wifi.p2p.WifiP2pManager#setDnsSdResponseListeners(WifiP2pManager.Channel,
156+
WifiP2pManager.DnsSdServiceResponseListener,
157+
WifiP2pManager.DnsSdTxtRecordListener) setDnsSdResponseListeners()} method.</p>
158+
159+
<pre>
160+
private void discoverService() {
161+
...
162+
163+
DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
164+
&#64;Override
165+
public void onDnsSdServiceAvailable(String instanceName, String registrationType,
166+
WifiP2pDevice resourceType) {
167+
168+
// Update the device name with the human-friendly version from
169+
// the DnsTxtRecord, assuming one arrived.
170+
resourceType.deviceName = buddies
171+
.containsKey(resourceType.deviceAddress) ? buddies
172+
.get(resourceType.deviceAddress) : resourceType.deviceName;
173+
174+
// Add to the custom adapter defined specifically for showing
175+
// wifi devices.
176+
WiFiDirectServicesList fragment = (WiFiDirectServicesList) getFragmentManager()
177+
.findFragmentById(R.id.frag_peerlist);
178+
WiFiDevicesAdapter adapter = ((WiFiDevicesAdapter) fragment
179+
.getListAdapter());
180+
181+
adapter.add(resourceType);
182+
adapter.notifyDataSetChanged();
183+
Log.d(TAG, "onBonjourServiceAvailable " + instanceName);
184+
}
185+
};
186+
187+
mManager.setDnsSdResponseListeners(channel, servListener, txtListener);
188+
...
189+
}
190+
</pre>
191+
192+
<p>Now create a service request and call {@link
193+
android.net.wifi.p2p.WifiP2pManager#addServiceRequest(WifiP2pManager.Channel,
194+
WifiP2pServiceRequest, WifiP2pManager.ActionListener) addServiceRequest()}.
195+
This method also takes a listener to report success or failure.</p>
196+
197+
<pre>
198+
serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
199+
mManager.addServiceRequest(channel,
200+
serviceRequest,
201+
new ActionListener() {
202+
&#64;Override
203+
public void onSuccess() {
204+
// Success!
205+
}
206+
207+
&#64;Override
208+
public void onFailure(int code) {
209+
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
210+
}
211+
});
212+
</pre>
213+
214+
<p>Finally, make the call to {@link
215+
android.net.wifi.p2p.WifiP2pManager#discoverServices(WifiP2pManager.Channel,
216+
WifiP2pManager.ActionListener) discoverServices()}.</p>
217+
218+
<pre>
219+
mManager.discoverServices(channel, new ActionListener() {
220+
221+
&#64;Override
222+
public void onSuccess() {
223+
// Success!
224+
}
225+
226+
&#64;Override
227+
public void onFailure(int code) {
228+
// Command failed. Check for P2P_UNSUPPORTED, ERROR, or BUSY
229+
if (code == WifiP2pManager.P2P_UNSUPPORTED) {
230+
Log.d(TAG, "P2P isn't supported on this device.");
231+
else if(...)
232+
...
233+
}
234+
});
235+
</pre>
236+
237+
<p>If all goes well, hooray, you're done! If you encounter problems, remember
238+
that the asynchronous calls you've made take an
239+
{@link android.net.wifi.p2p.WifiP2pManager.ActionListener} as an argument, and
240+
this provides you with callbacks indicating success or failure. To diagnose
241+
problems, put debugging code in {@link
242+
android.net.wifi.p2p.WifiP2pManager.ActionListener#onFailure(int) onFailure()}. The error code
243+
provided by the method hints at the problem. Here are the possible error values
244+
and what they mean</p>
245+
<dl>
246+
<dt> {@link android.net.wifi.p2p.WifiP2pManager#P2P_UNSUPPORTED}</dt>
247+
<dd> Wi-Fi Direct isn't supported on the device running the app.</dd>
248+
<dt> {@link android.net.wifi.p2p.WifiP2pManager#BUSY}</dt>
249+
<dd> The system is to busy to process the request.</dd>
250+
<dt> {@link android.net.wifi.p2p.WifiP2pManager#ERROR}</dt>
251+
<dd> The operation failed due to an internal error.</dd>
252+
</dl>

0 commit comments

Comments
 (0)