1 2 package com.example.android.wifidirect.discovery; 3 4 import android.app.Activity; 5 import android.app.Fragment; 6 import android.content.BroadcastReceiver; 7 import android.content.Context; 8 import android.content.IntentFilter; 9 import android.net.wifi.WpsInfo; 10 import android.net.wifi.p2p.WifiP2pConfig; 11 import android.net.wifi.p2p.WifiP2pDevice; 12 import android.net.wifi.p2p.WifiP2pInfo; 13 import android.net.wifi.p2p.WifiP2pManager; 14 import android.net.wifi.p2p.WifiP2pManager.ActionListener; 15 import android.net.wifi.p2p.WifiP2pManager.Channel; 16 import android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener; 17 import android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener; 18 import android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener; 19 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo; 20 import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest; 21 import android.os.Bundle; 22 import android.os.Handler; 23 import android.os.Message; 24 import android.util.Log; 25 import android.view.View; 26 import android.widget.TextView; 27 28 import com.example.android.wifidirect.discovery.WiFiChatFragment.MessageTarget; 29 import com.example.android.wifidirect.discovery.WiFiDirectServicesList.DeviceClickListener; 30 import com.example.android.wifidirect.discovery.WiFiDirectServicesList.WiFiDevicesAdapter; 31 32 import java.io.IOException; 33 import java.util.HashMap; 34 import java.util.Map; 35 36 /** 37 * The main activity for the sample. This activity registers a local service and 38 * perform discovery over Wi-Fi p2p network. It also hosts a couple of fragments 39 * to manage chat operations. When the app is launched, the device publishes a 40 * chat service and also tries to discover services published by other peers. On 41 * selecting a peer published service, the app initiates a Wi-Fi P2P (Direct) 42 * connection with the peer. On successful connection with a peer advertising 43 * the same service, the app opens up sockets to initiate a chat. 44 * {@code WiFiChatFragment} is then added to the the main activity which manages 45 * the interface and messaging needs for a chat session. 46 */ 47 public class WiFiServiceDiscoveryActivity extends Activity implements 48 DeviceClickListener, Handler.Callback, MessageTarget, 49 ConnectionInfoListener { 50 51 public static final String TAG = "wifidirectdemo"; 52 53 // TXT RECORD properties 54 public static final String TXTRECORD_PROP_AVAILABLE = "available"; 55 public static final String SERVICE_INSTANCE = "_wifidemotest"; 56 public static final String SERVICE_REG_TYPE = "_presence._tcp"; 57 58 public static final int MESSAGE_READ = 0x400 + 1; 59 public static final int MY_HANDLE = 0x400 + 2; 60 private WifiP2pManager manager; 61 62 static final int SERVER_PORT = 4545; 63 64 private final IntentFilter intentFilter = new IntentFilter(); 65 private Channel channel; 66 private BroadcastReceiver receiver = null; 67 private WifiP2pDnsSdServiceRequest serviceRequest; 68 69 private Handler handler = new Handler(this); 70 private WiFiChatFragment chatFragment; 71 private WiFiDirectServicesList servicesList; 72 73 private TextView statusTxtView; 74 getHandler()75 public Handler getHandler() { 76 return handler; 77 } 78 setHandler(Handler handler)79 public void setHandler(Handler handler) { 80 this.handler = handler; 81 } 82 83 /** Called when the activity is first created. */ 84 @Override onCreate(Bundle savedInstanceState)85 public void onCreate(Bundle savedInstanceState) { 86 super.onCreate(savedInstanceState); 87 setContentView(R.layout.main); 88 statusTxtView = (TextView) findViewById(R.id.status_text); 89 90 intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 91 intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 92 intentFilter 93 .addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 94 intentFilter 95 .addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 96 97 manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); 98 channel = manager.initialize(this, getMainLooper(), null); 99 startRegistrationAndDiscovery(); 100 101 servicesList = new WiFiDirectServicesList(); 102 getFragmentManager().beginTransaction() 103 .add(R.id.container_root, servicesList, "services").commit(); 104 105 } 106 107 @Override onRestart()108 protected void onRestart() { 109 Fragment frag = getFragmentManager().findFragmentByTag("services"); 110 if (frag != null) { 111 getFragmentManager().beginTransaction().remove(frag).commit(); 112 } 113 super.onRestart(); 114 } 115 116 @Override onStop()117 protected void onStop() { 118 if (manager != null && channel != null) { 119 manager.removeGroup(channel, new ActionListener() { 120 121 @Override 122 public void onFailure(int reasonCode) { 123 Log.d(TAG, "Disconnect failed. Reason :" + reasonCode); 124 } 125 126 @Override 127 public void onSuccess() { 128 } 129 130 }); 131 } 132 super.onStop(); 133 } 134 135 /** 136 * Registers a local service and then initiates a service discovery 137 */ startRegistrationAndDiscovery()138 private void startRegistrationAndDiscovery() { 139 Map<String, String> record = new HashMap<String, String>(); 140 record.put(TXTRECORD_PROP_AVAILABLE, "visible"); 141 142 WifiP2pDnsSdServiceInfo service = WifiP2pDnsSdServiceInfo.newInstance( 143 SERVICE_INSTANCE, SERVICE_REG_TYPE, record); 144 manager.addLocalService(channel, service, new ActionListener() { 145 146 @Override 147 public void onSuccess() { 148 appendStatus("Added Local Service"); 149 } 150 151 @Override 152 public void onFailure(int error) { 153 appendStatus("Failed to add a service"); 154 } 155 }); 156 157 discoverService(); 158 159 } 160 discoverService()161 private void discoverService() { 162 163 /* 164 * Register listeners for DNS-SD services. These are callbacks invoked 165 * by the system when a service is actually discovered. 166 */ 167 168 manager.setDnsSdResponseListeners(channel, 169 new DnsSdServiceResponseListener() { 170 171 @Override 172 public void onDnsSdServiceAvailable(String instanceName, 173 String registrationType, WifiP2pDevice srcDevice) { 174 175 // A service has been discovered. Is this our app? 176 177 if (instanceName.equalsIgnoreCase(SERVICE_INSTANCE)) { 178 179 // update the UI and add the item the discovered 180 // device. 181 WiFiDirectServicesList fragment = (WiFiDirectServicesList) getFragmentManager() 182 .findFragmentByTag("services"); 183 if (fragment != null) { 184 WiFiDevicesAdapter adapter = ((WiFiDevicesAdapter) fragment 185 .getListAdapter()); 186 WiFiP2pService service = new WiFiP2pService(); 187 service.device = srcDevice; 188 service.instanceName = instanceName; 189 service.serviceRegistrationType = registrationType; 190 adapter.add(service); 191 adapter.notifyDataSetChanged(); 192 Log.d(TAG, "onBonjourServiceAvailable " 193 + instanceName); 194 } 195 } 196 197 } 198 }, new DnsSdTxtRecordListener() { 199 200 /** 201 * A new TXT record is available. Pick up the advertised 202 * buddy name. 203 */ 204 @Override 205 public void onDnsSdTxtRecordAvailable( 206 String fullDomainName, Map<String, String> record, 207 WifiP2pDevice device) { 208 Log.d(TAG, 209 device.deviceName + " is " 210 + record.get(TXTRECORD_PROP_AVAILABLE)); 211 } 212 }); 213 214 // After attaching listeners, create a service request and initiate 215 // discovery. 216 serviceRequest = WifiP2pDnsSdServiceRequest.newInstance(); 217 manager.addServiceRequest(channel, serviceRequest, 218 new ActionListener() { 219 220 @Override 221 public void onSuccess() { 222 appendStatus("Added service discovery request"); 223 } 224 225 @Override 226 public void onFailure(int arg0) { 227 appendStatus("Failed adding service discovery request"); 228 } 229 }); 230 manager.discoverServices(channel, new ActionListener() { 231 232 @Override 233 public void onSuccess() { 234 appendStatus("Service discovery initiated"); 235 } 236 237 @Override 238 public void onFailure(int arg0) { 239 appendStatus("Service discovery failed"); 240 241 } 242 }); 243 } 244 245 @Override connectP2p(WiFiP2pService service)246 public void connectP2p(WiFiP2pService service) { 247 WifiP2pConfig config = new WifiP2pConfig(); 248 config.deviceAddress = service.device.deviceAddress; 249 config.wps.setup = WpsInfo.PBC; 250 if (serviceRequest != null) 251 manager.removeServiceRequest(channel, serviceRequest, 252 new ActionListener() { 253 254 @Override 255 public void onSuccess() { 256 } 257 258 @Override 259 public void onFailure(int arg0) { 260 } 261 }); 262 263 manager.connect(channel, config, new ActionListener() { 264 265 @Override 266 public void onSuccess() { 267 appendStatus("Connecting to service"); 268 } 269 270 @Override 271 public void onFailure(int errorCode) { 272 appendStatus("Failed connecting to service"); 273 } 274 }); 275 } 276 277 @Override handleMessage(Message msg)278 public boolean handleMessage(Message msg) { 279 switch (msg.what) { 280 case MESSAGE_READ: 281 byte[] readBuf = (byte[]) msg.obj; 282 // construct a string from the valid bytes in the buffer 283 String readMessage = new String(readBuf, 0, msg.arg1); 284 Log.d(TAG, readMessage); 285 (chatFragment).pushMessage("Buddy: " + readMessage); 286 break; 287 288 case MY_HANDLE: 289 Object obj = msg.obj; 290 (chatFragment).setChatManager((ChatManager) obj); 291 292 } 293 return true; 294 } 295 296 @Override onResume()297 public void onResume() { 298 super.onResume(); 299 receiver = new WiFiDirectBroadcastReceiver(manager, channel, this); 300 registerReceiver(receiver, intentFilter); 301 } 302 303 @Override onPause()304 public void onPause() { 305 super.onPause(); 306 unregisterReceiver(receiver); 307 } 308 309 @Override onConnectionInfoAvailable(WifiP2pInfo p2pInfo)310 public void onConnectionInfoAvailable(WifiP2pInfo p2pInfo) { 311 Thread handler = null; 312 /* 313 * The group owner accepts connections using a server socket and then spawns a 314 * client socket for every client. This is handled by {@code 315 * GroupOwnerSocketHandler} 316 */ 317 318 if (p2pInfo.isGroupOwner) { 319 Log.d(TAG, "Connected as group owner"); 320 try { 321 handler = new GroupOwnerSocketHandler( 322 ((MessageTarget) this).getHandler()); 323 handler.start(); 324 } catch (IOException e) { 325 Log.d(TAG, 326 "Failed to create a server thread - " + e.getMessage()); 327 return; 328 } 329 } else { 330 Log.d(TAG, "Connected as peer"); 331 handler = new ClientSocketHandler( 332 ((MessageTarget) this).getHandler(), 333 p2pInfo.groupOwnerAddress); 334 handler.start(); 335 } 336 chatFragment = new WiFiChatFragment(); 337 getFragmentManager().beginTransaction() 338 .replace(R.id.container_root, chatFragment).commit(); 339 statusTxtView.setVisibility(View.GONE); 340 } 341 appendStatus(String status)342 public void appendStatus(String status) { 343 String current = statusTxtView.getText().toString(); 344 statusTxtView.setText(current + "\n" + status); 345 } 346 } 347