Wi-Fi Peer-to-Peer
Wi-Fi对等网络(P2P),让Android 4.0(API级别14)或相应的硬件更高版本的设备直接连接到通过Wi-Fi对方没有中间接入点(Android的无线网络连接的P2P架构符合在Wi-Fi联盟的Wi-Fi直™认证计划)。使用这些API,你可以发现并连接到其他设备时,每个设备支持Wi-Fi P2P,然后在沟通跨越距离迅速连接比蓝牙连接更长的时间。这是为使用户之间共享数据的应用,如一个多人游戏或相片共享应用是有用的。
在Wi-Fi P2P的API包括以下主要部分:
方法,使您可以发现,请求,并连接到同龄人在WifiP2pManager类中定义。
监听器,让您得到通知的WifiP2pManager方法调用的成功或失败。当调用WifiP2pManager方法,每个方法可接收通过作为参数的特定监听器。
通知您通过了Wi-Fi的P2P架构,检测的特定事件,如丢弃连接或新发现的同行意图。
你经常使用这些API的这三个主要组件在一起。例如,你可以提供一个WifiP2pManager.ActionListener来调用discoverPeers(),这样就可以用ActionListener.onSuccess()和ActionListener.onFailure()方法来通知。如果discoverPeers()方法,发现同行名单已经改变了WIFI_P2P_PEERS_CHANGED_ACTION意图还播出。
API概述
该WifiP2pManager类提供了一些方法,让你的Wi-Fi硬件设备上做事情喜欢发现并连接到同龄人交流。以下操作可用:
表1.Wi网络P2P方法
方法说明
初始化()注册与Wi-Fi无线架构应用。这必须调用任何其它Wi-Fi点对点方法之前被调用。
连接()启动与指定配置的设备对等网络连接。
cancelConnect()取消任何正在进行的对等网络组协商。
requestConnectInfo()请求的设备的连接信息。
createGroup()创建一个对等网络组与当前设备为组拥有者。
removeGroup()删除当前对等网络组。
requestGroupInfo()请求的对等体组的信息。
discoverPeers()发起对端发现
requestPeers()请求发现同行的当前列表。
WifiP2pManager方法,让你在听众传递,从而使无线网络的P2P架构可以通知您的呼叫状态的活动。使用该听众的可用侦听器接口和相应的WifiP2pManager方法调用在下表中描述:
表2的Wi-Fi点对点监听器
监听器接口相关行动
WifiP2pManager.ActionListener连接(),cancelConnect(),createGroup(),removeGroup(),和discoverPeers()
WifiP2pManager.ChannelListener初始化()
WifiP2pManager.ConnectionInfoListener requestConnectInfo()
WifiP2pManager.GroupInfoListener requestGroupInfo()
WifiP2pManager.PeerListListener requestPeers()
在Wi-Fi点对点API定义的意图时,某些无线网络连接P2P的事件发生,广播,当一个新的对等发现或当设备的Wi-Fi状态的变化,如。您可以注册通过创建一个处理这些意图的广播接收器来接收应用程序中的这些意图:
表3.无线网络连接的P2P意图
意向描述
WIFI_P2P_CONNECTION_CHANGED_ACTION广播当设备的Wi-Fi连接的状态发生改变。
WIFI_P2P_PEERS_CHANGED_ACTION广播当你调用discoverPeers()。通常你想打电话requestPeers(),如果你处理这个意图在应用程序中得到同行的更新列表。
WIFI_P2P_STATE_CHANGED_ACTION广播时的Wi-Fi P2P启用或设备上禁用。
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION广播当设备的细节有变化,如设备的名称。
创建一个广播接收器Wi-Fi的P2P意图
广播接收器,您可以接收由意图Android系统播放,让您的应用程序能够对你有兴趣在响应事件是创建一个广播接收器处理的Wi-Fi点对点意图的基本步骤如下:
创建一个扩展的BroadcastReceiver类的类。对于类的构造函数,您很可能希望拥有的WifiP2pManager,WifiP2pManager.Channel,而这个广播接收器将在登记的活动性参数,这使得广播接收器发送更新到活动以及访问如果需要的无线网络连接的硬件和通信信道。
在广播接收器,检查你有兴趣的onReceive()的意图。执行取决于所接收到的意图的任何必要的行动。例如,如果广播接收器接收到WIFI_P2P_PEERS_CHANGED_ACTION意图,你可以调用requestPeers()方法来获得当前发现的对等的名单。
下面的代码演示如何创建一个典型的广播接收机。广播接收机需要一个WifiP2pManager对象作为参数的活动,并使用这两个类当广播接收机接收的意图,适当开展所需采取的行动:
/** * A BroadcastReceiver that notifies of important Wi-Fi p2p events. */ public class WiFiDirectBroadcastReceiver extends BroadcastReceiver { private WifiP2pManager mManager; private Channel mChannel; private MyWiFiActivity mActivity; public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel, MyWifiActivity activity) { super(); this.mManager = manager; this.mChannel = channel; this.mActivity = activity; } @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { // Check to see if Wi-Fi is enabled and notify appropriate activity } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { // Call WifiP2pManager.requestPeers() to get a list of current peers } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { // Respond to new connection or disconnections } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { // Respond to this device's wifi state changing } } }创建一个Wi-Fi的P2P应用
<uses-sdk android:minSdkVersion="14" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />请检查是否无线网络连接P2P是在和支持。一个好地方,检查这是你的广播接收器,当它接收到WIFI_STATE_CHANGED_ACTION意图。通知您的了Wi-Fi的P2P状态的活动,并作出相应的反应:
@Override public void onReceive(Context context, Intent intent) { ... String action = intent.getAction(); if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1); if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) { // Wifi P2P is enabled } else { // Wi-Fi P2P is not enabled } } ... }在活动的onCreate()方法,获得WifiP2pManager的一个实例,并通过调用初始化寄存器与Wi-Fi无线P2P架构您的应用程序()。该方法返回一个WifiP2pManager.Channel,用于连接您的应用程序在Wi-Fi的P2P架构。您还应该创建一个WifiP2pManager你的广播接收器的实例,并与WifiP2pManager.Channel你活动的参考对象一起。这使您的广播接收器来通知你感兴趣的事件的活动,并相应更新。它还允许在必要时操纵设备的Wi-Fi状态:
WifiP2pManager mManager; Channel mChannel; BroadcastReceiver mReceiver; ... @Override protected void onCreate(Bundle savedInstanceState){ ... mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); mChannel = mManager.initialize(this, getMainLooper(), null); mReceiver = new WiFiDirectBroadcastReceiver(mManager, mChannel, this); ... }创建一个意图过滤器,并添加相同的意图为您广播接收机检查:
IntentFilter mIntentFilter; ... @Override protected void onCreate(Bundle savedInstanceState){ ... mIntentFilter = new IntentFilter(); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); ... }注册广播接收器在您的活动的onResume()方法,并在活动的onPause()方法取消注册:
/* register the broadcast receiver with the intent values to be matched */ @Override protected void onResume() { super.onResume(); registerReceiver(mReceiver, mIntentFilter); } /* unregister the broadcast receiver */ @Override protected void onPause() { super.onPause(); unregisterReceiver(mReceiver); }当你获得了WifiP2pManager.Channel并成立了广播接收器,应用程序可以让无线网络的P2P方式拨打和接收的Wi-Fi点对点意图。
mManager.discoverPeers(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { ... } @Override public void onFailure(int reasonCode) { ... } });如果发现过程成功并检测对等体,则系统广播WIFI_P2P_PEERS_CHANGED_ACTION意图,而可以在一个广播接收机监听,以获得对等体的列表。当你的应用程序收到WIFI_P2P_PEERS_CHANGED_ACTION意图,您可以要求发现的对等与requestPeers列表()。下面的代码演示了如何设置此:
PeerListListener myPeerListListener; ... 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, myPeerListListener); } }该requestPeers()方法也是异步的,可以通知你的活动时,同龄人的名单可与现有的对等(),这是在WifiP2pManager.PeerListListener接口中定义。该onPeersAvailable()方法提供了一个WifiP2pDeviceList,您可以遍历找到您想要连接到同级。
//obtain a peer from the WifiP2pDeviceList WifiP2pDevice device; WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = device.deviceAddress; mManager.connect(mChannel, config, new ActionListener() { @Override public void onSuccess() { //success logic } @Override public void onFailure(int reason) { //failure logic } });传输数据
public static class FileServerAsyncTask extends AsyncTask { private Context context; private TextView statusText; public FileServerAsyncTask(Context context, View statusText) { this.context = context; this.statusText = (TextView) statusText; } @Override protected String doInBackground(Void... params) { try { /** * Create a server socket and wait for client connections. This * call blocks until a connection is accepted from a client */ ServerSocket serverSocket = new ServerSocket(8888); Socket client = serverSocket.accept(); /** * If this code is reached, a client has connected and transferred data * Save the input stream from the client as a JPEG file */ final File f = new File(Environment.getExternalStorageDirectory() + "/" + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis() + ".jpg"); File dirs = new File(f.getParent()); if (!dirs.exists()) dirs.mkdirs(); f.createNewFile(); InputStream inputstream = client.getInputStream(); copyFile(inputstream, new FileOutputStream(f)); serverSocket.close(); return f.getAbsolutePath(); } catch (IOException e) { Log.e(WiFiDirectActivity.TAG, e.getMessage()); return null; } } /** * Start activity that can handle the JPEG image */ @Override protected void onPostExecute(String result) { if (result != null) { statusText.setText("File copied - " + result); Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse("file://" + result), "image/*"); context.startActivity(intent); } } }在客户端,连接到与客户端套接字和传输数据的服务器套接字。这个例子传输客户端设备的文件系统上的JPEG文件。
Context context = this.getApplicationContext(); String host; int port; int len; Socket socket = new Socket(); byte buf[] = new byte[1024]; ... try { /** * Create a client socket with the host, * port, and timeout information. */ socket.bind(null); socket.connect((new InetSocketAddress(host, port)), 500); /** * Create a byte stream from a JPEG file and pipe it to the output stream * of the socket. This data will be retrieved by the server device. */ OutputStream outputStream = socket.getOutputStream(); ContentResolver cr = context.getContentResolver(); InputStream inputStream = null; inputStream = cr.openInputStream(Uri.parse("path/to/picture.jpg")); while ((len = inputStream.read(buf)) != -1) { outputStream.write(buf, 0, len); } outputStream.close(); inputStream.close(); } catch (FileNotFoundException e) { //catch logic } catch (IOException e) { //catch logic } /** * Clean up any open sockets when done * transferring or if an exception occurred. */ finally { if (socket != null) { if (socket.isConnected()) { try { socket.close(); } catch (IOException e) { //catch logic } } } }