二十五岁时我们都一样愚蠢、多愁善感,喜欢故弄玄虚,可如果不那样的话,五十岁时也就不会如此明智。
标题:8.14 WIFI Direct开发实例演示
实例 WIFIDirectDemo 改编 Android SDK 提供的实例,演示了通过 WIFI 搜寻连接点,建立连接,并进行数据传输的过程。
该实例包含 5 个类,说明说下:
- WIFIDirectDemoActivity:用于注册 BroadcastReceiver,处理 UI,并管理连接点的生命周期。
- WiFiDirectBroadcastReceiver:用于接收与 WIFI Direct 功能相关的 Intent。
- DeviceListFragment:用于显示可以连接点列表及其状态。
- FileTransferService:通过 TCP 协议在客户端与服务器之间进行文件传输的 IntentService。
- IntentService:Sevice 的子类,用于处理异步请求。
该实例的运行效果如图 1 所示。
图 1 实例WIFIDirectDemo的运行效果
WIFIDirectDemo 的 AndroidManifest.xml 文件内容如下:WIFIDirectDemoActivity.java 的代码如下:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="introduction.android.wifidirectdemo">
- <uses-sdk android:minSdkVersion="14" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
- <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <!--Market filtering -->
- <uses-feature
- android:name="android.hardware.wifi.direct"
- android:required="true" />
- <application
- android:allowBackup="true"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/AppTheme">
- <activity android:name=".WIFIDirectDemoActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
- </manifest>
WiFiDirectBroadcastReceiver.java 的代码如下:
- package introduction.android.wifidirectdemo;
- import android.app.Activity;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.net.wifi.p2p.WifiP2pConfig;
- import android.net.wifi.p2p.WifiP2pDevice;
- import android.net.wifi.p2p.WifiP2pManager;
- import android.net.wifi.p2p.WifiP2pManager.ActionListener;
- import android.net.wifi.p2p.WifiP2pManager.Channel;
- import android.net.wifi.p2p.WifiP2pManager.ChannelListener;
- import android.os.Bundle;
- import android.provider.Settings;
- import android.util.Log;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.view.View;
- import android.widget.Toast;
- public class WIFIDirectDemoActivity extends Activity implements ChannelListener, DeviceListFragment.WiFiPeerListAdapter.DeviceActionListener {
- public static final String TAG = "wifidirectdemo";
- private WifiP2pManager manager;
- private boolean isWifiP2pEnabled = false;
- private boolean retryChannel = false;
- private final IntentFilter intentFilter = new IntentFilter();
- private Channel channel;
- private BroadcastReceiver receiver = null;
- public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
- this.isWifiP2pEnabled = isWifiP2pEnabled;
- }
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- // add necessary intent values to be matched.
- intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTI0N);
- intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTI0N);
- intentFilter.addAction(WifiP2pManager.WIFI_P2P_C0NNECTI0N_CHANGED_ACTI0N);
- intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTI0N);
- manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
- channel = manager.initialize(this, getMainLooper(), null);
- }
- /**
- * register the BroadcastReceiver with the intent values to be matched
- */
- public void onResume() {
- super.onResume();
- receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
- registerReceiver(receiver, intentFilter);
- }
- public void onPause() {
- super.onPause();
- unregisterReceiver(receiver);
- }
- /*
- *Remove all peers and clear all fields.This is called on
- *BroadcastReceiver receiving a state change event.
- */
- public void resetData() {
- DeviceListFragment fragmentList = (DeviceListFragment) getFragmentManager()
- .findFragmentById(R.id.frag_list);
- DeviceDetailFragment1 fragmentDetails = (DeviceDetailFragment1) getFragmentManager().findFragmentById(R.id.frag_detail);
- if (fragmentList != null) {
- fragmentList.clearPeers();
- }
- if (fragmentDetails != null) {
- fragmentDetails.resetViews();
- }
- }
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.action_items, menu);
- return true;
- }
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.atn_direct_enable:
- if (manager != null && channel != null) {
- startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
- } else {
- Log.e(TAG, "channel or manager is null");
- }
- return true;
- case R.id.atn_direct_discover:
- if (!isWifiP2pEnabled) {
- Toast.makeText(WIFIDirectDemoActivity.this, R.string.p2p_off_warning, Toast.LENGTHJSHORT).show();
- return true;
- }
- final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager().findFragmentByld(R.id.frag_list);
- fragment.onInitiateDiscovery();
- manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
- public void onSuccess() {
- Toast.makeText(WIFIDirectDemoActivity.this, "Discovery Initiated", Toast.LENGTH_SHORT).show();
- }
- public void onFailure(int reasonCode) {
- Toast.makeText(WIFIDirectDemoActivity.this, "Discovery Failed " + reasonCode, Toast.LENGTH_SHORT).show();
- }
- });
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
- public void showDetails(WifiP2pDevice device) {
- DeviceDetailFragmentl fragment = (DeviceDetailFragmentl) getFragmentManager().findFragmentById(R.id.frag_detail);
- fragment.showDetails(device);
- }
- public void connect(WifiP2pConfig config) {
- manager.connect(channel, config, new ActionListener() {
- public void onSuccess() {
- // WiFiDirectBroadcastReceiver will notify us. Ignore for now.
- }
- public void onFailure(int reason) {
- Toast.makeText(WIFIDirectDemoActivity.this, "Connect failed. Retry.", Toast.LENGTH_SHORT).show();
- }
- });
- }
- public void disconnect() {
- final DeviceDetailFragmentl fragment = (DeviceDetailFragmentl) getFragmentManager().findFragmentById(R.id.frag_detail);
- fragment.resetViews();
- manager.removeGroup(channel, new ActionListener() {
- public void onFailure(int reasonCode) {
- Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);
- }
- public void onSuccess() {
- fragment.getView().setVisibility(View.GONE);
- }
- });
- }
- public void onChannelDisconnected() {
- if (manager != null && !retryChannel) {
- Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show();
- resetData();
- retryChannel = true;
- manager.initialize(this, getMainLooper(), this);
- } else {
- Toast.makeText(this,
- "Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.",Toast.LENGTH_LONG).show();
- }
- }
- public void cancelDisconnect() {
- if (manager != null) {
- final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager().findFragmentById(R.id.frag_list);
- if (fragment.getDevice() == null
- || fragment.getDevice().status == WifiP2pDevice.CONNECTED) {
- disconnect();
- } else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE || fragment.getDevice().status == WifiP2pDevice.INVITED) {
- manager.cancelConnect(channel, new ActionListener() {
- public void onSuccess() {
- Toast.makeText(WIFIDirectDemoActivity.this, "Aborting connection", Toast.LENGTH_SHORT).show();
- }
- public void onFailure(int reasonCode) {
- Toast.makeText(WIFIDirectDemoActivity.this,
- "Connect abort request failed. Reason Code: " + reasonCode, Toast.LENGTH_SHORT).show();
- }
- });
- }
- }
- }
- }
DeviceListFragment.java 的代码如下:
- package introduction.android.wifidirectdemo;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.net.NetworkInfo;
- import android.net.wifi.p2p.WifiP2pDevice;
- import android.net.wifi.p2p.WifiP2pManager;
- import android.net.wifi.p2p.WifiP2pManager.Channel;
- import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
- import android.util.Log;
- public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {
- private WifiP2pManager manager;
- private Channel channel;
- private WIFIDirectDemoActivity activity;
- public WiFiDirectBroadcastReceiver(WifiP2pManager manager, Channel channel, WIFIDirectDemoActivity wifiDirectDemoActivity) {
- super();
- this.manager = manager;
- this.channel = channel;
- this.activity = wifiDirectDemoActivity;
- }
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
- // UI update to indicate wifi p2p status.
- int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
- if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
- // Wifi Direct mode is enabled activity.setlsWifiP2pEnabled (true) ;
- } else {
- activity.setIsWifiP2pEnabled(false);
- activity.resetData();
- }
- Log.d(WIFIDirectDemoActivity.TAG, "P2P state changed - " + state);
- } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
- // request available peers from the wifi p2p manager. This is an
- // asynchronous call and the calling activity is notified with a
- // callback on PeerListListener.onPeersAvailable() if (manager !=null) {
- manager.requestPeers(channel, (PeerListListener) activity.getFragmentManager().findFragmentById(R.id.frag_list));
- Log.d(WIFIDirectDemoActivity.TAG, "P2P peers changed");
- } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
- if (manager == null) {
- return;
- }
- NetworkInfo networkInfo = (NetworkInfo) intent
- .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
- if (networkInfo.isConnected()) {
- // we are connected with the other device, request connection
- // info to find group owner IP
- DeviceDetailFragment1 fragment = (DeviceDetailFragmentl) activity.getFragmentManager().findFragmentById(R.id.frag_detail);
- manager.requestConnectionlnfo(channel, fragment);
- } else {
- // It's a disconnect
- activity.resetData();
- }
- } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)){
- DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
- .findFragmentById(R.id.frag_list);
- fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
- WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));
- }
- }
- }
FileTransferService.java 的代码如下:
- package introduction.android.wifidirectdemo;
- import android.app.ListFragment;
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.net.wifi.p2p.WifiP2pConfig;
- import android.net.wifi.p2p.WifiP2pDevice;
- import android.net.wifi.p2p.WifiP2pDeviceList;
- import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.ArrayAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
- import java.util.ArrayList;
- import java.util.List;
- public class DeviceListFragment extends ListFragment implements PeerListListener {
- private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
- ProgressDialog progressDialog = null;
- View mContentView = null;
- private WifiP2pDevice device;
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- this.setListAdapter(new WiFiPeerListAdapter(getActivity(), R.layout.row_devices,
- peers));
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
- savedInstanceState) {
- mContentView = inflater.inflate(R.layout.device_list, null);
- return mContentView;
- }
- /* return this device */
- public WifiP2pDevice getDevice() {
- return device;
- }
- private static String getDeviceStatus(int deviceStatus) {
- Log.d(WIFIDirectDemoActivity.TAG, "Peer status :" + deviceStatus);
- switch (deviceStatus) {
- case WifiP2pDevice.AVAILABLE:
- return "Available";
- case WifiP2pDevice.INVITED:
- return "Invited";
- case WifiP2pDevice.CONNECTED:
- return "Connected";
- case WifiP2pDevice.FAILED:
- return "Failed";
- case WifiP2pDevice.UNAVAILABLE:
- return "Unavailable";
- default:
- return "Unknown";
- }
- }
- /**
- * Initiate a connection with the peer.
- */
- @Override
- public void onListItemClick(ListView l, View v, int position, long id) {
- WifiP2pDevice device = (WifiP2pDevice) getListAdapter().getItem(position);
- ((DeviceActionListener) getActivity()).showDetails(device);
- }
- /*
- Array adapter for ListFragment that maintains WifiP2pDevice list.
- */
- public class WiFiPeerListAdapter extends ArrayAdapter<WifiP2pDevice> {
- private List<WifiP2pDevice> items;
- public WiFiPeerListAdapter(Context context, int textViewResourceId, List<WifiP2pDevice> objects) {
- super(context, textViewResourceId, objects);
- items = objects;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View v = convertView;
- if (v == null) {
- LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- v = vi.inflate(R.layout.row_devices, null);
- }
- WifiP2pDevice device = items.get(position);
- if (device != null) {
- TextView top = (TextView) v.findViewById(R.id.device_name);
- TextView bottom = (TextView) v.findViewById(R.id.device_details);
- if (top != null) {
- top.setText(device.deviceName);
- }
- if (bottom != null) {
- bottom.setText(getDeviceStatus(device.status));
- }
- }
- return v;
- }
- public void updateThisDevice(WifiP2pDevice device) {
- this.device = device;
- TextView view = (TextView) mContentView.findViewById(R.id.my_name);
- view.setText(device.deviceName);
- view = (TextView) mContentView.findViewById(R.id.my_status);
- view.setText(getDeviceStatus(device.status));
- }
- public void onPeersAvailable(WifiP2pDeviceList peerList) {
- if (progressDialog != null && progressDialog.isShowing()) {
- progressDialog.dismiss();
- }
- peers.clear();
- peers.addAll(peerList.getDeviceList());
- ((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
- if (peers.size() == 0) {
- Log.d(WIFIDirectDemoActivity.TAG, "No devices found");
- return;
- }
- }
- public void clearPeers() {
- peers.clear();
- ((WiFiPeerListAdapter) getListAdapter()).notifyDataSetChanged();
- }
- public void onInitiateDiscovery() {
- if (progressDialog != null && progressDialog.isShowing()) {
- progressDialog.dismiss();
- }
- progressDialog = ProgressDialog.show(getActivity(), "Press back to cancel", true,
- true, new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- }
- });
- }
- public interface DeviceActionListener {
- void showDetails(WifiP2pDevice device);
- void cancelDisconnect();
- void connect(WifiP2pConfig config);
- void disconnect();
- }
- }
- }
- package introduction.android.wifidirectdemo;
- import android.app.IntentService;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.content.Intent;
- import android.net.Uri;
- import android.util.Log;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.InetSocketAddress;
- import java.net.Socket;
- public class FileTransferService extends IntentService {
- private static final int SOCKET_TIMEOUT = 5000;
- public static final String ACTION_SEND_FILE = "com.example.android.wifidirect.SEND_FILE"
- public static final String EXTRAS_FILE_PATH = "file_url";
- public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
- public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";
- public FileTransferService(String name) {
- super(name);
- }
- public FileTransferService() {
- super("FileTransferService");
- }
- @Override
- protected void onHandleIntent(Intent intent) {
- Context context = getApplicationContext();
- if (intent.getAction().equals(ACTION_SEND_FILE)) {
- String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
- String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
- Socket socket = new Socket();
- int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
- try {
- Log.d(WIFIDirectDemoActivity.TAG, "Opening client socket - ");
- socket.bind(null);
- socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
- Log.d(WIFIDirectDemoActivity.TAG, "Client socket - " + socket.isConnected())
- OutputStream stream = socket.getOutputStream();
- ContentResolver cr = context.getContentResolver();
- InputStream is = null;
- try {
- is = cr.openInputStream(Uri.parse(fileUri));
- } catch (FileNotFoundException e) {
- Log.d(WIFIDirectDemoActivity.TAG, e.toString());
- }
- DeviceDetailFragment1.copyFile(is, stream);
- Log.d(WIFIDirectDemoActivity.TAG, "Client: Data written");
- } catch (IOException e) {
- Log.e(WIFIDirectDemoActivity.TAG, e.getMessage());
- } finally {
- if (socket != null) {
- if (socket.isConnected()) {
- try {
- socket.close();
- } catch (IOException e) {
- // Give up
- e.printStackTrace();
- }
- }
- }
- }
- }
- }
- }