package com.wifiscanner.service; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; 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.os.Bundle; import android.os.ResultReceiver; import com.wifiscanner.listener.WifiP2PConnectionCallback; import com.wifiscanner.receiver.WiFiDirectBroadcastReceiver; import com.wifiscanner.server.ServerDataService; import com.wifiscanner.tasks.DataServerTask; import com.wifiscanner.utils.PreferenceUtils; import com.wifiscanner.utils.Utils; import java.lang.reflect.Method; import static com.wifiscanner.WifiConstants.ACTION_SEND_FILE; import static com.wifiscanner.WifiConstants.DEFAULT_WIFI_PORT; import static com.wifiscanner.WifiConstants.EXTRAS_DATA; import static com.wifiscanner.WifiConstants.EXTRAS_GROUP_OWNER_ADDRESS; import static com.wifiscanner.WifiConstants.EXTRAS_GROUP_OWNER_PORT; import static com.wifiscanner.WifiConstants.EXTRAS_MESSAGE; import static com.wifiscanner.WifiConstants.EXTRAS_RESULT_RECEIVER; import static com.wifiscanner.WifiConstants.PREFS_CLIENT_KEY; import static com.wifiscanner.WifiConstants.RECEIVER_PREFS_VALUE; import static com.wifiscanner.WifiConstants.SENDER_PREFS_VALUE; import static com.wifiscanner.WifiConstants.STATUS_CONNECTING; import static com.wifiscanner.WifiConstants.STATUS_FAILURE; import static com.wifiscanner.WifiConstants.STATUS_SUCCESS; public class WifiP2PServiceImpl implements WifiP2PService { private Activity activity; private WifiP2pManager manager; private WifiManager wifiManager; private WifiP2pManager.Channel channel; private BroadcastReceiver wifiDirectBroadcastReceiver; private WifiP2PConnectionCallback wifiP2PConnectionCallback; private WifiP2PServiceImpl(Builder builder) { this.activity = builder.activity; this.wifiP2PConnectionCallback = builder.wifiP2PConnectionCallback; PreferenceUtils.setStringValues(activity, PREFS_CLIENT_KEY, builder.prefsKey); } @Override public synchronized void onCreate() { manager = (WifiP2pManager) activity.getSystemService(Context.WIFI_P2P_SERVICE); channel = manager.initialize(activity.getApplicationContext(), activity.getMainLooper(), null); this.wifiManager = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE); } @Override public synchronized void onResume() { if (!wifiManager.isWifiEnabled()) wifiManager.setWifiEnabled(true); wifiDirectBroadcastReceiver = new WiFiDirectBroadcastReceiver(this); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); activity.registerReceiver(wifiDirectBroadcastReceiver, intentFilter); } @Override public synchronized void onStop() { try { activity.unregisterReceiver(wifiDirectBroadcastReceiver); deletePersistentGroups(); disconnectDevice(); } catch (Exception e) {} } @Override public synchronized void onDestroy() { } @Override public synchronized void handleOnWifiStateChanged(int state) { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onInitiateDiscovery(); } }); } initiateDiscovery(); } @Override public synchronized void initiateDiscovery() { manager.discoverPeers(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onDiscoverySuccess(); } }); } } @Override public void onFailure(int i) { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onDiscoveryFailure(); } }); } } }); } @Override public synchronized void connectDevice(WifiP2pDevice wifiP2pDevice) { WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = wifiP2pDevice.deviceAddress; config.wps.setup = WpsInfo.PBC; config.groupOwnerIntent = 15; manager.connect(channel, config, new WifiP2pManager.ActionListener() { @Override public void onSuccess() {} @Override public void onFailure(int reason) { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onPeerConnectionFailure(); } }); } } }); } @Override public synchronized void disconnectDevice() { if(manager == null) return; manager.removeGroup(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() {} @Override public void onFailure(int i) { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onPeerDisconnectionFailure(); } }); } } }); } @Override public synchronized void handleOnPeersChangedResponse() { manager.requestPeers(channel, new WifiP2pManager.PeerListListener() { @Override public void onPeersAvailable(final WifiP2pDeviceList wifiP2pDeviceList) { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onPeerAvailable(wifiP2pDeviceList); } }); } } }); } @Override public synchronized void handleOnPeerConnected() { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onPeerConnectionSuccess(); boolean isClient = RECEIVER_PREFS_VALUE.equalsIgnoreCase(PreferenceUtils.getStringValues(activity, PREFS_CLIENT_KEY)); if(isClient) startDataTransfer(null); } }); } } @Override public synchronized void handleOnPeerDisconnected() { if(wifiP2PConnectionCallback != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onPeerDisconnectionSuccess(); } }); } } @Override public synchronized void handleOnDeviceStatusChanged(WifiP2pDevice wifiP2pDevice) { if(wifiP2pDevice.status == WifiP2pDevice.CONNECTED) { // handleOnPeerConnected(); } } @Override public void startDataTransfer(final String message) { manager.requestConnectionInfo(channel, new WifiP2pManager.ConnectionInfoListener() { @Override public void onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo) { boolean isGroupOwner = wifiP2pInfo.groupFormed && wifiP2pInfo.isGroupOwner; boolean isClient = RECEIVER_PREFS_VALUE.equalsIgnoreCase(PreferenceUtils.getStringValues(activity, PREFS_CLIENT_KEY)); if(isClient && isGroupOwner) { handleOnPeerServer(wifiP2pInfo); } else if(!isClient && !isGroupOwner && message != null) { handleOnPeerClient(wifiP2pInfo, message); } } }); } @Override public void handleOnPeerServer(WifiP2pInfo wifiP2pInfo) { new DataServerTask(wifiP2PConnectionCallback, DEFAULT_WIFI_PORT).execute(); } @Override public void handleOnPeerClient(WifiP2pInfo wifiP2pInfo, String message) { Intent serviceIntent = new Intent(activity, ServerDataService.class); serviceIntent.setAction(ACTION_SEND_FILE); serviceIntent.putExtra(EXTRAS_DATA, message); serviceIntent.putExtra(EXTRAS_GROUP_OWNER_ADDRESS, wifiP2pInfo.groupOwnerAddress == null ? "" : wifiP2pInfo.groupOwnerAddress.getHostAddress()); serviceIntent.putExtra(EXTRAS_GROUP_OWNER_PORT, DEFAULT_WIFI_PORT); serviceIntent.putExtra(EXTRAS_RESULT_RECEIVER, new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, final Bundle resultData) { if(resultCode == DEFAULT_WIFI_PORT && resultData != null) { int status = Integer.valueOf(String.valueOf(resultData.get(EXTRAS_MESSAGE))); switch (status) { case STATUS_CONNECTING: activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onDataTransferring(); } }); break; case STATUS_SUCCESS: activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onDataTransferredSuccess(); } }); break; case STATUS_FAILURE: activity.runOnUiThread(new Runnable() { @Override public void run() { wifiP2PConnectionCallback.onDataTransferredFailure(); } }); break; } } } }); activity.startService(serviceIntent); } private void deletePersistentGroups() { try { Method[] methods = WifiP2pManager.class.getMethods(); for (int i = 0; i < methods.length; i++) { if (methods[i].getName().equals("deletePersistentGroup")) { // Delete any persistent group for (int netid = 0; netid < 32; netid++) { methods[i].invoke(manager, channel, netid, null); } } } } catch (Exception e) { e.printStackTrace(); } } public static class Builder { private String prefsKey; private Activity activity; private WifiP2PConnectionCallback wifiP2PConnectionCallback; public Builder setSender(Activity activity) { this.activity = activity; this.prefsKey = RECEIVER_PREFS_VALUE; return this; } public Builder setReceiver(Activity activity) { this.activity = activity; this.prefsKey = SENDER_PREFS_VALUE; return this; } public Builder setWifiP2PConnectionCallback(WifiP2PConnectionCallback wifiP2PConnectionCallback) { this.wifiP2PConnectionCallback = wifiP2PConnectionCallback; return this; } public WifiP2PServiceImpl build() { return new WifiP2PServiceImpl(this); } } }