글
Wi-Fi P2P 연결하기
- 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 Listpeers = 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/