package org.ecjtu.channellibrary.wifidirect; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.Method; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WpsInfo; import android.net.wifi.p2p.WifiP2pConfig; import android.net.wifi.p2p.WifiP2pDevice; import android.net.wifi.p2p.WifiP2pDeviceList; import android.net.wifi.p2p.WifiP2pInfo; 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.ConnectionInfoListener; import android.net.wifi.p2p.WifiP2pManager.PeerListListener; import android.os.Handler; import android.os.Message; import org.ecjtu.channellibrary.wifidirect.util.Utilities; import org.ecjtu.channellibrary.wifidirect.util.ALog; @SuppressLint("NewApi") public class WifiDirectManager implements ConnectionInfoListener, PeerListListener { private static final String TAG = "WifiDirectManager"; // singleton private static WifiDirectManager sInstance = null; private String mWifiP2pGroupOwnerAddress = null; private String mRemoteWifiP2pDeviceAddress = null; // private int mLatestConnectedWifiType = Utilities.WIFI_CONNECTED_NONE; private Context mContext; private Channel mWifiChannel; private WifiP2pManager mWifiP2pManager; private WifiP2pInfo mWifiP2pInfo; private WifiP2pDevice mWifiP2pDevice; private WifiManager mWifiManager; private boolean mIsWifiP2pConnected = false; // private boolean mIsWifiP2pSocketConnected = false; private boolean mIsWifiP2pEnabled = false; public static final String WIFI_DIRECT_DISCOVERED_PEER_ACTION="wifidirect.action.DISCOVERED_PEER_ACTION"; public static final String WIFI_DIRECT_CONNECTED_ACTION="wifidirect.action.CONNECTED_ACTION"; public static final String WIFI_DIRECT_CONNECTION_INFO_AVAILABLE_ACTION="wifidirect.action.CONNECTION_INFO_AVAILABLE_ACTION"; public static final String WIFI_DIRECT_CONNECT_FAILED="wifidirect.action.CONNECT_FAILED"; public static final String WIFI_DIRECT_BEGIN_SEARCHING_ACTION="wifidirect.action.BEGIN_SEARCHING_ACTION"; public static final String WIFI_DIRECT_END_SEARCHING_ACTION="wifidirect.action.END_SEARCHING_ACTION"; private List<WifiP2pDevice> mWifiP2pPeers = new ArrayList<WifiP2pDevice>(); private final Handler mManagerHandler = new Handler() { @Override public void handleMessage(Message msg) { ALog.i(TAG, "mManagerHandler msg.what:" + msg.what); switch (msg.what) { case Utilities.MSG_WIFI_DISCOVER_PEER_FAILED: ALog.i(TAG, "Wifi discover peer failed.now retry"); discover((ActionListener)msg.obj); break; case Utilities.MSG_WIFI_DISCOVER_STOP_FAILED: ALog.i(TAG, "Wifi discover stop failed.now retry"); stopDiscover((ActionListener)msg.obj); break; case Utilities.MSG_WIFI_DISCOVER_PEER_SUCCESS: ALog.i(TAG, "Wifi discover peer success."); sendWifiDirectBroadcast(WIFI_DIRECT_DISCOVERED_PEER_ACTION); break; case Utilities.MSG_WIFI_CONNECT_FAILED: ALog.i(TAG, "Wifi connect failed."); break; case Utilities.MSG_WIFI_CONNECT_SUCCESS: ALog.i(TAG, "Wifi connect success."); sendWifiDirectBroadcast(WIFI_DIRECT_CONNECT_FAILED); break; case Utilities.MSG_WIFI_CONNECTED: mIsWifiP2pConnected = true; ALog.i(TAG, "Wifi now p2pConnected."); sendWifiDirectBroadcast(WIFI_DIRECT_CONNECTED_ACTION); break; } } }; private void sendWifiDirectBroadcast(String action) { Intent intent = new Intent(action); mContext.sendBroadcast(intent); } public String getWifiMacAddress(Context context) { WifiManager wifiManager = (WifiManager) context.getSystemService(context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress(); ALog.i(TAG, "getWifiMacAddress macAddress:" + macAddress); return macAddress; } private void init(Context context) { ALog.i(TAG, "init-----------"); if (mContext == null) { mContext = context; } // mLatestConnectedWifiType = Utilities.WIFI_CONNECTED_NONE; if (mWifiManager == null) { mWifiManager = (WifiManager) context.getApplicationContext() .getSystemService(Context.WIFI_SERVICE); } if (mWifiP2pManager == null) { mWifiP2pManager = (WifiP2pManager) context .getSystemService(Context.WIFI_P2P_SERVICE); } if (mWifiChannel == null && mWifiP2pManager != null) { mWifiChannel = mWifiP2pManager.initialize(context, context.getMainLooper(), null); } } public static synchronized WifiDirectManager getInstance(Context context) { ALog.i(TAG, "getInstance sInstance:" + sInstance); if (sInstance == null) { sInstance = new WifiDirectManager(); sInstance.init(context); } return sInstance; } public static synchronized WifiDirectManager getInstance() { ALog.i(TAG, "getInstance sInstance:" + sInstance); return sInstance; } public Handler getManagerHandler() { return mManagerHandler; } public void disconnectWifiDirect() { if (mWifiP2pDevice != null) { ALog.i(TAG, "disconnectWifiDirect mWifiP2pDevice.status:" + mWifiP2pDevice.status); if (mWifiP2pDevice.status == WifiP2pDevice.CONNECTED) { disconnect(); } else if (mWifiP2pDevice.status == WifiP2pDevice.AVAILABLE || mWifiP2pDevice.status == WifiP2pDevice.INVITED) { cancelConnect(); } } } public void setWifiP2pInfo(WifiP2pInfo info) { mWifiP2pInfo = info; ALog.i(TAG, "setWifiP2pInfo mWifiP2pInfo:" + mWifiP2pInfo); } public void setWifiP2pDevice(WifiP2pDevice device) { mWifiP2pDevice = device; ALog.i(TAG, "setWifiP2pDevice device:" + device.deviceAddress); } public void setIsWifiP2pConnected(boolean isConnected) { mIsWifiP2pConnected = isConnected; } public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) { mIsWifiP2pEnabled = isWifiP2pEnabled; } public void setWifiEnabled() { if (!mWifiManager.isWifiEnabled()) { mWifiManager.setWifiEnabled(true); } } public void setWifiDisabled() { if (mWifiManager.isWifiEnabled()) { mWifiManager.setWifiEnabled(false); } } public boolean isWifiP2pEnabled() { return mIsWifiP2pEnabled; } public WifiP2pManager getWifiP2pManager() { return mWifiP2pManager; } public WifiP2pDevice getWifiP2pDevice() { return mWifiP2pDevice; } public Channel getChannel() { return mWifiChannel; } public List<WifiP2pDevice> getWifiP2pPeers() { return mWifiP2pPeers; } public void discover(ActionListener actionListener) { ALog.i(TAG, "discover mWifiP2pManager:" + mWifiP2pManager); if(!mWifiManager.isWifiEnabled()) mWifiManager.setWifiEnabled(true); if (mWifiP2pManager != null) { if(actionListener==null){ final ActionListener fActionListener=actionListener; actionListener=new ActionListener() { private int mRetryTimes=0; @Override public void onSuccess() { ALog.i(TAG, "discover onSuccess!"); mRetryTimes=3; } @Override public void onFailure(int reason) { ALog.i(TAG, "discover failed reason:" + errorCode2String(reason)); if(mRetryTimes>=3) return; // Message msg = mManagerHandler.obtainMessage(Utilities.MSG_WIFI_DISCOVER_PEER_FAILED); // msg.obj=fActionListener; // mManagerHandler.sendMessageDelayed(msg, 500); mRetryTimes++; } }; } mWifiP2pManager.discoverPeers(mWifiChannel, actionListener); } } public void stopDiscover(ActionListener actionListener){ if(mWifiP2pManager!=null){ final ActionListener fActionListener=actionListener; if(actionListener==null){ actionListener=new ActionListener() { private int mRetryTimes=0; @Override public void onSuccess() { ALog.i(TAG, "stopDiscover onSuccess"); mRetryTimes=3; } @Override public void onFailure(int reason) { ALog.i(TAG, "stopDiscover failed reason:" + errorCode2String(reason)); if(mRetryTimes>=3) return; // Message msg = mManagerHandler.obtainMessage(Utilities.MSG_WIFI_DISCOVER_STOP_FAILED); // msg.obj=fActionListener; // mManagerHandler.sendMessageDelayed(msg, 500); mRetryTimes++; } }; } mWifiP2pManager.stopPeerDiscovery(mWifiChannel, actionListener); } } public static final int ERROR = 0; public static final int P2P_UNSUPPORTED = 1; public static final int BUSY = 2; public String errorCode2String(int code) { String res = null; switch (code) { case 0: res = "WifiDirect has an error."; break; case 1: res = "WifiDirect is unsupported."; break; case 2: res = "framework is busy.do wifi is open?"; break; } return res; } public void connect(WifiP2pConfig config) { ALog.i(TAG, "connect mWifiP2pManager:" + mWifiP2pManager + ", config:" + config); if (mWifiP2pManager != null) { mWifiP2pManager.connect(mWifiChannel, config, new ActionListener() { @Override public void onSuccess() { ALog.v(TAG, "connect onSuccess!"); Message msg = mManagerHandler.obtainMessage(Utilities.MSG_WIFI_CONNECT_SUCCESS); mManagerHandler.sendMessage(msg); } @Override public void onFailure(int reason) { ALog.v(TAG, "connect failed reason:" + reason); // Message msg = mManagerHandler.obtainMessage(Utilities.MSG_WIFI_CONNECT_FAILED); // if(mManagerHandler.hasMessages(Utilities.MSG_WIFI_CONNECT_FAILED)) // return; // mManagerHandler.sendMessageDelayed(msg, 500); } }); } } public void disconnect() { ALog.i(TAG, "disconnect mWifiP2pManager:" + mWifiP2pManager + ", mWifiChannel:" + mWifiChannel); if (mWifiP2pManager != null) { mWifiP2pManager.removeGroup(mWifiChannel, new ActionListener() { @Override public void onSuccess() { ALog.v(TAG, "disconnect onSuccess!"); } @Override public void onFailure(int reason) { ALog.v(TAG, "disconnect failed reason:" + reason); } }); } } public void cancelConnect() { ALog.i(TAG, "cancelDisconnect mWifiP2pManager:" + mWifiP2pManager + ", mWifiChannel:" + mWifiChannel); if (mWifiP2pManager != null) { mWifiP2pManager.cancelConnect(mWifiChannel, new ActionListener() { @Override public void onSuccess() { ALog.v(TAG, "cancelDisconnect onSuccess!"); } @Override public void onFailure(int reason) { ALog.v(TAG, "cancelDisconnect failed reason:" + reason); } }); } } @Override public void onPeersAvailable(WifiP2pDeviceList peers) { ALog.i(TAG, "onPeersAvailable mRemoteWifiP2pDeviceAddress:" + mRemoteWifiP2pDeviceAddress); mWifiP2pPeers.clear(); mWifiP2pPeers.addAll(peers.getDeviceList()); if (mRemoteWifiP2pDeviceAddress != null) { int size = mWifiP2pPeers.size(); for (int i = 0; i < size; i++) { WifiP2pDevice device = mWifiP2pPeers.get(i); ALog.i(TAG, "onPeersAvailable i:" + i + ", address:" + device.deviceAddress + ", name:" + device.deviceName); if (mRemoteWifiP2pDeviceAddress.substring(3).equals(device.deviceAddress.substring(3))) { mRemoteWifiP2pDeviceAddress = device.deviceAddress; } } } else { int size = mWifiP2pPeers.size(); if (size > 0) { WifiP2pDevice device = mWifiP2pPeers.get(0); mRemoteWifiP2pDeviceAddress = device.deviceAddress; } } Message msg = mManagerHandler .obtainMessage(Utilities.MSG_WIFI_DISCOVER_PEER_SUCCESS); mManagerHandler.sendMessageDelayed(msg, 500); } @Override public void onConnectionInfoAvailable(WifiP2pInfo info) { ALog.i(TAG, "onConnectionInfoAvailable info:" + info + ", mIsWifiP2pConnected:" + mIsWifiP2pConnected); doWifiDirectConnectionAvailable(info); } public void doWifiDirectConnectionAvailable(WifiP2pInfo info) { if (mIsWifiP2pConnected) { return; } if (info != null && info.groupOwnerAddress != null) { mWifiP2pGroupOwnerAddress = info.groupOwnerAddress.getHostAddress(); ALog.i(TAG, "doWifiDerectConnectionAvailable mWifiP2pGroupOwnerAddress:" + mWifiP2pGroupOwnerAddress); } if(info==null){ mWifiP2pManager.requestConnectionInfo(getChannel(), this); return; } setWifiP2pInfo(info); Message msg = mManagerHandler.obtainMessage(Utilities.MSG_WIFI_CONNECTED); mManagerHandler.sendMessage(msg); mIsWifiP2pConnected = true; mContext.sendBroadcast(new Intent(WIFI_DIRECT_CONNECTION_INFO_AVAILABLE_ACTION)); /* if (info.groupFormed && info.isGroupOwner) { ALog.i(TAG, "doWifiDirectConnectionAvailable is GroupOwner!!"); } else if (info.groupFormed) { }*/ } public void onWifiEnabled() { // common connect } public void onClearData() { ALog.i(TAG, "onClearData"); mIsWifiP2pConnected = false; // mIsWifiP2pSocketConnected = false; // mLatestConnectedWifiType = Utilities.WIFI_CONNECTED_NONE; mWifiP2pPeers.clear(); } public WifiP2pInfo getWifiP2pInfo() { return mWifiP2pInfo; } public String getWifiP2pGroupOwnerAddress(){ return mWifiP2pGroupOwnerAddress; } public String getRemoteP2pDeviceMacAddress(){ return mRemoteWifiP2pDeviceAddress; } public void wifiP2pConnect() { ALog.i(TAG, "wifiP2pConnect mRemoteWifiP2pDeviceAddress:" + mRemoteWifiP2pDeviceAddress); WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = mRemoteWifiP2pDeviceAddress; config.wps.setup = WpsInfo.PBC; } // @SuppressWarnings("resource") // public List<String> getLocalP2pIPFromArp() // { // BufferedReader reader=null; // String line; // List<String> list=new ArrayList<>(); // try { // reader=new BufferedReader(new FileReader("/proc/net/arp")); // while((line=reader.readLine())!=null){ // String[] params=line.split("\\s+"); // // int size=params.length-1; // // if (params[size].contains("p2p")) { // list.add(params[0]); // } // } // reader.close(); // } catch (Exception e) { // e.printStackTrace(); // } // return list; // } public String getLocalP2PIP(){ try { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); String iface = intf.getName(); if(iface.contains("p2p")){ if (inetAddress instanceof Inet4Address) { // fix for Galaxy Nexus. IPv4 is easy to use :-) return getDottedDecimalIP(inetAddress.getAddress()); } } } } } catch (SocketException ex) { // Log.e("AndroidNetworkAddressFactory", "getLocalIPAddress()", ex); } catch (NullPointerException ex) { // Log.e("AndroidNetworkAddressFactory", "getLocalIPAddress()", ex); } return null; } public String[] getLocalWLANIps(){ List<String> result=new ArrayList<>(); try { for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); String iface = intf.getName(); if(iface.contains("wlan")){ if (inetAddress instanceof Inet4Address) { // fix for Galaxy Nexus. IPv4 is easy to use :-) result.add(getDottedDecimalIP(inetAddress.getAddress())); } } } } } catch (SocketException ex) { } catch (NullPointerException ex) { } return result.toArray(new String[result.size()]); } private static String getDottedDecimalIP(byte[] ipAddr) { String ipAddrStr = ""; for (int i=0; i<ipAddr.length; i++) { if (i > 0) { ipAddrStr += "."; } ipAddrStr += ipAddr[i]&0xFF; } return ipAddrStr; } /** * ARP表中没有本机IP信息? * */ @SuppressWarnings("resource") public String getIPFromMac(String MAC) { BufferedReader reader=null; String line; try { reader=new BufferedReader(new FileReader("/proc/net/arp")); while((line=reader.readLine())!=null){ String[] params=line.split("\\s+"); if(params[3].equals(MAC)) return params[0]; } reader.close(); } catch (IOException e) { } return null; } public void setLatestConnectedWifiDevice(WifiP2pDevice device, int type) { // mLatestConnectedWifiType = type; } public WifiManager getWifiManager(){ return mWifiManager; } public void setDeviceName(String name){ // setDeviceName(Channel c, String devName, ActionListener listener) Class<WifiP2pManager> clzz = WifiP2pManager.class; ActionListener listener=new ActionListener() { @Override public void onSuccess() { ALog.i(TAG, "setDeviceName succees"); } @Override public void onFailure(int reason) { ALog.i(TAG, "setDeviceName failure"); } }; Method m=null; try { m=clzz.getDeclaredMethod("setDeviceName", new Class[]{Channel.class,String.class,ActionListener.class}); m.setAccessible(true); m.invoke(mWifiP2pManager, getChannel(),name,listener); } catch (Exception e) { e.printStackTrace(); } finally{ if(m!=null) m.setAccessible(false); } } public static String getDeviceStatus(int 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 error"; } } }