1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.wifidirect; 18 19 import android.app.Activity; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.net.wifi.p2p.WifiP2pConfig; 25 import android.net.wifi.p2p.WifiP2pDevice; 26 import android.net.wifi.p2p.WifiP2pManager; 27 import android.net.wifi.p2p.WifiP2pManager.ActionListener; 28 import android.net.wifi.p2p.WifiP2pManager.Channel; 29 import android.net.wifi.p2p.WifiP2pManager.ChannelListener; 30 import android.os.Bundle; 31 import android.provider.Settings; 32 import android.util.Log; 33 import android.view.Menu; 34 import android.view.MenuInflater; 35 import android.view.MenuItem; 36 import android.view.View; 37 import android.widget.Toast; 38 39 import com.example.android.wifidirect.DeviceListFragment.DeviceActionListener; 40 41 /** 42 * An activity that uses WiFi Direct APIs to discover and connect with available 43 * devices. WiFi Direct APIs are asynchronous and rely on callback mechanism 44 * using interfaces to notify the application of operation success or failure. 45 * The application should also register a BroadcastReceiver for notification of 46 * WiFi state related events. 47 */ 48 public class WiFiDirectActivity extends Activity implements ChannelListener, DeviceActionListener { 49 50 public static final String TAG = "wifidirectdemo"; 51 private WifiP2pManager manager; 52 private boolean isWifiP2pEnabled = false; 53 private boolean retryChannel = false; 54 55 private final IntentFilter intentFilter = new IntentFilter(); 56 private Channel channel; 57 private BroadcastReceiver receiver = null; 58 59 /** 60 * @param isWifiP2pEnabled the isWifiP2pEnabled to set 61 */ 62 public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) { 63 this.isWifiP2pEnabled = isWifiP2pEnabled; 64 } 65 66 @Override 67 public void onCreate(Bundle savedInstanceState) { 68 super.onCreate(savedInstanceState); 69 setContentView(R.layout.main); 70 71 // add necessary intent values to be matched. 72 73 intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 74 intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 75 intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 76 intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 77 78 manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); 79 channel = manager.initialize(this, getMainLooper(), null); 80 } 81 82 /** register the BroadcastReceiver with the intent values to be matched */ 83 @Override 84 public void onResume() { 85 super.onResume(); 86 receiver = new WiFiDirectBroadcastReceiver(manager, channel, this); 87 registerReceiver(receiver, intentFilter); 88 } 89 90 @Override 91 public void onPause() { 92 super.onPause(); 93 unregisterReceiver(receiver); 94 } 95 96 /** 97 * Remove all peers and clear all fields. This is called on 98 * BroadcastReceiver receiving a state change event. 99 */ 100 public void resetData() { 101 DeviceListFragment fragmentList = (DeviceListFragment) getFragmentManager() 102 .findFragmentById(R.id.frag_list); 103 DeviceDetailFragment fragmentDetails = (DeviceDetailFragment) getFragmentManager() 104 .findFragmentById(R.id.frag_detail); 105 if (fragmentList != null) { 106 fragmentList.clearPeers(); 107 } 108 if (fragmentDetails != null) { 109 fragmentDetails.resetViews(); 110 } 111 } 112 113 @Override 114 public boolean onCreateOptionsMenu(Menu menu) { 115 MenuInflater inflater = getMenuInflater(); 116 inflater.inflate(R.menu.action_items, menu); 117 return true; 118 } 119 120 /* 121 * (non-Javadoc) 122 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem) 123 */ 124 @Override 125 public boolean onOptionsItemSelected(MenuItem item) { 126 switch (item.getItemId()) { 127 case R.id.atn_direct_enable: 128 if (manager != null && channel != null) { 129 130 // Since this is the system wireless settings activity, it's 131 // not going to send us a result. We will be notified by 132 // WiFiDeviceBroadcastReceiver instead. 133 134 startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS)); 135 } else { 136 Log.e(TAG, "channel or manager is null"); 137 } 138 return true; 139 140 case R.id.atn_direct_discover: 141 if (!isWifiP2pEnabled) { 142 Toast.makeText(WiFiDirectActivity.this, R.string.p2p_off_warning, 143 Toast.LENGTH_SHORT).show(); 144 return true; 145 } 146 final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager() 147 .findFragmentById(R.id.frag_list); 148 fragment.onInitiateDiscovery(); 149 manager.discoverPeers(channel, new WifiP2pManager.ActionListener() { 150 151 @Override 152 public void onSuccess() { 153 Toast.makeText(WiFiDirectActivity.this, "Discovery Initiated", 154 Toast.LENGTH_SHORT).show(); 155 } 156 157 @Override 158 public void onFailure(int reasonCode) { 159 Toast.makeText(WiFiDirectActivity.this, "Discovery Failed : " + reasonCode, 160 Toast.LENGTH_SHORT).show(); 161 } 162 }); 163 return true; 164 default: 165 return super.onOptionsItemSelected(item); 166 } 167 } 168 169 @Override 170 public void showDetails(WifiP2pDevice device) { 171 DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager() 172 .findFragmentById(R.id.frag_detail); 173 fragment.showDetails(device); 174 175 } 176 177 @Override 178 public void connect(WifiP2pConfig config) { 179 manager.connect(channel, config, new ActionListener() { 180 181 @Override 182 public void onSuccess() { 183 // WiFiDirectBroadcastReceiver will notify us. Ignore for now. 184 } 185 186 @Override 187 public void onFailure(int reason) { 188 Toast.makeText(WiFiDirectActivity.this, "Connect failed. Retry.", 189 Toast.LENGTH_SHORT).show(); 190 } 191 }); 192 } 193 194 @Override 195 public void disconnect() { 196 final DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager() 197 .findFragmentById(R.id.frag_detail); 198 fragment.resetViews(); 199 manager.removeGroup(channel, new ActionListener() { 200 201 @Override 202 public void onFailure(int reasonCode) { 203 Log.d(TAG, "Disconnect failed. Reason :" + reasonCode); 204 205 } 206 207 @Override 208 public void onSuccess() { 209 fragment.getView().setVisibility(View.GONE); 210 } 211 212 }); 213 } 214 215 @Override 216 public void onChannelDisconnected() { 217 // we will try once more 218 if (manager != null && !retryChannel) { 219 Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show(); 220 resetData(); 221 retryChannel = true; 222 manager.initialize(this, getMainLooper(), this); 223 } else { 224 Toast.makeText(this, 225 "Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.", 226 Toast.LENGTH_LONG).show(); 227 } 228 } 229 230 @Override 231 public void cancelDisconnect() { 232 233 /* 234 * A cancel abort request by user. Disconnect i.e. removeGroup if 235 * already connected. Else, request WifiP2pManager to abort the ongoing 236 * request 237 */ 238 if (manager != null) { 239 final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager() 240 .findFragmentById(R.id.frag_list); 241 if (fragment.getDevice() == null 242 || fragment.getDevice().status == WifiP2pDevice.CONNECTED) { 243 disconnect(); 244 } else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE 245 || fragment.getDevice().status == WifiP2pDevice.INVITED) { 246 247 manager.cancelConnect(channel, new ActionListener() { 248 249 @Override 250 public void onSuccess() { 251 Toast.makeText(WiFiDirectActivity.this, "Aborting connection", 252 Toast.LENGTH_SHORT).show(); 253 } 254 255 @Override 256 public void onFailure(int reasonCode) { 257 Toast.makeText(WiFiDirectActivity.this, 258 "Connect abort request failed. Reason Code: " + reasonCode, 259 Toast.LENGTH_SHORT).show(); 260 } 261 }); 262 } 263 } 264 265 } 266 } 267