Settings>Wireless Settings>WiFi Setting>WiFi Enable 에 대해서 분석을 해보았습니다.
Settings App 에서보면, WiFi Enable 버튼이 보일 것입니다.
이 버튼에 대한 소스를 보면 어떤식으로 Wifi가 Enable이 되는지 Disable이 되는지에 대해서 궁굼할 것입니다.
Source를 보면 다음과 같습니다.
위의 소스를 보면 WifiEnablerprivate final BroadcastReceiver mReceiver = new BroadcastReceiver() { 란 생성자를 확인할 수 있습니다.
이 생성자를 통해서 Wifi Enable CheckBoxPreference가 Check가 되는지 안되는지를 처리를 해줍니다.
그러면 WifiEnabler란 생성자를 소스로 보면 CheckBoxPreference를 전달 받아서 이를 이용해 Wifi의 상태값에 의해서 Enable인지 Disable인지를 그려주는 것을 확인할 수 있습니다.
그런데 여기서 의문점이 하나 생기게됩니다.
어떻게 CheckBoxPreference에 Create해 주었을때, 바로 Wifi의 Enable을 설정해주는지에 대해서 의문을 가지게 될것입니다.
소스상으로 보게되면 다음과 같이 receiver로 WiFi상태 값을 받아서 Check해주는 법 외에는 처리를 하지 않을 것입니다.
private void registerForBroadcasts() {소스상에서 보여지는 것과 같이 Receiver로 받아서 처리해주는 방법외에는 없습니다. 그러면 여기서 또다른 의문이 생길것입니다. 도대체 어디서 Wifi의 상태값을 Broadcast로 보내주는 것일까....
그리고 Wifi Settings에 진입할 때 마다 정확하게 팍!팍! 보내주는 것일까...
그래서 이 부분에 대해서 소스를 분석한 결과 그 답은 WifiService에서 확인할 수 있었습니다.
WifiService.java의 위치는 다음과 같습니다.
frameworks/base/services/java/com/android/server/WifiService.java
sendEnableMessage 함수를 따라가다 보면, setWifiEnabledBlocking 이란 함수를 호출하게 되며, 결국은 setWifiEnabledState 함수를 호출하게 됩니다.
Settings App 에서보면, WiFi Enable 버튼이 보일 것입니다.
이 버튼에 대한 소스를 보면 어떤식으로 Wifi가 Enable이 되는지 Disable이 되는지에 대해서 궁굼할 것입니다.
Source를 보면 다음과 같습니다.
WiFiSettings.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (getIntent().getBooleanExtra("only_access_points", false)) {
addPreferencesFromResource(R.xml.wifi_access_points);
} else {
addPreferencesFromResource(R.xml.wifi_settings);
mWifiEnabler = new WifiEnabler(this,
(CheckBoxPreference) findPreference("enable_wifi"));
mNotifyOpenNetworks =
(CheckBoxPreference) findPreference("notify_open_networks");
mNotifyOpenNetworks.setChecked(Secure.getInt(getContentResolver(),
Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
}
mAccessPoints = (ProgressCategory) findPreference("access_points");
mAccessPoints.setOrderingAsAdded(false);
mAddNetwork = findPreference("add_network");
registerForContextMenu(getListView());
} |
위의 소스를 보면 WifiEnablerprivate final BroadcastReceiver mReceiver = new BroadcastReceiver() { 란 생성자를 확인할 수 있습니다.
이 생성자를 통해서 Wifi Enable CheckBoxPreference가 Check가 되는지 안되는지를 처리를 해줍니다.
그러면 WifiEnabler란 생성자를 소스로 보면 CheckBoxPreference를 전달 받아서 이를 이용해 Wifi의 상태값에 의해서 Enable인지 Disable인지를 그려주는 것을 확인할 수 있습니다.
그런데 여기서 의문점이 하나 생기게됩니다.
어떻게 CheckBoxPreference에 Create해 주었을때, 바로 Wifi의 Enable을 설정해주는지에 대해서 의문을 가지게 될것입니다.
소스상으로 보게되면 다음과 같이 receiver로 WiFi상태 값을 받아서 Check해주는 법 외에는 처리를 하지 않을 것입니다.
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
handleWifiStateChanged(intent.getIntExtra(
WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
} else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
handleStateChanged(WifiInfo.getDetailedStateOf((SupplicantState)
intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));
} else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
handleStateChanged(((NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO)).getDetailedState());
}
}
};
그리고 Wifi Settings에 진입할 때 마다 정확하게 팍!팍! 보내주는 것일까...
그래서 이 부분에 대해서 소스를 분석한 결과 그 답은 WifiService에서 확인할 수 있었습니다.
WifiService.java의 위치는 다음과 같습니다.
frameworks/base/services/java/com/android/server/WifiService.java
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(ACTION_DEVICE_IDLE);
intentFilter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
mContext.registerReceiver(mReceiver, intentFilter);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
...
updateWifiState();
}
위의 소스를 보면 ACTION_BATTERY_CHANGED 를 받아서 updateWifiState()함수를 호출 하는 것을 확인 할 수 있습니다.
여기서 updateWifiState() 함수를 따라가다보면 doUpdateWifiState 함수까지 따라 갈 수 있습니다. 이 함수를 보면, sendEnableMessage 함수를 호출하게 됩니다.
위의 소스를 보면 ACTION_BATTERY_CHANGED 를 받아서 updateWifiState()함수를 호출 하는 것을 확인 할 수 있습니다.
여기서 updateWifiState() 함수를 따라가다보면 doUpdateWifiState 함수까지 따라 갈 수 있습니다. 이 함수를 보면, sendEnableMessage 함수를 호출하게 됩니다.
private void doUpdateWifiState() {
...
if (wifiShouldBeEnabled) {
if (wifiShouldBeStarted) {
sWakeLock.acquire();
sendEnableMessage(true, false, mLastEnableUid);
sWakeLock.acquire();
sendStartMessage(strongestLockMode);
...
}
private void setWifiEnabledState(int wifiState, int uid) {
final int previousWifiState = mWifiStateTracker.getWifiState();
long ident = Binder.clearCallingIdentity();
try {
if (wifiState == WIFI_STATE_ENABLED) {
mBatteryStats.noteWifiOn();
} else if (wifiState == WIFI_STATE_DISABLED) {
mBatteryStats.noteWifiOff();
}
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(ident);
}
// Update state
mWifiStateTracker.setWifiState(wifiState);
// Broadcast
final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
mContext.sendStickyBroadcast(intent);
}
결국은 setWifiEnabledState란 함수를 통해서 WiFi의 상태 변화 값을 전달하게 됩니다.
위의 내용을 정리하자면, ACTION_BATTERY_CHANGED란 BroadCast를 통해서 Wifi의 상태값을 Broadcast로 전달하게 되며, Settings App에서는 Wifi의 상태값을 전달 받아서 CheckBoxPreference의 Check값을 설정하게 되는 것입니다.
ACTION_BATTERY_CHANGED란 Intent는 주기적으로 호출이 되기는 하지만, Activity가 생성되거나, Rotation될때, 그리고 기타적인 요인에 의해서 호출되게 됩니다.
Battery Changed가 호출되는 시점에 대해서는 다음에 설명하도록 하겠습니다.
결국은 setWifiEnabledState란 함수를 통해서 WiFi의 상태 변화 값을 전달하게 됩니다.
위의 내용을 정리하자면, ACTION_BATTERY_CHANGED란 BroadCast를 통해서 Wifi의 상태값을 Broadcast로 전달하게 되며, Settings App에서는 Wifi의 상태값을 전달 받아서 CheckBoxPreference의 Check값을 설정하게 되는 것입니다.
ACTION_BATTERY_CHANGED란 Intent는 주기적으로 호출이 되기는 하지만, Activity가 생성되거나, Rotation될때, 그리고 기타적인 요인에 의해서 호출되게 됩니다.
Battery Changed가 호출되는 시점에 대해서는 다음에 설명하도록 하겠습니다.
'안드로이드' 카테고리의 다른 글
fullScreenIntent (0) | 2011.07.22 |
---|---|
MountService의 기본과 UMS 연결 과정 (0) | 2011.07.22 |
Ring, Notification, Alarm etc. 저장 위치 (0) | 2011.07.14 |
The content of the adapter has changed but ListView did not receive a notification. (0) | 2011.07.12 |
안드로이드 안전모드 진입 (0) | 2011.07.12 |