/*
* 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 org.physical_web.collection.UrlDevice;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pGroup;
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.widget.Toast;
/**
* This class is for using WifiDirect to create a WifiDirect
* P2P connection with the Physical Web Device.
*/
class WifiDirectConnect {
private static final String TAG = WifiDirectConnect.class.getSimpleName();
private ProgressDialog mProgress;
private Context mContext;
private WifiP2pManager mManager;
private Channel mChannel;
private UrlDevice mDevice;
private BroadcastReceiver mReceiver;
private ConnectionListener mCallback;
public WifiDirectConnect(Context context) {
mManager = (WifiP2pManager) context.getSystemService(Context.WIFI_P2P_SERVICE);
mChannel = mManager.initialize(context, context.getMainLooper(), null);
mContext = context;
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
if (mManager == null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
if (networkInfo.isConnected()) {
mManager.requestConnectionInfo(mChannel,
new WifiP2pManager.ConnectionInfoListener() {
@Override
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
if (mDevice != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http:/" + info.groupOwnerAddress + ":" +
Integer.toString(Utils.getWifiPort(mDevice))));
mContext.startActivity(intent);
close();
}
}
});
}
}
}
};
}
public void connect(UrlDevice urlDevice, String title) {
String progressTitle = mContext.getString(R.string.page_loading_title) + " " + title;
mProgress = new ProgressDialog(mContext);
mProgress.setCancelable(true);
mProgress.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
Log.i(TAG, "Dialog box canceled");
mDevice = null;
mManager.cancelConnect(mChannel, new ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG, "cancel connect call success");
}
@Override
public void onFailure(int reason) {
Log.d(TAG, "cancel connect call fail " + reason);
}
});
}
});
mProgress.setTitle(progressTitle);
mProgress.setMessage(mContext.getString(R.string.page_loading_message));
mProgress.show();
mDevice = urlDevice;
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = Utils.getWifiAddress(mDevice);
config.groupOwnerIntent = 0;
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
mContext.registerReceiver(mReceiver, intentFilter);
mManager.requestGroupInfo(mChannel, new WifiP2pManager.GroupInfoListener() {
public void onGroupInfoAvailable(final WifiP2pGroup group) {
if (group != null) {
Log.d(TAG, "group not null");
if (group.getOwner().deviceAddress.equals(Utils.getWifiAddress(mDevice))) {
Log.i(TAG, "Already connected");
mManager.requestConnectionInfo(mChannel,
new WifiP2pManager.ConnectionInfoListener() {
public void onConnectionInfoAvailable(final WifiP2pInfo info) {
if (mDevice != null && info.groupOwnerAddress != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http:/" + info.groupOwnerAddress + ":" +
Integer.toString(Utils.getWifiPort(mDevice))));
mContext.startActivity(intent);
}
}
}
);
} else {
mManager.removeGroup(mChannel, new ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG, "remove call success");
connectHelper(true, config);
}
@Override
public void onFailure(int reason) {
Log.d(TAG, "remove call fail " + reason);
}
});
}
} else {
Log.d(TAG, "group null");
connectHelper(true, config);
}
}
});
}
public void connect(UrlDevice urlDevice, String title, ConnectionListener callback) {
mCallback = callback;
connect(urlDevice, title);
}
private void connectHelper(boolean retry, WifiP2pConfig config) {
mManager.connect(mChannel, config, new ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG, "connect call success");
Toast.makeText(mContext, R.string.wifi_direct_connection_succeeded, Toast.LENGTH_SHORT)
.show();
}
@Override
public void onFailure(int reason) {
Log.d(TAG, "connect call fail " + reason);
if (retry && reason == WifiP2pManager.BUSY) {
mManager.cancelConnect(mChannel, new ActionListener() {
@Override
public void onSuccess() {
Log.d(TAG, "cancel connect call success");
connectHelper(false, config);
}
@Override
public void onFailure(int reason) {
Log.d(TAG, "cancel connect call fail " + reason);
Toast.makeText(mContext, R.string.wifi_direct_connection_failed, Toast.LENGTH_SHORT)
.show();
close();
}
});
} else {
Toast.makeText(mContext, R.string.wifi_direct_connection_failed, Toast.LENGTH_SHORT)
.show();
close();
}
}
});
}
private void close() {
mProgress.dismiss();
if (mCallback != null) {
mCallback.onConnectionFinished();
}
}
}