Home | History | Annotate | Download | only in discovery
      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 
     75     public Handler getHandler() {
     76         return handler;
     77     }
     78 
     79     public void setHandler(Handler handler) {
     80         this.handler = handler;
     81     }
     82 
     83     /** Called when the activity is first created. */
     84     @Override
     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
    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
    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      */
    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 
    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
    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
    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
    297     public void onResume() {
    298         super.onResume();
    299         receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
    300         registerReceiver(receiver, intentFilter);
    301     }
    302 
    303     @Override
    304     public void onPause() {
    305         super.onPause();
    306         unregisterReceiver(receiver);
    307     }
    308 
    309     @Override
    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 
    342     public void appendStatus(String status) {
    343         String current = statusTxtView.getText().toString();
    344         statusTxtView.setText(current + "\n" + status);
    345     }
    346 }
    347