43 | * With Wroup Library you can register a service in the current local network to be discovered by 44 | * other devices. When a service is registered a WiFi P2P Group is created, we know it as Wroup ;) 45 | *
46 | * WroupService is the group owner and it manages the group changes (connections and
47 | * disconnections). When a new client is connected/disconnected the service device notify to the
48 | * other devices connected.
49 | *
50 | * To register a service you must do the following: 51 | *
52 | * {@code
53 | *
54 | * wiFiP2PService = WroupService.getInstance(getApplicationContext());
55 | * wiFiP2PService.registerService(groupName, new ServiceRegisteredListener() {
56 | *
57 | * public void onSuccessServiceRegistered() {
58 | * Log.i(TAG, "Wroup created. Waiting for client connections...");
59 | * }
60 | *
61 | * public void onErrorServiceRegistered(WiFiP2PError wiFiP2PError) {
62 | * Log.e(TAG, "Error creating group");
63 | * }
64 | *
65 | * });
66 | * }
67 | *
68 | */
69 | public class WroupService implements PeerConnectedListener {
70 |
71 |
72 | private static final String TAG = WroupService.class.getSimpleName();
73 |
74 | private static final String SERVICE_TYPE = "_wroup._tcp";
75 | public static final String SERVICE_PORT_PROPERTY = "SERVICE_PORT";
76 | public static final Integer SERVICE_PORT_VALUE = 9999;
77 | public static final String SERVICE_NAME_PROPERTY = "SERVICE_NAME";
78 | public static final String SERVICE_NAME_VALUE = "WROUP";
79 | public static final String SERVICE_GROUP_NAME = "GROUP_NAME";
80 |
81 | private static WroupService instance;
82 |
83 | private DataReceivedListener dataReceivedListener;
84 | private ClientConnectedListener clientConnectedListener;
85 | private ClientDisconnectedListener clientDisconnectedListener;
86 | private MapWroupService instance. If the instance doesn't exist yet, it's
99 | * created and returned.
100 | *
101 | * @param context The application context.
102 | * @return The actual WroupService instance.
103 | */
104 | public static WroupService getInstance(Context context) {
105 | if (instance == null) {
106 | instance = new WroupService(context);
107 | }
108 | return instance;
109 | }
110 |
111 | /**
112 | * Start a Wroup service registration in the actual local network with the name indicated in
113 | * the arguments. When te service is registered the method
114 | * {@link ServiceRegisteredListener#onSuccessServiceRegistered()} is called.
115 | *
116 | * @param groupName The name of the group that want to be created.
117 | * @param serviceRegisteredListener The ServiceRegisteredListener to notify
118 | * registration changes.
119 | */
120 | public void registerService(String groupName, ServiceRegisteredListener serviceRegisteredListener) {
121 | registerService(groupName, null, serviceRegisteredListener);
122 | }
123 |
124 | /**
125 | * Start a Wroup service registration in the actual local network with the name indicated in
126 | * the arguments. When te service is registered the method
127 | * {@link ServiceRegisteredListener#onSuccessServiceRegistered()} is called.
128 | *
129 | * @param groupName The name of the group that want to be created.
130 | * @param customProperties A Map of custom properties which will be registered with the
131 | * service. This properties can be accessed by the client devices
132 | * when the service is discovered.
133 | * @param serviceRegisteredListener The ServiceRegisteredListener to notify
134 | * registration changes.
135 | */
136 | public void registerService(String groupName, MapDataReceivedListener to notify data entries.
221 | */
222 | public void setDataReceivedListener(DataReceivedListener dataReceivedListener) {
223 | this.dataReceivedListener = dataReceivedListener;
224 | }
225 |
226 | /**
227 | * Set the listener to know when a client has been disconnected from the group.
228 | *
229 | * @param clientDisconnectedListener The ClientDisconnectedListener to notify
230 | * client disconnections.
231 | */
232 | public void setClientDisconnectedListener(ClientDisconnectedListener clientDisconnectedListener) {
233 | this.clientDisconnectedListener = clientDisconnectedListener;
234 | }
235 |
236 | /**
237 | * Set the listener to know when a new client is registered in the group.
238 | *
239 | * @param clientConnectedListener The ClientConnectedListener to notify new
240 | * connections in the group.
241 | */
242 | public void setClientConnectedListener(ClientConnectedListener clientConnectedListener) {
243 | this.clientConnectedListener = clientConnectedListener;
244 | }
245 |
246 | @Override
247 | public void onPeerConnected(WifiP2pInfo wifiP2pInfo) {
248 | Log.i(TAG, "OnPeerConnected...");
249 |
250 | if (wifiP2pInfo.groupFormed && wifiP2pInfo.isGroupOwner) {
251 | Log.i(TAG, "I am the group owner");
252 | Log.i(TAG, "My addess is: " + wifiP2pInfo.groupOwnerAddress.getHostAddress());
253 | }
254 | }
255 |
256 | /**
257 | * Send a message to all the devices connected to the group.
258 | *
259 | * @param message The message to be sent.
260 | */
261 | public void sendMessageToAllClients(final MessageWrapper message) {
262 | for (WroupDevice clientDevice : clientsConnected.values()) {
263 | sendMessage(clientDevice, message);
264 | }
265 | }
266 |
267 | /**
268 | * Send a message to the desired device who it's connected in the group.
269 | *
270 | * @param device The receiver of the message.
271 | * @param message The message to be sent.
272 | */
273 | public void sendMessage(final WroupDevice device, MessageWrapper message) {
274 | // Set the actual device to the message
275 | message.setWroupDevice(wiFiP2PInstance.getThisDevice());
276 |
277 | new AsyncTask52 | * Wroup Library will allow you to create a "Server" device and multiple "Client" devices. The 53 | * {@link WroupService} can register a service which could be discover by the multiple client 54 | * devices. The client will search the Wroup services registered in the local network and could 55 | * connect to any ot them. 56 | *
57 | * WroupClient only discover Wroup services, can exist multiple services registered with WiFi-P2P in 58 | * the same local network but only a WroupClient instance will found services registered by a 59 | * WroupService device. 60 | *
61 | * To discover the Wroup services registered you only need to do the following: 62 | *
63 | * {@code wiFiP2PClient = WroupClient.getInstance(getApplicationContext());
64 | * wiFiP2PClient.discoverServices(5000L, new ServiceDiscoveredListener() {
65 | *
66 | * public void onNewServiceDeviceDiscovered(WroupServiceDevice serviceDevice) {
67 | * Log.i(TAG, "New service found:");
68 | * Log.i(TAG, "\tName: " + serviceDevice.getDeviceName());
69 | * }
70 | *
71 | * public void onFinishServiceDeviceDiscovered(List serviceDevices) {
72 | * Log.i(TAG, "Found '" + serviceDevices.size() + "' services");
73 | * }
74 | *
75 | * public void onError(WiFiP2PError wiFiP2PError) {
76 | * Toast.makeText(getApplicationContext(), "Error searching groups: " + wiFiP2PError, Toast.LENGTH_LONG).show();
77 | * }
78 | * });
79 | * }
80 | *
81 | * Once that you have the desired service to which connect you must call to
82 | * {@link #connectToService(WroupServiceDevice, ServiceConnectedListener)} passing as argument the
83 | * appropiate {@link WroupServiceDevice} obtained in the discoverServices() call.
84 | */
85 | public class WroupClient implements PeerConnectedListener, ServiceDisconnectedListener {
86 |
87 | private static final String TAG = WroupClient.class.getSimpleName();
88 |
89 | private static WroupClient instance;
90 |
91 | private List
131 | * Before you start to discover services you must to register the WiFiDirectBroadcastReceiver
132 | * in the onResume() method of your activity.
133 | *
134 | * @param discoveringTimeInMillis The time in milliseconds to search for registered Wroup services.
135 | * @param serviceDiscoveredListener The listener to notify changes of the services found by the client.
136 | * @see com.abemart.wroup.common.WiFiDirectBroadcastReceiver
137 | */
138 | public void discoverServices(Long discoveringTimeInMillis, final ServiceDiscoveredListener serviceDiscoveredListener) {
139 | serviceDevices.clear();
140 |
141 | // We need to start discovering peers to activate the service search
142 | wiFiP2PInstance.startPeerDiscovering();
143 |
144 | setupDnsListeners(wiFiP2PInstance, serviceDiscoveredListener);
145 | WiFiDirectUtils.clearServiceRequest(wiFiP2PInstance);
146 |
147 | WifiP2pServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
148 | wiFiP2PInstance.getWifiP2pManager().addServiceRequest(wiFiP2PInstance.getChannel(), serviceRequest, new WifiP2pManager.ActionListener() {
149 |
150 | @Override
151 | public void onSuccess() {
152 | Log.d(TAG, "Success adding service request");
153 | }
154 |
155 | @Override
156 | public void onFailure(int reason) {
157 | WiFiP2PError wiFiP2PError = WiFiP2PError.fromReason(reason);
158 | Log.e(TAG, "Error adding service request. Reason: " + WiFiP2PError.fromReason(reason));
159 | serviceDiscoveredListener.onError(wiFiP2PError);
160 | }
161 |
162 | });
163 |
164 | wiFiP2PInstance.getWifiP2pManager().discoverServices(wiFiP2PInstance.getChannel(), new WifiP2pManager.ActionListener() {
165 |
166 | @Override
167 | public void onSuccess() {
168 | Log.d(TAG, "Success initiating disconvering services");
169 | }
170 |
171 | @Override
172 | public void onFailure(int reason) {
173 | WiFiP2PError wiFiP2PError = WiFiP2PError.fromReason(reason);
174 | if (wiFiP2PError != null) {
175 | Log.e(TAG, "Error discovering services. Reason: " + wiFiP2PError.name());
176 | serviceDiscoveredListener.onError(wiFiP2PError);
177 | }
178 | }
179 |
180 | });
181 |
182 | Handler handler = new Handler();
183 | handler.postDelayed(new Runnable() {
184 | @Override
185 | public void run() {
186 | serviceDiscoveredListener.onFinishServiceDeviceDiscovered(serviceDevices);
187 | }
188 | }, discoveringTimeInMillis);
189 | }
190 |
191 | /**
192 | * Start the connection with the WroupServiceDevice passed by argument. When the
193 | * connection is stablished with the device service the {@link ServiceConnectedListener#onServiceConnected(WroupDevice)}
194 | * method is called.
195 | *
196 | * When the client is connected to the service, it's connected to the WiFi Direct Group created
197 | * by the service device. Once the client belongs to the "Wroup" (group), it can know when a new
198 | * client is connected or disconnected from it.
199 | *
200 | * @param serviceDevice The WroupServiceDevice with you want to connect.
201 | * @param serviceConnectedListener The listener to know when the client device is connected to
202 | * the desired service.
203 | */
204 | public void connectToService(final WroupServiceDevice serviceDevice, ServiceConnectedListener serviceConnectedListener) {
205 | this.serviceDevice = serviceDevice;
206 | this.serviceConnectedListener = serviceConnectedListener;
207 |
208 | WifiP2pConfig wifiP2pConfig = new WifiP2pConfig();
209 | wifiP2pConfig.deviceAddress = serviceDevice.getDeviceMac();
210 |
211 | wiFiP2PInstance.getWifiP2pManager().connect(wiFiP2PInstance.getChannel(), wifiP2pConfig, new WifiP2pManager.ActionListener() {
212 | @Override
213 | public void onSuccess() {
214 | Log.i(TAG, "Initiated connection to device: ");
215 | Log.i(TAG, "\tDevice name: " + serviceDevice.getDeviceName());
216 | Log.i(TAG, "\tDevice address: " + serviceDevice.getDeviceMac());
217 | }
218 |
219 | @Override
220 | public void onFailure(int reason) {
221 | Log.e(TAG, "Fail initiation connection. Reason: " + WiFiP2PError.fromReason(reason));
222 | }
223 | });
224 | }
225 |
226 | /**
227 | * Set the listener to know when data is received from the service device or other client devices
228 | * connected to the same group.
229 | *
230 | * @param dataReceivedListener The DataReceivedListener to notify data entries.
231 | */
232 | public void setDataReceivedListener(DataReceivedListener dataReceivedListener) {
233 | this.dataReceivedListener = dataReceivedListener;
234 | }
235 |
236 | /**
237 | * Set the listener to notify when the service device has been disconnected.
238 | *
239 | * @param serviceDisconnectedListener The ServiceDisconnectedListener to notify
240 | * service device disconnections.
241 | */
242 | public void setServerDisconnetedListener(ServiceDisconnectedListener serviceDisconnectedListener) {
243 | this.serviceDisconnectedListener = serviceDisconnectedListener;
244 | }
245 |
246 | /**
247 | * Set the listener to know when a new client is registered in the actual group.
248 | *
249 | * @param clientConnectedListener The ClientConnectedListener to notify new
250 | * connections in the group.
251 | */
252 | public void setClientConnectedListener(ClientConnectedListener clientConnectedListener) {
253 | this.clientConnectedListener = clientConnectedListener;
254 | }
255 |
256 | /**
257 | * Set the listener to know when a client has been disconnected from the group.
258 | *
259 | * @param clientDisconnectedListener The ClientDisconnectedListener to notify
260 | * client disconnections.
261 | */
262 | public void setClientDisconnectedListener(ClientDisconnectedListener clientDisconnectedListener) {
263 | this.clientDisconnectedListener = clientDisconnectedListener;
264 | }
265 |
266 | @Override
267 | public void onPeerConnected(WifiP2pInfo wifiP2pInfo) {
268 | Log.i(TAG, "OnPeerConnected...");
269 |
270 | if (wifiP2pInfo.groupFormed && wifiP2pInfo.isGroupOwner) {
271 | Log.e(TAG, "I shouldn't be the group owner, I'am a client!");
272 | }
273 |
274 | if (wifiP2pInfo.groupFormed && serviceDevice != null && !isRegistered) {
275 | serviceDevice.setDeviceServerSocketIP(wifiP2pInfo.groupOwnerAddress.getHostAddress());
276 | Log.i(TAG, "The Server Address is: " + wifiP2pInfo.groupOwnerAddress.getHostAddress());
277 |
278 | // We are connected to the server. Create a server socket to receive messages
279 | createServerSocket();
280 |
281 | // FIXME - Change this into a server socket creation listener or similar
282 | // Wait 2 seconds for the server socket creation
283 | Handler handler = new Handler();
284 | handler.postDelayed(new Runnable() {
285 | public void run() {
286 | // We send the negotiation message to the server
287 | sendServerRegistrationMessage();
288 | if (serviceConnectedListener != null) {
289 | serviceConnectedListener.onServiceConnected(serviceDevice);
290 | }
291 |
292 | isRegistered = true;
293 | }
294 | }, 2000);
295 | }
296 | }
297 |
298 | @Override
299 | public void onServerDisconnectedListener() {
300 | // If the server is disconnected the client is cleared
301 | disconnect();
302 |
303 | if (serviceDisconnectedListener != null) {
304 | serviceDisconnectedListener.onServerDisconnectedListener();
305 | }
306 | }
307 |
308 | /**
309 | * Send a message to the service device.
310 | *
311 | * @param message The message to be sent.
312 | */
313 | public void sendMessageToServer(MessageWrapper message) {
314 | sendMessage(serviceDevice, message);
315 | }
316 |
317 | /**
318 | * Send a message to all the devices connected to the group, including the service device.
319 | *
320 | * @param message The message to be sent.
321 | */
322 | public void sendMessageToAllClients(MessageWrapper message) {
323 | sendMessageToServer(message);
324 |
325 | for (WroupDevice device : clientsConnected.values()) {
326 | if (!device.getDeviceMac().equals(wiFiP2PInstance.getThisDevice().getDeviceMac())) {
327 | sendMessage(device, message);
328 | }
329 | }
330 | }
331 |
332 | /**
333 | * Send a message to the desired device who it's connected in the group.
334 | *
335 | * @param device The receiver of the message.
336 | * @param message The message to be sent.
337 | */
338 | public void sendMessage(final WroupDevice device, MessageWrapper message) {
339 | // Set the actual device to the message
340 | message.setWroupDevice(wiFiP2PInstance.getThisDevice());
341 |
342 | new AsyncTask