標籤:
最近GOOGLE發布時間Android4.4,我看了看原始碼。4.4藍芽開啟過程或這部分的一些變化,判斷藍芽開關是從介面設定settings在裡面switch開關,widget當然,它可以切換,也許啟動不同的過程是相同的。第一眼systemServer.java該代碼。。真機情況下我們關心的是最後一個else分支。
if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
Slog.i(TAG, "No Bluetooh Service (emulator)");
} else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
Slog.i(TAG, "No Bluetooth Service (factory test)");
} else if (!context.getPackageManager().hasSystemFeature
(PackageManager.FEATURE_BLUETOOTH)) {
Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
} else if (disableBluetooth) {
Slog.i(TAG, "Bluetooth Service disabled by config");
} else {
Slog.i(TAG, "Bluetooth Manager Service");
bluetooth = new BluetoothManagerService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
}
看下bluetoothManagerService的構造方法,我們看三個地方。 loadStoredNameAndAddress()是讀取藍芽開啟預設名稱的地方。isBluetoothPersistedStateOn()是推斷是否已開啟藍芽的,假設已開啟。興許操作要運行開啟藍芽的動作
BluetoothManagerService(Context context) {
mHandler = new BluetoothHandler(IoThread.get().getLooper());
mContext = context;
mBluetooth = null;
mQBluetooth = null;
mBinding = false;
mUnbinding = false;
mEnable = false;
mState = BluetoothAdapter.STATE_OFF;
mQuietEnableExternal = false;
mEnableExternal = false;
mAddress = null;
mName = null;
mErrorRecoveryRetryCounter = 0;
mContentResolver = context.getContentResolver();
mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
mQCallbacks = new RemoteCallbackList<IQBluetoothManagerCallback>();
mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
mContext.registerReceiver(mReceiver, filter);
loadStoredNameAndAddress();
if (isBluetoothPersistedStateOn()) {
mEnableExternal = true;
}
}
另外的registerForAirplaneMode方法,例如以下
private void registerForAirplaneMode(IntentFilter filter) {
final ContentResolver resolver = mContext.getContentResolver();
final String airplaneModeRadios = Settings.Global.getString(resolver,
Settings.Global.AIRPLANE_MODE_RADIOS);
final String toggleableRadios = Settings.Global.getString(resolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
boolean mIsAirplaneSensitive = airplaneModeRadios == null ? true :
airplaneModeRadios.contains(Settings.Global.RADIO_BLUETOOTH);
if (mIsAirplaneSensitive) {
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
}
}
當中
Settings.Global.getString(resolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS)
擷取到的值是在String檔案裡定義的,如:
<!-- Comma-separated list of bluetooth, wifi, and cell. -->
<string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc,wimax</string>
表示假設開啟飛航模式下,哪些服務將會被關閉。所以registerForAirplaneMode方法就是在假設藍芽也受飛航模式影響。那麼飛航模式的變化也將使藍芽服務收到對應廣播。
介面上開關就是BluetoothEnabler.java這個類了,而setBluetoothEnabled()則是詳細開關動作。當中有開關的回呼函數,代碼例如以下:
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// Show toast message if Bluetooth is not allowed in airplane mode
if (isChecked
&& (WifiSettings.needPrompt(mContext) || !WirelessSettings.isRadioAllowed(
mContext, Settings.Global.RADIO_BLUETOOTH))) {
Toast.makeText(mContext, R.string.wifi_in_airplane_mode,
Toast.LENGTH_SHORT).show();
// Reset switch to off
buttonView.setChecked(false);
}
// shouldn‘t setBluetoothEnabled(true) in airplane mode.
if (mLocalAdapter != null) {
if (isChecked && WifiSettings.needPrompt(mContext)) {
return;
}
mLocalAdapter.setBluetoothEnabled(isChecked);
}
mSwitch.setEnabled(false);
}
著作權聲明:本文部落格原創文章。部落格,未經同意,不得轉載。
Android4.4 藍芽原始碼段分析