/*
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.physical_web.physicalweb;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
/**
* This class is for using WifiDirect to discover Physical Web
* Devices through peer discovery.
*/
class WifiUrlDeviceDiscoverer extends UrlDeviceDiscoverer {
private static final String TAG = WifiUrlDeviceDiscoverer.class.getSimpleName();
private Context mContext;
private WifiP2pManager mManager;
private Channel mChannel;
private IntentFilter mIntentFilter = new IntentFilter();
private boolean mIsRunning = false;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)
&& mManager != null) {
mManager.requestPeers(mChannel, mPeerListener);
}
}
};
private final PeerListListener mPeerListener = new PeerListListener() {
@Override
public void onPeersAvailable(WifiP2pDeviceList list) {
Log.d(TAG, list.toString());
for (WifiP2pDevice device : list.getDeviceList()) {
Utils.WifiDirectInfo info = Utils.parseWifiDirectName(device.deviceName);
if (info != null) {
String name = info.title;
int port = info.port;
reportUrlDevice(createUrlDeviceBuilder("WifiDirect" + name,
device.deviceAddress + ":" + port)
.setWifiAddress(device.deviceAddress)
.setWifiPort(port)
.setTitle(name)
.setDescription("")
.setDeviceType(Utils.WIFI_DIRECT_DEVICE_TYPE)
.build());
}
}
}
};
public WifiUrlDeviceDiscoverer(Context context) {
mContext = context;
}
@Override
public synchronized void startScanImpl() {
mManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(mContext, mContext.getMainLooper(), null);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
mContext.registerReceiver(mReceiver, intentFilter);
mIsRunning = true;
discoverHelper(true);
}
private void discoverHelper(boolean retry) {
mManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(int reasonCode) {
if (retry && reasonCode == WifiP2pManager.BUSY) {
mManager.cancelConnect(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG, "cancel connect call success");
if (mIsRunning) {
discoverHelper(false);
}
}
@Override
public void onFailure(int reason) {
Log.d(TAG, "cancel connect call fail " + reason);
}
});
}
}
});
}
@Override
public synchronized void stopScanImpl() {
mIsRunning = false;
mContext.unregisterReceiver(mReceiver);
mManager.stopPeerDiscovery(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG, "stop discovering");
}
@Override
public void onFailure(int reasonCode) {
Log.d(TAG, "stop discovery failed " + reasonCode);
}
});
}
}