xuke123 发表于 2015-9-30 13:32:59

Wifi-Direct

  参考链接:http://developer.android.com/guide/topics/connectivity/wifip2p.html
  国内镜像开发文档:http://wear.techbrood.com/guide/topics/connectivity/wifip2p.html
  

API:
  WifiP2pManager类提供了很多方法允许用户通过设备的Wi-Fi模块来进行交互,比如做一些如发现,连接其他对等设备的事情。下列的方法都是可以使用的: 表格1.Wi-Fi直连技术方法



方法名详细描述

  initialize()


  通过Wi-Fi框架对应用来进行注册。这个方法必须在任何其他Wi-Fi直连方法使用之前调用。




  connect()]


  开始一个拥有特定设置的设备的点对点连接。




  cancelConnect()


  取消任何一个正在进行的点对点组的连接。




  requestConnectInfo()


  获取一个设备的连接信息。




  createGroup()


  以当前设备为组拥有者来创建一个点对点连接组。




  removeGroup()


  移除当前的点对点连接组。




  requestGroupInfo()


  获取点对点连接组的信息。




  discoverPeers()


  初始化对等设备的发现。




  requestPeers()


  获取当前发现的对等设备列表。




  WifiP2pManager的方法可以让你在一个监听器里传递参数,这样Wi-fi直连框架就可以通知给你的窗体这个方法调用的状态。可以被使用的监听器接口和使用监听器的相应的WifiP2pManager的方法的调用都将在下面这张表中有所描述:
  表格 2. Wi-Fi直连监听器方法



监听器接口相关联的方法

  WifiP2pManager.ActionListener


  connect(), cancelConnect(), createGroup(), removeGroup(), and discoverPeers()




  WifiP2pManager.ChannelListener


  initialize()




  WifiP2pManager.ConnectionInfoListener


  requestConnectInfo()




  WifiP2pManager.GroupInfoListener


  requestGroupInfo()




  WifiP2pManager.PeerListListener


  requestPeers()




  Wi-Fi直连技术的API定义了一些当特定的Wi-Fi直连事件发生时作为广播的意图,比如说当一个新的对等设备被发现,或者一个设备的Wi-Fi状态的改变。你可以在你的应用里通过创建一个处理这些意图的广播接收器来注册去接收这些意图。
  Table 3. Wi-Fi 直连意图



意图名称详细描述

  WIFI_P2P_CONNECTION_CHANGED_ACTION


  当设备的Wi-Fi连接信息状态改变时候进行广播。




  WIFI_P2P_PEERS_CHANGED_ACTION


  当调用discoverPeers()方法的时候进行广播。在你的应用里处理此意图时,你通常会调用requestPeers()去获得对等设备列表的更新。




  WIFI_P2P_STATE_CHANGED_ACTION


  当设备的Wi-Fi 直连功能打开或关闭时进行广播。




  WIFI_P2P_THIS_DEVICE_CHANGED_ACTION


  当设备的详细信息改变的时候进行广播,比如设备的名称




  

创建一个广播接收器
  一个广播接收器允许你接收由android系统发布的意图广播,这样你的应用就可以对那些你感兴趣的事件作出响应。创建一个基本的Wi-Fi直连意图使用的广播接收器的步骤如下:
  1.创建一个继承自BroadcastReceiver的类。对于类的构造,一般最常用的就是以WifiP2pManager, WifiP2pManager.Channel作为参数,同时这个广播接收器对应的窗体也将被注册进来。这个广播接收器可以像窗体发送更新或者在需要的时候可以访问Wi-Fi硬件或通信通道。
  2.在广播接收器里,处理onReceive()方法里你感兴趣的意图。执行接收到的意图的任何需要的动作。比如,广播接收器接收到一个WIFI_P2P_PEERS_CHANGED_ACTION的意图,你就要调用requestPeers()方法去获得当前发现的对等设备列表。
  下面的代码展示了怎样去创建一个典型的广播接收器。广播接收器接收一个WifiP2pManager对象和一个窗体对象作为参数然后利用这两个类去处理接收到的意图的特定的动作需求。
  



1 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
2 @SuppressLint("NewApi")
3 public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
4
5   private WifiP2pManager manager;
6   private Channel channel;
7   private WiFiDirectActivity activity;
8
9
10   public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel,
11             WiFiDirectActivity activity) {
12         super();
13         this.manager = manager;
14         this.channel = channel;
15         this.activity = activity;
16   }
17
18
19   @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
20   @SuppressLint("NewApi")
21   @Override
22   public void onReceive(Context context, Intent intent) {
23         String action = intent.getAction();
24         if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
25             int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
26             if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
27             } else {
28               Log.d(WiFiDirectActivity.TAG, "无法使用Wifi-Direct");
29               activity.setIsWifiP2pEnabled(false);
30               activity.resetData();
31
32             }
33             Log.d(WiFiDirectActivity.TAG, "P2P state changed - " + state);
34         } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
35             if (manager != null) {
36               manager.requestPeers(channel, (PeerListListener) activity.getFragmentManager()
37                         .findFragmentById(R.id.frag_list));
38             }
39             Log.d(WiFiDirectActivity.TAG, "P2P peers changed");
40         } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
41             if (manager == null) {
42               return;
43             }
44
45             NetworkInfo networkInfo = (NetworkInfo) intent
46                     .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
47
48             if (networkInfo.isConnected()) {
49
50               // we are connected with the other device, request connection
51               // info to find group owner IP
52
53               DeviceDetailFragment fragment = (DeviceDetailFragment) activity
54                         .getFragmentManager().findFragmentById(R.id.frag_detail);
55               manager.requestConnectionInfo(channel, fragment);
56             } else {
57               // It's a disconnect
58               activity.resetData();
59             }
60         } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
61             DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
62                     .findFragmentById(R.id.frag_list);
63             fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
64                     WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));
65
66         }
67   }
68 }
  

发现对等设备
  要发现可以使用并连接的对等设备,调用discoverPeers()方法去检测在范围内的可使用设备。这个方法的调用是异步的同时如果你创建了一个WifiP2pManager.ActionListener监听器的话你会通过onSuccess()或者onFailure()方法收到发现成功或失败的消息。
  onSuccess()方法只能通知你发现的过程是否成功而不能提供任何关于发现设备的信息:



1 manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
2   @Override
3   public void onSuccess() {
4         ...
5   }
6
7   @Override
8   public void onFailure(int reasonCode) {
9         ...
10   }
11 });
连接到设备
  当你已经找到你要连接的设备在获得发现设备列表之后,调用connect()方法去连接指定设备。这个方法的调用需要一个包含待连接设备信息的WifiP2pConfig对象。你可以通过WifiP2pManager.ActionListener接收到连接是否成功的通知。下面的代码展示了怎样去连接一个想得到的连接:



1 WifiP2pDevice device;
2 WifiP2pConfig config = new WifiP2pConfig();
3 config.deviceAddress = device.deviceAddress;
4 manager.connect(channel, config, new ActionListener() {
5
6   @Override
7   public void onSuccess() {
8         //success logic
9   }
10
11   @Override
12   public void onFailure(int reason) {
13         //failure logic
14   }
15 });
  
  

创建一个Wi-Fi直连的应用
  创建一个Wi-Fi直连的应用包括创建和注册一个广播接收器,发现其他设备,连接其他设备,然后传输数据等步骤。接下来的几个部分描述了怎么去做这些工作。

初始化设置
  在使用Wi-Fi直连的API之前,你必须确保你的应用可以访问设备的硬件并且你的设备要支持Wi-Fi直连的通讯协议。如果Wi-Fi直连技术是支持的,你可以获得一个WifiP2pManager的实例对象,然后创建并注册你的广播接收器,然后开始使用Wi-Fi直连的API方法。
  1.为设备的Wi-Fi硬件获取权限并在Android的清单文件中声明你的应用正确使用的最低SDK版本:



1 <uses-sdk android:minSdkVersion="14" />
2 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
3 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
4 <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
5 <uses-permission android:name="android.permission.INTERNET" />
6 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  2.在你的窗体的onCreate()方法里,获得一个WifiP2pManager的实例并调用initialize()方法通过Wi-Fi直连框架去注册你的应用。这个方法返回一个WifiP2pManager.Channel对象,是被用来连接你的应用和Wi-Fi直连框架的。你应该再创建一个以WifiP2pManager和WifiP2pManager.Channel为参数且关联你的窗体的广播接收器的实例。这样你的广播接收器就可以接收到你感兴趣的事件去通知你的窗体并更新它。它还可以让你在需要的时候操纵设备的Wi-Fi状态。



1 WifiP2pManager mManager;
2 Channel mChannel;
3 BroadcastReceiver mReceiver;
4 ...
5 @Override
6 protected void onCreate(Bundle savedInstanceState){
7   ...
8   mManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
9   mChannel = mManager.initialize(this, getMainLooper(), null);
10   mReceiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
11   ...
12 }
  3.创建一个意图过滤器并把它添加在你的广播接收器需要处理的意图上。



1 IntentFilter mIntentFilter;
2 ...
3 @Override
4 protected void onCreate(Bundle savedInstanceState){
5   ...
6   mIntentFilter = new IntentFilter();
7   mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
8   mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
9   mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
10   mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
11   ...
12 }
  4.注册你的广播接收器在窗体的onResume()方法,解除注册在onPause()方法中。



1 @Override
2 protected void onResume() {
3   super.onResume();
4   registerReceiver(mReceiver, mIntentFilter);
5 }
6 /* unregister the broadcast receiver */
7 @Override
8 protected void onPause() {
9   super.onPause();
10   unregisterReceiver(mReceiver);
11 }
  当你获取到一个WifiP2pManager.Channel对象并且设置好你的广播接收器时,你的应用就可以调用Wi-Fi直连的方法并且可以接收Wi-Fi直连的意图。
  你可以现在就通过调用WifiP2pManager中的方法取实现你的应用体验Wi-Fi直连技术的特性了。
  
  下面是窗体Activity的完整代码:



1 @SuppressLint("NewApi")
2 public class WiFiDirectActivity extends Activity implements ChannelListener, DeviceActionListener {
3
4   public static final String TAG = "wifidirectdemo";
5   private WifiP2pManager manager;
6   private boolean isWifiP2pEnabled = false;
7   private boolean retryChannel = false;
8
9   private final IntentFilter intentFilter = new IntentFilter();
10   private Channel channel;
11   private BroadcastReceiver receiver = null;
12
13   public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
14         this.isWifiP2pEnabled = isWifiP2pEnabled;
15   }
16
17   @Override
18   public void onCreate(Bundle savedInstanceState) {
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.main);
21
22         // add necessary intent values to be matched.
23
24         intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
25         intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
26         intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
27         intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
28
29         manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
30         channel = manager.initialize(this, getMainLooper(), null);
31   }
32
33   /** register the BroadcastReceiver with the intent values to be matched */
34   @Override
35   public void onResume() {
36         super.onResume();
37         receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
38         registerReceiver(receiver, intentFilter);
39   }
40
41   @Override
42   public void onPause() {
43         super.onPause();
44         unregisterReceiver(receiver);
45   }
46
47   /**
48      * Remove all peers and clear all fields. This is called on
49      * BroadcastReceiver receiving a state change event.
50      */
51   public void resetData() {
52         DeviceListFragment fragmentList = (DeviceListFragment) getFragmentManager()
53               .findFragmentById(R.id.frag_list);
54         DeviceDetailFragment fragmentDetails = (DeviceDetailFragment) getFragmentManager()
55               .findFragmentById(R.id.frag_detail);
56         if (fragmentList != null) {
57             fragmentList.clearPeers();
58         }
59         if (fragmentDetails != null) {
60             fragmentDetails.resetViews();
61         }
62   }
63
64   @Override
65   public boolean onCreateOptionsMenu(Menu menu) {
66         MenuInflater inflater = getMenuInflater();
67         inflater.inflate(R.menu.wi_fi_direct, menu);
68         return true;
69   }
70
71   @Override
72   public boolean onOptionsItemSelected(MenuItem item) {
73         switch (item.getItemId()) {
74             case R.id.atn_direct_enable:
75               if (manager != null && channel != null) {
76
77                     // Since this is the system wireless settings activity, it's
78                     // not going to send us a result. We will be notified by
79                     // WiFiDeviceBroadcastReceiver instead.
80
81                     startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
82               } else {
83                     Log.e(TAG, "channel or manager is null");
84               }
85               return true;
86
87             case R.id.atn_direct_discover:
88               if (!isWifiP2pEnabled) {
89                     Toast.makeText(WiFiDirectActivity.this, R.string.p2p_off_warning,
90                           Toast.LENGTH_SHORT).show();
91                     return true;
92               }
93               final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
94                         .findFragmentById(R.id.frag_list);
95               fragment.onInitiateDiscovery();
96               manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
97
98                     @Override
99                     public void onSuccess() {
100                         Toast.makeText(WiFiDirectActivity.this, "Discovery Initiated",
101                                 Toast.LENGTH_SHORT).show();
102                     }
103
104                     @Override
105                     public void onFailure(int reasonCode) {
106                         Toast.makeText(WiFiDirectActivity.this, "Discovery Failed : " + reasonCode,
107                                 Toast.LENGTH_SHORT).show();
108                     }
109               });
110               return true;
111             default:
112               return super.onOptionsItemSelected(item);
113         }
114   }
115
116   @Override
117   public void showDetails(WifiP2pDevice device) {
118         DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
119               .findFragmentById(R.id.frag_detail);
120         fragment.showDetails(device);
121
122   }
123
124   @Override
125   public void connect(WifiP2pConfig config) {
126         manager.connect(channel, config, new ActionListener() {
127
128             @Override
129             public void onSuccess() {
130               // WiFiDirectBroadcastReceiver will notify us. Ignore for now.
131               Log.e(TAG, "Success!");
132             }
133
134             @Override
135             public void onFailure(int reason) {
136               Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.",
137                         Toast.LENGTH_SHORT).show();
138             }
139         });
140   }
141
142   @Override
143   public void disconnect() {
144         final DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
145               .findFragmentById(R.id.frag_detail);
146         fragment.resetViews();
147         manager.removeGroup(channel, new ActionListener() {
148
149             @Override
150             public void onFailure(int reasonCode) {
151               Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
152
153             }
154
155             @Override
156             public void onSuccess() {
157               fragment.getView().setVisibility(View.GONE);
158             }
159
160         });
161   }
162
163   @Override
164   public void onChannelDisconnected() {
165         // we will try once more
166         if (manager != null && !retryChannel) {
167             Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show();
168             resetData();
169             retryChannel = true;
170             manager.initialize(this, getMainLooper(), this);
171         } else {
172             Toast.makeText(this,
173                     "Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.",
174                     Toast.LENGTH_LONG).show();
175         }
176   }
177
178   @Override
179   public void cancelDisconnect() {
180
181         if (manager != null) {
182             final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
183                     .findFragmentById(R.id.frag_list);
184             if (fragment.getDevice() == null
185                     || fragment.getDevice().status == WifiP2pDevice.CONNECTED) {
186               disconnect();
187             } else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE
188                     || fragment.getDevice().status == WifiP2pDevice.INVITED) {
189
190               manager.cancelConnect(channel, new ActionListener() {
191
192                     @Override
193                     public void onSuccess() {
194                         Toast.makeText(WiFiDirectActivity.this, "Aborting connection",
195                                 Toast.LENGTH_SHORT).show();
196                     }
197
198                     @Override
199                     public void onFailure(int reasonCode) {
200                         Toast.makeText(WiFiDirectActivity.this,
201                                 "Connect abort request failed. Reason Code: " + reasonCode,
202                                 Toast.LENGTH_SHORT).show();
203                     }
204               });
205             }
206         }
207
208   }
209 }
显示设备连接的详细信息代码



1 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
2 @SuppressLint("NewApi")
3 public class DeviceListFragment extends ListFragment implements PeerListListener {
4
5   private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
6   ProgressDialog progressDialog = null;
7   View mContentView = null;
8   private WifiP2pDevice device;
9
10   @Override
11   public void onActivityCreated(Bundle savedInstanceState) {
12         super.onActivityCreated(savedInstanceState);
13         this.setListAdapter(new WiFiPeerListAdapter(getActivity(), R.layout.row_devices, peers));
14
15   }
16
17   @Override
18   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
19         mContentView = inflater.inflate(R.layout.device_list, null);
20         return mContentView;
21   }
22
23   public WifiP2pDevice getDevice() {
24         return device;
25   }
26
27   private static String getDeviceStatus(int deviceStatus) {
28         Log.d(WiFiDirectActivity.TAG, "Peer status :" + deviceStatus);
29         switch (deviceStatus) {
30             case WifiP2pDevice.AVAILABLE:
31               return "available";
32             case WifiP2pDevice.INVITED:
33               return "invited";
34             case WifiP2pDevice.CONNECTED:
35               return "connected";
36             case WifiP2pDevice.FAILED:
37               return "failed";
38             case WifiP2pDevice.UNAVAILABLE:
39               return "unavailable";
40             default:
41               return "unknow";
42
43         }
44   }
45
46   /**
47      * Initiate a connection with the peer.
48      */
49   @Override
50   public void onListItemClick(ListView l, View v, int position, long id) {
51         WifiP2pDevice device = (WifiP2pDevice) getListAdapter().getItem(position);
52         ((DeviceActionListener) getActivity()).showDetails(device);
53   }
54
55   /**
56      * Array adapter for ListFragment that maintains WifiP2pDevice list.
57      */
58   private class WiFiPeerListAdapter extends ArrayAdapter<WifiP2pDevice> {
59
60         private List<WifiP2pDevice> items;
61
62         public WiFiPeerListAdapter(Context context, int textViewResourceId,
63               List<WifiP2pDevice> objects) {
64             super(context, textViewResourceId, objects);
65             items = objects;
66
67         }
68
69         @Override
70         public View getView(int position, View convertView, ViewGroup parent) {
71             View v = convertView;
72             if (v == null) {
73               LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(
74                         Context.LAYOUT_INFLATER_SERVICE);
75               v = vi.inflate(R.layout.row_devices, null);
76             }
77             WifiP2pDevice device = items.get(position);
78             if (device != null) {
79               TextView top = (TextView) v.findViewById(R.id.device_name);
80               TextView bottom = (TextView) v.findViewById(R.id.device_details);
81               if (top != null) {
82                     top.setText(device.deviceName);
83               }
84               if (bottom != null) {
85                     bottom.setText(getDeviceStatus(device.status));
86               }
87             }
88
89             return v;
90
91         }
92   }
93
94   public void updateThisDevice(WifiP2pDevice device) {
95         this.device = device;
96         TextView view = (TextView) mContentView.findViewById(R.id.my_name);
97         view.setText(device.deviceName);
98         view = (TextView) mContentView.findViewById(R.id.my_status);
99         view.setText(getDeviceStatus(device.status));
100   }
101   
102   @Override
103   public void onPeersAvailable(WifiP2pDeviceList peerList) {
104         if (progressDialog != null && progressDialog.isShowing()) {
105             progressDialog.dismiss();
106         }
107         peers.clear();
108         peers.addAll(peerList.getDeviceList());
109      
110         if (peers.size() == 0) {
111             Log.d(WiFiDirectActivity.TAG, "size==0");
112             return;
113         }
114
115   }
116
117   public void clearPeers() {
118         peers.clear();
119         ((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
120   }
121
122   public void onInitiateDiscovery() {
123         if (progressDialog != null && progressDialog.isShowing()) {
124             progressDialog.dismiss();
125         }
126         progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel", "finding peers", true,
127               true, new DialogInterface.OnCancelListener() {
128
129                     @Override
130                     public void onCancel(DialogInterface dialog) {
131                        
132                     }
133               });
134   }
135
136   public interface DeviceActionListener {
137
138         void showDetails(WifiP2pDevice device);
139
140         void cancelDisconnect();
141
142         void connect(WifiP2pConfig config);
143
144         void disconnect();
145   }
146
147 }
  

数据传输
  一旦连接已经建立,你可以通过套接字来进行数据的传输。基本的数据传输步骤如下:
  1.创建一个ServerSocket对象。这个服务端套接字对象等待一个来自指定地址和端口的客户端的连接且阻塞线程直到连接发生,所以把它建立在一个后台线程里。
  2.创建一个客户端Socket.这个客户端套接字对象使用指定ip地址和端口去连接服务端设备。
  3.服务端等待客户端的连接(使用accept()方法)。这个调用阻塞服务端线程直到客户端连接上,所以叫这个过程一个新的线程。当连接建立时,服务端可以接受来自客户端的数据。执行关于数据的任何动作,比如保存数据或者展示给用户。
  



1    @Override
2         protected String doInBackground(Void... params) {
3             try {
4               ServerSocket serverSocket = new ServerSocket(8888);
5               //服务器端口号
6               Log.d(WiFiDirectActivity.TAG, "Server: Socket opened");
7               Socket client = serverSocket.accept();
8               //客户端绑定服务器端口
9               //!!!!!!!!!!使用accept方法等待客户机发送数据
10               Log.d(WiFiDirectActivity.TAG, "Server: connection done");
11               
12               
13               final File f = new File(Environment.getExternalStorageDirectory() + "/"
14                         + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
15                         + ".jpg");
16
17               File dirs = new File(f.getParent());
18               if (!dirs.exists())
19                     dirs.mkdirs();
20               f.createNewFile();
21
22               Log.d(WiFiDirectActivity.TAG, "server: copying files " + f.toString());
23               InputStream inputstream = client.getInputStream();
24               copyFile(inputstream, new FileOutputStream(f));
25               serverSocket.close();
26               return f.getAbsolutePath();
27             } catch (IOException e) {
28               Log.e(WiFiDirectActivity.TAG, e.getMessage());
29               return null;
30             }
31         }
  4.服务端与客户端,官方demo只给出了客户端向服务端发送数据的方式。



1 @Override
2   public void onConnectionInfoAvailable(final WifiP2pInfo info) {
3         if (progressDialog != null && progressDialog.isShowing()) {
4             progressDialog.dismiss();
5         }
6         this.info = info;
7         this.getView().setVisibility(View.VISIBLE);
8
9         // The owner IP is now known.
10         TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
11         view.setText(getResources().getString(R.string.group_owner_text)
12               + ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
13                         : getResources().getString(R.string.no)));
14
15         // InetAddress from WifiP2pInfo struct.
16         view = (TextView) mContentView.findViewById(R.id.device_info);
17         view.setText("群主IP - " + info.groupOwnerAddress.getHostAddress());
18
19         // After the group negotiation, we assign the group owner as the file
20         // server. The file server is single threaded, single connection server
21         // socket.
22         if (info.groupFormed && info.isGroupOwner) {      
23             new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text))
24                  .execute();
25         } else if (info.groupFormed) {
26             mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
27             ((TextView) mContentView.findViewById(R.id.status_text)).setText(getResources()
28                     .getString(R.string.client_text));
29         }
30         
31         // hide the connect button
32         mContentView.findViewById(R.id.btn_connect).setVisibility(View.GONE);
33   }
  
  完整代码如下:



1 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
2 @SuppressLint("NewApi")
3 public class DeviceDetailFragment extends Fragment implements ConnectionInfoListener {
4
5   protected static final int CHOOSE_FILE_RESULT_CODE = 20;
6   private View mContentView = null;
7   private WifiP2pDevice device;
8   private WifiP2pInfo info;
9   ProgressDialog progressDialog = null;
10
11   @Override
12   public void onActivityCreated(Bundle savedInstanceState) {
13         super.onActivityCreated(savedInstanceState);
14   }
15
16   @Override
17   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
18
19         mContentView = inflater.inflate(R.layout.device_detail, null);
20         mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
21
22             @Override
23             public void onClick(View v) {
24               WifiP2pConfig config = new WifiP2pConfig();
25               config.deviceAddress = device.deviceAddress;
26               config.wps.setup = WpsInfo.PBC;
27               if (progressDialog != null && progressDialog.isShowing()) {
28                     progressDialog.dismiss();
29               }
30               progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel",
31                         "Connecting to :" + device.deviceAddress, true, true);
32             }
33         });
34
35         mContentView.findViewById(R.id.btn_disconnect).setOnClickListener(
36               new View.OnClickListener() {
37
38                     @Override
39                     public void onClick(View v) {
40                         ((DeviceActionListener) getActivity()).disconnect();
41                     }
42               });
43
44         mContentView.findViewById(R.id.btn_start_client).setOnClickListener(
45               new View.OnClickListener() {
46
47                     @Override
48                     public void onClick(View v) {
49                         Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
50                         intent.setType("image/*");
51                         startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
52                     }
53               });
54
55         return mContentView;
56   }
57
58   @Override
59   public void onActivityResult(int requestCode, int resultCode, Intent data) {
60
61         // User has picked an image. Transfer it to group owner i.e peer using
62         // FileTransferService.
63         Uri uri = data.getData();
64         TextView statusText = (TextView) mContentView.findViewById(R.id.status_text);
65         statusText.setText("Sending: " + uri);
66         Log.d(WiFiDirectActivity.TAG, "Intent----------- " + uri);
67         Intent serviceIntent = new Intent(getActivity(), FileTransferService.class);
68         serviceIntent.setAction(FileTransferService.ACTION_SEND_FILE);
69         serviceIntent.putExtra(FileTransferService.EXTRAS_FILE_PATH, uri.toString());
70         serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_ADDRESS,
71               info.groupOwnerAddress.getHostAddress());
72         serviceIntent.putExtra(FileTransferService.EXTRAS_GROUP_OWNER_PORT, 8888);
73         getActivity().startService(serviceIntent);
74   }
75
76   @Override
77   public void onConnectionInfoAvailable(final WifiP2pInfo info) {
78         if (progressDialog != null && progressDialog.isShowing()) {
79             progressDialog.dismiss();
80         }
81         this.info = info;
82         this.getView().setVisibility(View.VISIBLE);
83
84         // The owner IP is now known.
85         TextView view = (TextView) mContentView.findViewById(R.id.group_owner);
86         view.setText(getResources().getString(R.string.group_owner_text)
87               + ((info.isGroupOwner == true) ? getResources().getString(R.string.yes)
88                         : getResources().getString(R.string.no)));
89
90         // InetAddress from WifiP2pInfo struct.
91         view = (TextView) mContentView.findViewById(R.id.device_info);
92         view.setText("群主IP - " + info.groupOwnerAddress.getHostAddress());
93
94         // After the group negotiation, we assign the group owner as the file
95         // server. The file server is single threaded, single connection server
96         // socket.
97         if (info.groupFormed && info.isGroupOwner) {      
98             new FileServerAsyncTask(getActivity(), mContentView.findViewById(R.id.status_text))
99                  .execute();
100         } else if (info.groupFormed) {
101             mContentView.findViewById(R.id.btn_start_client).setVisibility(View.VISIBLE);
102             ((TextView) mContentView.findViewById(R.id.status_text)).setText(getResources()
103                     .getString(R.string.client_text));
104         }
105         
106         // hide the connect button
107         mContentView.findViewById(R.id.btn_connect).setVisibility(View.GONE);
108   }
109
110   /**
111      * Updates the UI with device data
112      *
113      * @param device the device to be displayed
114      */
115   public void showDetails(WifiP2pDevice device) {
116         this.device = device;
117         this.getView().setVisibility(View.VISIBLE);
118         TextView view = (TextView) mContentView.findViewById(R.id.device_address);
119         view.setText(device.deviceAddress);
120         view = (TextView) mContentView.findViewById(R.id.device_info);
121         view.setText(device.toString());
122
123   }
124
125   /**
126      * Clears the UI fields after a disconnect or direct mode disable operation.
127      */
128   public void resetViews() {
129         mContentView.findViewById(R.id.btn_connect).setVisibility(View.VISIBLE);
130         TextView view = (TextView) mContentView.findViewById(R.id.device_address);
131         view.setText(R.string.empty);
132         view = (TextView) mContentView.findViewById(R.id.device_info);
133         view.setText(R.string.empty);
134         view = (TextView) mContentView.findViewById(R.id.group_owner);
135         view.setText(R.string.empty);
136         view = (TextView) mContentView.findViewById(R.id.status_text);
137         view.setText(R.string.empty);
138         mContentView.findViewById(R.id.btn_start_client).setVisibility(View.GONE);
139         this.getView().setVisibility(View.GONE);
140   }
141
142   public static class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
143
144         private Context context;
145         private TextView statusText;
146
147         public FileServerAsyncTask(Context context, View statusText) {
148             this.context = context;
149             this.statusText = (TextView) statusText;
150         }
151
152         @Override
153         protected String doInBackground(Void... params) {
154             try {
155               ServerSocket serverSocket = new ServerSocket(8888);
156               //服务器端口号
157               Log.d(WiFiDirectActivity.TAG, "Server: Socket opened");
158               Socket client = serverSocket.accept();
159               //客户端绑定服务器端
160               //!!!!!!!!!!使用accept方法等待客户机发送数据
161               Log.d(WiFiDirectActivity.TAG, "Server: connection done");
162               
163               
164               final File f = new File(Environment.getExternalStorageDirectory() + "/"
165                         + context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
166                         + ".jpg");
167
168               File dirs = new File(f.getParent());
169               if (!dirs.exists())
170                     dirs.mkdirs();
171               f.createNewFile();
172
173               Log.d(WiFiDirectActivity.TAG, "server: copying files " + f.toString());
174               InputStream inputstream = client.getInputStream();
175               copyFile(inputstream, new FileOutputStream(f));
176               serverSocket.close();
177               return f.getAbsolutePath();
178             } catch (IOException e) {
179               Log.e(WiFiDirectActivity.TAG, e.getMessage());
180               return null;
181             }
182         }
183
184         @Override
185         protected void onPostExecute(String result) {
186             if (result != null) {
187               statusText.setText("File copied - " + result);
188               Intent intent = new Intent();
189               intent.setAction(android.content.Intent.ACTION_VIEW);
190               intent.setDataAndType(Uri.parse("file://" + result), "image/*");
191               context.startActivity(intent);
192             }
193
194         }
195
196         @Override
197         protected void onPreExecute() {
198             statusText.setText("Opening a server socket");
199         }
200
201   }
202
203   public static boolean copyFile(InputStream inputStream, OutputStream out) {
204         byte buf[] = new byte;
205         int len;
206         try {
207             while ((len = inputStream.read(buf)) != -1) {
208               out.write(buf, 0, len);
209
210             }
211             out.close();
212             inputStream.close();
213         } catch (IOException e) {
214             Log.d(WiFiDirectActivity.TAG, e.toString());
215             return false;
216         }
217         return true;
218   }
219
220 }
  文件传输代码如下:



1 public class FileTransferService extends IntentService {
2
3   private static final int SOCKET_TIMEOUT = 5000;
4   public static final String ACTION_SEND_FILE = "com.example.android.wifidirect.SEND_FILE";
5   public static final String EXTRAS_FILE_PATH = "file_url";
6   public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
7   public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";
8
9   public FileTransferService(String name) {
10         super(name);
11   }
12
13   public FileTransferService() {
14         super("FileTransferService");
15   }
16
17   @Override
18   protected void onHandleIntent(Intent intent) {
19
20         Context context = getApplicationContext();
21         if (intent.getAction().equals(ACTION_SEND_FILE)) {
22             String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
23             String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
24             Socket socket = new Socket();
25             int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
26         
27             try {
28               Log.d(WiFiDirectActivity.TAG, "Opening client socket - ");
29               socket.bind(null);
30               socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
31
32               Log.d(WiFiDirectActivity.TAG, "Client socket - " + socket.isConnected());
33               OutputStream stream = socket.getOutputStream();
34               ContentResolver cr = context.getContentResolver();
35               InputStream is = null;
36               try {
37                     is = cr.openInputStream(Uri.parse(fileUri));
38               } catch (FileNotFoundException e) {
39                     Log.d(WiFiDirectActivity.TAG, e.toString());
40               }
41               DeviceDetailFragment.copyFile(is, stream);
42               Log.d(WiFiDirectActivity.TAG, "Client: Data written");
43             } catch (IOException e) {
44               Log.e(WiFiDirectActivity.TAG, e.getMessage());
45             } finally {
46               if (socket != null) {
47                     if (socket.isConnected()) {
48                         try {
49                           socket.close();
50                         } catch (IOException e) {
51                           // Give up
52                           e.printStackTrace();
53                         }
54                     }
55               }
56             }
57
58         }
59         
60   }
61 }
  
  
  
  

页: [1]
查看完整版本: Wifi-Direct