Wi-Fi P2P 연결하기

Android 2014. 3. 4. 13:15

- Android 4.0(API Level 14) 부터 Wi-Fi P2P 연결 관련 API를 제공한다.

- 아래와 같은 퍼미션이 필요하다.

    <uses-permission
       
android:required="true"
       
android:name="android.permission.ACCESS_WIFI_STATE"/>
   
<uses-permission
       
android:required="true"
       
android:name="android.permission.CHANGE_WIFI_STATE"/>
   
<uses-permission
       
android:required="true"
       
android:name="android.permission.INTERNET"/>

- WifiP2pManager를 아래와 같이 초기화해준다. 생성된 WifiP2pManager.Channel를 통해 Wi-Fi P2P Framework에 접속하게 된다.

@Override

Channel mChannel;

public void onCreate(Bundle savedInstanceState) {
   
....
    mManager
= (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    mChannel
= mManager.initialize(this, getMainLooper(), null);
}

- BroadcastReceiver에 등록할 IntentFilter,이벤트를 처리할 onReceive(), 생명주기 관련 코드는 아래와 같이 작성한다.

private final IntentFilter intentFilter = new IntentFilter();
...
@Override
public void onCreate(Bundle savedInstanceState) {
   
super.onCreate(savedInstanceState);
    setContentView
(R.layout.main);

   
//  Indicates a change in the Wi-Fi P2P status.
    intentFilter
.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);

   
// Indicates a change in the list of available peers.
    intentFilter
.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);

   
// Indicates the state of Wi-Fi P2P connectivity has changed.
    intentFilter
.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);

   
// Indicates this device's details have changed.
    intentFilter
.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

   
...
}

    @Override
   
public void onReceive(Context context, Intent intent) {
       
String action = intent.getAction();
       
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
           
// Determine if Wifi P2P mode is enabled or not, alert
           
// the Activity.
           
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
           
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                activity
.setIsWifiP2pEnabled(true);
           
} else {
                activity
.setIsWifiP2pEnabled(false);
           
}
       
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {

           
// The peer list has changed!  We should probably do something about
           
// that.

       
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {

           
// Connection state changed!  We should probably do something about
           
// that.

       
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
           
DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
                   
.findFragmentById(R.id.frag_list);
            fragment
.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
                   
WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));

       
}
   
}

    /** register the BroadcastReceiver with the intent values to be matched */
   
@Override
   
public void onResume() {
       
super.onResume();
        receiver
= new WiFiDirectBroadcastReceiver(mManager, mChannel, this);
        registerReceiver
(receiver, intentFilter);
   
}

   
@Override
   
public void onPause() {
       
super.onPause();
        unregisterReceiver
(receiver);
   
}

- 주변에 있는 Peer들을 검색하기 위해서는 discoverPeers()를 아래와 같이 호출한다. 이것은 검색 시작을 의미하며, 실제로 Peer들이 검색되었을 때는 위의 onReceive()에서 판단한다.

mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {

       
@Override
       
public void onSuccess() {
           
// Code for when the discovery initiation is successful goes here.
           
// No services have actually been discovered yet, so this method
           
// can often be left blank.  Code for peer discovery goes in the
           
// onReceive method, detailed below.
       
}

       
@Override
       
public void onFailure(int reasonCode) {
           
// Code for when the discovery initiation fails goes here.
           
// Alert the user that something went wrong.
       
}
});

- 실제 Peer들의 목록을 가져오기 위해서는 위 onReceive()의 WIFI_P2P_PEERS_CHANGED_ACTION에서 requestPeers()를 호출해야 한다.

public void onReceive(Context context, Intent intent) {
   
...
   
else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {

       
// Request available peers from the wifi p2p manager. This is an
       
// asynchronous call and the calling activity is notified with a
       
// callback on PeerListListener.onPeersAvailable()
       
if (mManager != null) {
            mManager
.requestPeers(mChannel, peerListListener);
       
}
       
Log.d(WiFiDirectActivity.TAG, "P2P peers changed");
   
}...
}
    private List peers = new ArrayList();
   
...

   
private PeerListListener peerListListener = new PeerListListener() {
       
@Override
       
public void onPeersAvailable(WifiP2pDeviceList peerList) {

           
// Out with the old, in with the new.
            peers
.clear();
            peers
.addAll(peerList.getDeviceList());

           
// If an AdapterView is backed by this data, notify it
           
// of the change.  For instance, if you have a ListView of available
           
// peers, trigger an update.
           
((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
           
if (peers.size() == 0) {
               
Log.d(WiFiDirectActivity.TAG, "No devices found");
               
return;
           
}
       
}
   
}

- Peer에 접속하기 위해서 아래와 같이 connect()를 호출한다.

    @Override
   
public void connect() {
       
// Picking the first device found on the network.
       
WifiP2pDevice device = peers.get(0);

       
WifiP2pConfig config = new WifiP2pConfig();
        config
.deviceAddress = device.deviceAddress;
        config
.wps.setup = WpsInfo.PBC;

        mManager
.connect(mChannel, config, new ActionListener() {

           
@Override
           
public void onSuccess() {
               
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
           
}

           
@Override
           
public void onFailure(int reason) {
               
Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
                       
Toast.LENGTH_SHORT).show();
           
}
       
});
   
}

- 접속이 되면 관련 정보를 얻기 위해 onReceive()에서 아래와 같이 처리한다.

        ...
       
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {

           
if (mManager == null) {
               
return;
           
}

           
NetworkInfo networkInfo = (NetworkInfo) intent
                   
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);

           
if (networkInfo.isConnected()) {

               
// We are connected with the other device, request connection
               
// info to find group owner IP

                mManager
.requestConnectionInfo(mChannel, connectionListener);
           
}
           
...

- 위의 WifiP2pManager.ConnectionInfoListener는 아래와 같다. 자신이 "group owner"이면 서버 역할을 해야 한다.

    @Override
   
public void onConnectionInfoAvailable(final WifiP2pInfo info) {

       
// InetAddress from WifiP2pInfo struct.
       
InetAddress groupOwnerAddress = info.groupOwnerAddress.getHostAddress());

       
// After the group negotiation, we can determine the group owner.
       
if (info.groupFormed && info.isGroupOwner) {
           
// Do whatever tasks are specific to the group owner.
           
// One common case is creating a server thread and accepting
           
// incoming connections.
       
} else if (info.groupFormed) {
           
// The other device acts as the client. In this case,
           
// you'll want to create a client thread that connects to the group
           
// owner.
       
}
   
}

- 이후에 상대의 IP에 접속하여 통신을 하면 된다.


출처 : http://developer.android.com/

설정

트랙백

댓글