个人翻译的Wi-Fi Peer-to-Peer,语言不通顺,仅供个人浏览

来源:互联网 发布:it设备维修管理软件 编辑:程序博客网 时间:2024/05/03 17:58

Wi-Fi Peer-to-Peer

wifip2p允许Android4.0系统(API14)的设备或这个最近含有一样硬件的设备直接连接,通过WIFI而不是允许的媒介点(
Android的wifip2p框架使用wif联盟验证的项目编译).通过这些APIS,你可以发现并连接其他支持wifip2p的设备,然后用一种比蓝牙传输距离更远的快速传输方式进行连接.在用户中的应用来共享数据时非常有用的,就像多美体游戏或者在应用程序中尽心分享照片.

wifiP2p是由下面的几大重要部分组成的:
1.在WifiP2pManager的类中,定义了允许你发现,请求和连接其他设备的方法;
2.监听允许你去通知wifippManager的方法调用是否成功,当你调用WifiP2pManager方法时,每一个方法都可以接到一个特殊的监听作为元素传过来;
3.通知你这些特殊事件的意图会被Wifip2p框架检测到,比如说失去联系或者新发现一个设备;

你经常一起使用这三个主要部分.比如你可以提供一个WifiP2pManager.ActionListener来调用discoverPeers()方法,以便于你可以被ActionListener.onSuccess()和ActionListerner.onFailure()方法通知.如果discoverPeers()方法发现同等设备列表改变的时候,一个WIFI_P2P_PEERS_CHANGED_ACTION意图也会发出广播.

API概览:
WifiP2pManager类提供了方法允许你通过你设备上的wifi硬件来互相联系,比如发现和联系其他设备.
方法:
initialize():给应用注册wifi框架,这个方法必须在你调用其他WifiP2p的方法前调用.
connect():用设备通过特殊的配置开始一个点对点的连接
cancelConnect():取消所有点对点连接组的配置
requestConnectInfo():请求得到连接设备的信息
createGroup():以主机的身份利用现有的设备创建一个点对点连接组
removeGroup():移除现有的点对点连接组
requestGroupInfo():请求得到点对点组的信息
discoverPeers():开始搜寻有Wifi的设备
requestPeers():请求得到目前发现具有wifi的设备列表



WifiP2pManager方法允许你使用监听,以便于wifip2p框架可以用接口回调通知你的activtiy.这些可以使用的监听接口和wifip2pManager通信的方法调用情况描述如下:
WifiP2pManager.ActionListenerconnect(), cancelConnect(), createGroup(), removeGroup(), and discoverPeers()WifiP2pManager.ChannelListenerinitialize()WifiP2pManager.ConnectionInfoListenerrequestConnectInfo()WifiP2pManager.GroupInfoListenerrequestGroupInfo()WifiP2pManager.PeerListListenerrequestPeers()
wifip2p Api定义了广播意图当wifip2p事件发生的时候,比如说一个新的设备被发现,或者当一个设备的wifi状态改变了.你可以在你的应用中注册并接收这些意图通过创建一个广播接受者来处理这些意图
WIFI_P2P_CONNECTION_CHANGED_ACTION当设备的wifi连接状态改变时的广播意图WIFI_P2P_PEERS_CHANGED_ACTION当你调用discoverPeers() 方法时候的广播意图.如果你在你的应用中处理这个意图,会经常通过调用 requestPeers() 来获取一个更新的设备列表 WIFI_P2P_STATE_CHANGED_ACTION当 Wi-Fi P2P在设备上可用或不可用是的广播意图.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION当一个设备的详细信息被改变的时候,比如说设备的名字的广播意图为wifip2p创建一个广播接收者
一个广播接受者通过android系统,允许你接收到广播意图,以便你的应用可以响应你关注的事件,创建一个处理wifip2p的
意图的广播接收者基础步骤如下:
1.创建一个类继承BroadcastRecetiver.在这个类的构造方法里面需要有三个参数:WifiP2pManager,WifiP2pManager.Channel,还有你将要注册这个广播接收者的activity.这样将允许你的广播接收者向你的activity发送更新信息,并且你的activity可以在必要的情况下,使用wifi硬件和连接的channel;
2.在广播接受者类的onReceive()方法中,你可以检测上面的广播意图.通过你接收到的意图来执行重要的动作.比如广播接收者受到了WIFI_P2P_PEERS_CHANGED_ACTION意图,你可以调用requesPeers()方法来获取目前发现的设备列表.

如下代码给你展现如何创建一个典型的广播接受者.这个广播接收者受到一个广播意图时候,就会拿到一个WifiP2pManager的对象,一个activity的参数.并且可以使用这两个类适当的执行需要的方法
/**
 * 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
       
}
   
}
}
创建一个wifip2p的应用
创建一个wifip2p应用包含::为你应用创建和注册一个广播接受者,
                                         发现设备,
                                         连接另外一个设备,
                                         与其他设备进行数据传输.下面内容描述怎么去做这些事情

初始化设置:
在使用 Wi-Fi P2P APIS 之前,你必须确保你的应用程序有权限使用硬件并且你的设备只是 Wi-Fi P2P操作.如果 设备支持Wi-Fi P2P,你可以获取一个 Wi-Fi P2PManager的实例,创建并且注册广播接受者,然后开始使用 Wi-Fi P2P APIS.
1.在清单列表中要求有的权限:
<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" />
2.检测Wi-Fi P2P是否开启状态并且可用,在你广播接受者接到 WIFI_P2P_STATE_CHANGED_ACTION意图时来检测是最好的方式.这样直接通知给activity得到的WIFI-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
       
}
   
}
   
...
}
3.在你activity的onCreate()方法中,获取一个 WifiP2pManager 的实例.并且通过调用initialize()方法,为你的应用注册wifip2p框架.这个方法将会返回一个 WifiP2pManager.Channel,这个Channel用来将你的应用与wifiP2p框架来建立连接.你也应该利用wifip2pManager和wifip2pManager.channel,还有你的activity的引用来创建一个你的广播接受者.这样就会让你的广播接受者可以直接通知你的activity那些activity所关注的事情.这也可以在必要的情况下由你手动操作设备的wifi状态.
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);
   
...
}
4.创建一个意图过滤器,并且给这个意图过滤器添加上你的广播接受者检测的action:
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);
   
...
}
5.在你的Activity中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的对象,并且设置好了广播接受者,你的应用可以使用WIFIP2P的方法,并且接收WIFIP2P的意图

通过调用WIFIP2PManager的方法,现在实现了你的应用程序使用WIFIP2P的特性.接下来的信息描述发现一个设备并连接的通常做法:

 
发现设备:
为了发现可以连接的设备,你可以调用discoverPeers()方法来探测在一定范围内的可用设备.调用的这个方法是异步的,当你的应用通过onSuccess()和onFailure()方法通知你的应用是否已经成功建立连接,当你创建了一个WifiP2pManager.ActionListener接口时候.这个onSuccess()方法只通知你那些它成功发现的程序设备,但不提供个实际的这个他发现的设备的信息,if any:
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()方法同样也是异步的,可以在得到可用的设备列表时通过onPeersAvailable()方法通知你的activity,这个onPeersAvailable()是定义在WifiP2pManager.PeerListListener接口里的方法.这个onPeersAvailable()方法向你提供一个WifiP2pDeviceList,这个list里面你可以遍历的找到你想连接的设备.

连接设备
当你获取到设备清单并指出你要想连接的设备时候,调用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
   
}
});


传输数据:
一旦一个连接建立了,你就可以利用套接字在设备间传递信息.传递数据的基本步骤如下:
1.创建一个ServerSocket,这个套接字等待从客户端通过指定端口发出来的数据.这些操作也是在后台线程运行的.
2.创建一个客户端Socket,这个客户端利用服务器提供的ip地址和端口来连接到服务端的设备;
3.从客户端发送数据到服务器.当一个客户端的套接字成功连接到服务器的套接字,你就可以用字节流的形式从客户端发送数据到服务器.
4.服务器套接字用accept()方法等待客户端的连接,直到客户端连接上,所以这个方法也得开启另一个线程.当一个连接发生了,服务端设备可以接到客户端发来的数据.然后处理这些字节数据,比如保存为一个文件,或者给用户展示出来;

下面的这个例子,从WIFIP2P Demo样例中进行了改进,向你展示如何创建一个客户端--服务端套接字连接和从客户端利用service给服务器传送一副图片.

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









0 0
原创粉丝点击