|
参考链接: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[1024];
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 }
|
|