package eu.hgross.blaubot.android.wifip2p;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pGroup;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import eu.hgross.blaubot.util.Log;
/**
* A BroadcastReceiver that gets notified on important WIFI Direct events.
* This events can be retrieved by regsitering a {@link IBlaubotWifiDirectEventListener}s
* to this object via addEventListener(..).
*
* @author Henning Gross {@literal (mail.to@henning-gross.de)}
*
*/
public class BlaubotWifiP2PBroadcastReceiver extends BroadcastReceiver {
protected static final String LOG_TAG = "WifiP2PBroadcastReceiver";
/**
* If true, events will be logged.
*/
private static final boolean LOG_EVENTS = false;
/**
* Threadpool used to notify listenres.
*/
private ExecutorService executorService = Executors.newCachedThreadPool();
/**
* The wifi manager obtained from the android context
*/
private WifiP2pManager mManager;
/**
* The initialized wifi channel to operate on
*/
private Channel mChannel;
/**
* The attached listeners to this receiver
*/
private List<IBlaubotWifiDirectEventListener> eventListeners;
/**
* The needed {@link WifiP2pManager} and {@link Channel} can be retrieved like this:
* mManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE);
* mChannel = mManager.initialize(context, context.getMainLooper(), null);
*
* @param manager the {@link WifiP2pManager} manager instace
* @param channel the channel
*/
public BlaubotWifiP2PBroadcastReceiver(WifiP2pManager manager, Channel channel) {
super();
this.mManager = manager;
this.mChannel = channel;
this.eventListeners = new CopyOnWriteArrayList<BlaubotWifiP2PBroadcastReceiver.IBlaubotWifiDirectEventListener>();
}
public interface IBlaubotWifiDirectEventListener {
/**
* Called when the P2PWifiManager's state changed to enabled
*/
public void onP2PWifiEnabled();
/**
* Called when the P2PWifiManager's state changed to disabled
*/
public void onP2PWifiDisabled();
/**
* Called when a discovery for WifiDirect devices was started.
*/
public void onDiscoveryStarted();
/**
* Called when a discovery for WifiDirect devices was stopped/finished.
*/
public void onDiscoveryStopped();
/**
* Called when the list of CURRENTLY AVAILBALE devices changed.
* @param deviceList the list of currently available devices
*/
public void onListOfPeersChanged(WifiP2pDeviceList deviceList);
/**
* Called on changes to the P2p-WiFi connectivity like connects, disconnects, ...
* @param p2pInfo the p2p2 info containing group owner state, group owner ip, ...
* @param networkInfo the network information
* @param group the group of which the connectivity changed
*/
public void onConnectivityChanged(WifiP2pInfo p2pInfo, NetworkInfo networkInfo, WifiP2pGroup group);
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Received intent: WIFI_P2P_STATE_CHANGED_ACTION");
}
// Check to see if Wi-Fi is enabled and notify appropriate activity
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Wifi P2P is now enabled");
}
notify_p2p_enabled();
} else {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Wi-Fi P2P is now disabled ");
}
notify_p2p_disabled();
}
} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Received intent: WIFI_P2P_PEERS_CHANGED_ACTION");
}
// -- the list of AVAILABLE peers has changed
// Call WifiP2pManager.requestPeers() to get a list of current peers
// 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 (mManager != null) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Requesting peers ...");
}
mManager.requestPeers(mChannel, new PeerListListener() {
@Override
public void onPeersAvailable(WifiP2pDeviceList peers) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Got available peers: " + peers.getDeviceList());
}
notify_list_of_peers_changed(peers);
}
});
}
} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
/*
* Broadcast intent action indicating that the state of Wi-Fi p2p connectivity has changed. One extra
* EXTRA_WIFI_P2P_INFO provides the p2p connection info in the form of a WifiP2pInfo object. Another extra
* EXTRA_NETWORK_INFO provides the network info in the form of a NetworkInfo. A third extra provides the
* details of the group.
*/
// Respond to new connection or disconnections
WifiP2pInfo p2pInfo = (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
WifiP2pGroup wifiP2pGroup = (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);// --> at higher api levels
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Received intent: WIFI_P2P_CONNECTION_CHANGED_ACTION");
Log.d(LOG_TAG, "WIFI_P2P_CONNECTION_CHANGED_ACTION.p2pInfo: " + p2pInfo);
Log.d(LOG_TAG, "WIFI_P2P_CONNECTION_CHANGED_ACTION.networkInfo: " + networkInfo);
Log.d(LOG_TAG, "WIFI_P2P_CONNECTION_CHANGED_ACTION.wifiP2pGroup: " + wifiP2pGroup);
}
notify_connectivity_changed(p2pInfo, networkInfo, wifiP2pGroup);
} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "Received intent: WIFI_P2P_THIS_DEVICE_CHANGED_ACTION");
}
// Respond to this device's wifi state changing
} else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {
// indicating that peer discovery has either started or stopped
int newState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE, -1);
if (newState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "P2P Discovery started");
}
// discovery started
notify_discovery_started();
} else if(newState == WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED) {
if(Log.logDebugMessages() && LOG_EVENTS) {
Log.d(LOG_TAG, "P2P Discovery stopped");
}
// discovery stopped
notify_discovery_stopped();
} else {
// newState == -1
if(Log.logWarningMessages() && LOG_EVENTS) {
Log.w(LOG_TAG, "Got WIFI_P2P_DISCOVERY_CHANGED_ACTION intent but could not determine the discovery state (state = " + newState + " )");
}
}
}
}
/**
* Adds an event listener to this receiver.
* @param listener the listener to be attached
*/
public void addEventListener(IBlaubotWifiDirectEventListener listener) {
this.eventListeners.add(listener);
}
/**
* Removes an event listener from this receiver, if registered.
* @param listener the listener to be attached
*/
public void removeEventListener(IBlaubotWifiDirectEventListener listener) {
this.eventListeners.remove(listener);
}
/**
* Creates an {@link IntentFilter} for the WIFIDirect intents needed by this {@link BroadcastReceiver}.
*
* @return the set up {@link IntentFilter}
*/
public static IntentFilter createWifiP2PIntentFilter() {
// register wifip2p related intents
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
return mIntentFilter;
}
/*
* Listener Notification methods.
*/
private void notify_discovery_stopped() {
executorService.execute(new Runnable() {
@Override
public void run() {
for (IBlaubotWifiDirectEventListener listener : eventListeners) {
listener.onDiscoveryStopped();
}
}
});
}
private void notify_discovery_started() {
executorService.execute(new Runnable() {
@Override
public void run() {
for (IBlaubotWifiDirectEventListener listener : eventListeners) {
listener.onDiscoveryStarted();
}
}
});
}
private void notify_connectivity_changed(final WifiP2pInfo p2pInfo, final NetworkInfo networkInfo, final WifiP2pGroup group) {
executorService.execute(new Runnable() {
@Override
public void run() {
for (IBlaubotWifiDirectEventListener listener : eventListeners) {
listener.onConnectivityChanged(p2pInfo, networkInfo, group);
}
}
});
}
protected void notify_list_of_peers_changed(final WifiP2pDeviceList peers) {
executorService.execute(new Runnable() {
@Override
public void run() {
for (IBlaubotWifiDirectEventListener listener : eventListeners) {
listener.onListOfPeersChanged(peers);
}
}
});
}
private void notify_p2p_disabled() {
executorService.execute(new Runnable() {
@Override
public void run() {
for (IBlaubotWifiDirectEventListener listener : eventListeners) {
listener.onP2PWifiDisabled();
}
}
});
}
private void notify_p2p_enabled() {
executorService.execute(new Runnable() {
@Override
public void run() {
for (IBlaubotWifiDirectEventListener listener : eventListeners) {
listener.onP2PWifiEnabled();
}
}
});
}
}