zoukankan      html  css  js  c++  java
  • 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[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 }

     

  • 相关阅读:
    资料下载
    sublime安装AngularJS插件
    Zen Coding: 一种快速编写HTML/CSS代码的方法[Emmet]
    手机号码归属地API
    浅谈JavaScript中的作用域
    原生ajax、jsoup
    Java排序:选择排序
    Java排序:冒泡排序
    Oracle系列一、基本术语
    linux jdk tomcat 安装
  • 原文地址:https://www.cnblogs.com/pngcui/p/4350456.html
Copyright © 2011-2022 走看看