欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

Android API Guides---Wi-Fi Peer-to-Peer

来源: 开发者 投稿于  被查看 49056 次 评论:54

Android API Guides---Wi-Fi Peer-to-Peer


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应用


创建一个Wi-Fi的P2P应用程序包括创建和注册的广播接收器为您的应用程序,发现同行,连接到一个同行,和传输数据到对等。下面的章节描述了如何做到这一点。


初始设置


使用的Wi-Fi P2P的API之前,必须确保您的应用程序可以访问硬件和设备支持的Wi-Fi P2P协议。如果支持的Wi-Fi P2P,您可以获得WifiP2pManager的一个实例,创建并注册您的广播接收器,并开始使用的Wi-Fi P2P的API。


请求许可使用设备上的Wi-Fi硬件,也宣告您的应用程序在Android清单正确的最低SDK版本:

 

 






请检查是否无线网络连接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点对点意图。
现在,您可以实现您的应用程序,并通过调用WifiP2pManager的方法使用的Wi-Fi功能的P2P。接下来的部分描述了怎么办共同行动,如发现和连接同行。


发现同行


要发现同行可用来连接,调用discoverPeers()来检测在范围内可用的同行。这个函数的调用是异步的,一个成功或失败传递给您的应用程序的onSuccess()和onFailure处(),如果你创建了一个WifiP2pManager.ActionListener。该的onSuccess()方法只通知您发现过程成功,不提供有关实际同龄人的任何信息,它发现,如果有的话:

 

 

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,您可以遍历找到您想要连接到同级。
连接到同行
当你想通了,你想获得可能的同龄人名单后,连接到设备,调用connect()方法连接到该设备。此方法调用需要包含该装置的信息来连接到一个WifiP2pConfig对象。你可以通知通过WifiP2pManager.ActionListener连接成功或失败。下面的代码演示如何创建到所需设备的连接:

 

 

//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
  }
});
传输数据


一旦建立了连接,你可以用插座的设备之间传输数据。是传送数据的基本步骤如下:


创建一个ServerSocket。此插座等待来自客户端的指定端口和块上的连接,直到它发生,所以在后台线程做到这一点。
创建一个客户端的Socket。客户端使用服务器套接字的IP地址和端口,以连接到服务器设备。
从客户机向服务器发送数据。当客户端套接字成功地连接到服务器插口,可以从客户端发送的数据与字节流服务器。
服务器套接字等待客户端连接(使用accept()方法)。这个调用块,直到客户端连接,所以称这是另一个线程。当连接发生时,服务器设备可以从客户端接收数据。执行与该数据的任何动作,如将其保存到文件或它呈现给用户。
下面的例子,从Wi-Fi无线P2P演示样品修改,向您展示如何创建这个客户端 - 服务器socket通讯和从客户端与服务传送JPEG图像传输到服务器。对于一个完整的工作示例,编译和运行的Wi-Fi点对点演示样本。

 

 

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
      }
    }
  }
}
 

用户评论