您好,登錄后才能下訂單哦!
6.0設置源碼分析:https://blog.csdn.net/zrf1335348191/article/details/51469058?locationNum=8
?
1.?源碼位置:/packages/apps/Settings/
2.?Settings.java即是應用的首頁
3.?|----SettingsActivity.java? ?(和Settings.java就在一個包下,不要全局搜索,否則會搜到多個SettingsActivity這個類)
4.??Android6.0源碼分析:
? ? ? ?1-1:清單文件分析
? ? ? ?通過清單文件可以知道設置應用的啟動類是Settings.java
? ? ? ??? ? ? ?
? ? ? ? ?看看清單文件里,可以發現很多的activity都有這樣的meta標簽定義,這些activity都是Settings.java的內部類,UI都是通過Fragment來實現的。
? ? ? ??
???????? 1-2:Settings.java分析
? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? 繼承自SettingsActivity,其它的都是一些內部類,雖然是空實現,但是都繼承了SettingsActivity.
????????????? ?說實話,這么詭異的寫法我生平還是第一次見!
?????
????????????????
? ? ? ? ?1-3:SettingsActivity分析
?????????第一步:看onCreate方法
? ? ? ? ?
? ? ? ? ?首先調用了一個getMetaData的方法
?????private?void?getMetaData()?{
????try?{
????????ActivityInfo?ai?=?getPackageManager().getActivityInfo(getComponentName(),
????????????????PackageManager.GET_META_DATA);
????????if?(ai?==?null?||?ai.metaData?==?null)?return;
????????mFragmentClass?=?ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
????}?catch?(NameNotFoundException?nnfe)?{
????????//?No?recovery
????????Log.d(LOG_TAG,?"Cannot?get?Metadata?for:?"?+?getComponentName().toString());
????}
}
? ? ? ??PackageManager從清單文件里解析當前Activity的信息,并且從META_DATA獲取到了對應的Fragment的類名。
???private?static?final?String?META_DATA_KEY_FRAGMENT_CLASS?=212????????"com.android.settings.FRAGMENT_CLASS";
????????這個正與清單文件里的meta的key一樣。
? ? ? ??
????1-4:Usb網絡共享界面
?????????https://blog.csdn.net/kc58236582/article/details/48313315
????????
????????項目有個需要,需要判斷一下USB網絡共享開關是否打開 。但是百度幾乎是沒有答案的,我就想著研究一下源碼,看看設置里的那個頁面是怎么去刷新這個UI的。
?
? ? ? ??
? ? ? ? ?
????????找到網絡共享設置頁面:TetherSettings.java
?????? ?TetherSettings
????????????????|-----SettingsPreferenceFragment
? ? ???????????????? |---------InstrumentedPreferenceFragment
????????????????????????????|--------PreferenceFragment
????????
????? ? 布局是在PreferenceFragment這個類里實現的,默認使用布局
<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
????????android:orientation="vertical"
????????android:layout_height="match_parent"
????????android:layout_width="match_parent"
????????android:background="@android:color/transparent"
????????android:layout_removeBorders="true">
????
????????<ListView?android:id="@android:id/list"
????????????
????????????android:layout_width="match_parent"
????????????android:layout_height="0px"
????????????android:layout_weight="1"
????????????android:paddingTop="0dip"
????????????android:paddingBottom="@dimen/preference_fragment_padding_bottom"
????????????android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
????????????android:clipToPadding="false"
????????????android:drawSelectorOnTop="false"
????????????android:cacheColorHint="@android:color/transparent"
????????????android:scrollbarAlwaysDrawVerticalTrack="true"?/>
????
????????<TextView?android:id="@android:id/empty"
????????????android:layout_width="match_parent"
????????????android:layout_height="match_parent"
????????????android:padding="@dimen/preference_fragment_padding_side"
????????????android:gravity="center"
????????????android:visibility="gone"?/>
????
????????<RelativeLayout?android:id="@+id/button_bar"
????????????android:layout_height="wrap_content"
????????????android:layout_width="match_parent"
????????????android:layout_weight="0"
????????????android:visibility="gone">
????
????????????<Button?android:id="@+id/back_button"
????????????????android:layout_width="0dip"
????????????????android:layout_height="wrap_content"
????????????????android:layout_margin="5dip"
????????????????android:layout_alignParentStart="true"
????????????????android:text="@string/back_button_label"
????????????/>
????????????<LinearLayout
????????????????android:orientation="horizontal"
????????????????android:layout_width="wrap_content"
????????????????android:layout_height="wrap_content"
????????????????android:layout_alignParentEnd="true">
????
????????????????<Button?android:id="@+id/skip_button"
????????????????????android:layout_width="0dip"
????????????????????android:layout_height="wrap_content"
????????????????????android:layout_margin="5dip"
????????????????????android:text="@string/skip_button_label"
????????????????????android:visibility="gone"
????????????????/>
????
????????????????<Button?android:id="@+id/next_button"
????????????????????android:layout_width="0dip"
????????????????????android:layout_height="wrap_content"
????????????????????android:layout_margin="5dip"
????????????????????android:text="@string/next_button_label"
????????????????/>
????????????</LinearLayout>
????????</RelativeLayout>
????</LinearLayout>
????????這些設置里的按鈕,是如何更新UI的呢?
????????
? ? ? ??
? ? ? ?可以看到USB網絡共享的開關是通過mUsbTether這個對象來控制的。至此,USB網絡共享是否開啟的代碼也就找到了。
?
? ? ??
????????findPreference是父類PreferenceFragment的方法:
? ? ?
????方法引用了PreferenceManager對象,對象在fragment創建時創建:
? ? ??
? ? ????? 通過代碼可以判斷刷新布局的應該這個方法:
????????
????????? 將preferenceScreen這個對象與前面提到的布局里的ListView綁定起來。
???????? 這個preferenceScreen對象通過下面的方法賦值:
? ? ? ? ?
????????????那么,問題來了,這兩個方法什么在哪里被調用的呢?
? ? ? ? ? ?
? ? ? ? ?
?????? ? ?
? ? ? ? 文件內容如下:
<PreferenceScreen?xmlns:android="http://schemas.android.com/apk/res/android">
????
????????<SwitchPreference
????????????android:key="usb_tether_settings"
????????????android:title="@string/usb_tethering_button_text"
????????????android:persistent="false"?/>
????
????????<SwitchPreference
????????????android:key="enable_wifi_ap"
????????????android:title="@string/wifi_tether_checkbox_text"
????????????android:persistent="false"?/>
????
????????<Preference
????????????android:key="wifi_ap_ssid_and_security"
????????????android:title="@string/wifi_tether_configure_ap_text"
????????????android:persistent="false"?/>
????
????????<SwitchPreference
????????????android:key="enable_bluetooth_tethering"
????????????android:title="@string/bluetooth_tether_checkbox_text"
????????????android:persistent="false"?/>
????
????</PreferenceScreen>
???到這里就清楚了,settings里的這些開關,并不是單獨使用switchButtont等控制堆疊起來的,而是通過解析res/xml下的xml文件,將標簽解析(采用XmlPullParser)出現,轉化成PreferenceScreen對象,
???再將PreferenceBean對象與布局里的ListView綁定起來。
? ? ? ?
當然,設置里的源碼粘貼過來,不能直接使用,很多字段和方法是hide的,需要通過反射來搞定。下面是我測試過的判斷usb網絡共享是否開啟的源碼:
package?com.refactor.usb_share;
import?android.content.BroadcastReceiver;
import?android.content.Context;
import?android.content.Intent;
import?android.content.IntentFilter;
import?android.hardware.usb.UsbManager;
import?android.net.ConnectivityManager;
import?android.util.Log;
import?java.lang.reflect.InvocationTargetException;
import?java.lang.reflect.Method;
import?java.util.ArrayList;
/**
?*?Created?by?XinYi?on?8/8/10.
?*?監聽USB網絡共享是否開啟
?*/
public?class?UsbShareStateMonitor?{
????private?Context?context;
????private?final?String?TAG?=?"UsbShareStateMonitor";
????private?static?UsbShareStateMonitor?instance?=?new?UsbShareStateMonitor();
????private?ConnectivityManager?cm;
????private?String[]?forReflect?=?new?String[]{};
????private?boolean?mMassStorageActive;
????private?boolean?mUsbConnected;
????private?String?ACTION_TETHER_STATE_CHANGED?=?"android.net.conn.TETHER_STATE_CHANGED";
????/**
?????*?@hide?gives?a?String[]?listing?all?the?interfaces?configured?for
?????*?tethering?and?currently?available?for?tethering.
?????*/
????private?final?String?EXTRA_AVAILABLE_TETHER?=?"availableArray";
????/**
?????*?@hide?gives?a?String[]?listing?all?the?interfaces?currently?tethered
?????*?(ie,?has?dhcp?support?and?packets?potentially?forwarded/NATed)
?????*/
????private?final?String?EXTRA_ACTIVE_TETHER?=?"activeArray";
????/**
?????*?@hide?gives?a?String[]?listing?all?the?interfaces?we?tried?to?tether?and
?????*?failed.??Use?{@link?#getLastTetherError}?to?find?the?error?code
?????*?for?any?interfaces?listed?here.
?????*/
????private?final?String?EXTRA_ERRORED_TETHER?=?"erroredArray";
????/**
?????*?Broadcast?Action:??External?media?is?no?longer?being?shared?via?USB?mass?storage.
?????*?The?path?to?the?mount?point?for?the?previously?shared?media?is?contained?in?the?Intent.mData?field.
?????*
?????*?@hide
?????*/
????private?final?String?ACTION_MEDIA_UNSHARED?=?"android.intent.action.MEDIA_UNSHARED";
????private?final?String?ACTION_USB_STATE?=
????????????"android.hardware.usb.action.USB_STATE";
????private?final?String?USB_CONNECTED?=?"connected";
????private?final?int?TETHER_ERROR_NO_ERROR?=?0;
????private?String[]?mUsbRegexs;
????private?boolean?isUsbShareOpened;
????private?TetherChangeReceiver?mTetherChangeReceiver;
????private?UsbShareStateMonitor()?{
????????isUsbShareOpened?=?false;
????}
????public?static?UsbShareStateMonitor?getInstance()?{
????????return?instance;
????}
????public?void?regist(Context?context)?{
????????this.context?=?context;
????????cm?=?(ConnectivityManager)?context.getSystemService(Context.CONNECTIVITY_SERVICE);
????????mUsbRegexs?=?getTetherableUsbRegexs();
????????registTetherChangeReceiver();
????}
????public?void?unRegist(){
????????if(context?!=?null){
????????????context.unregisterReceiver(mTetherChangeReceiver);
????????????mTetherChangeReceiver?=?null;
????????}
????}
????private?void?registTetherChangeReceiver()?{
????????mTetherChangeReceiver?=?new?TetherChangeReceiver();
????????IntentFilter?filter?=?new?IntentFilter(ACTION_TETHER_STATE_CHANGED);
????????Intent?intent?=?context.registerReceiver(mTetherChangeReceiver,?filter);
????????filter?=?new?IntentFilter();
????????filter.addAction(ACTION_USB_STATE);
????????context.registerReceiver(mTetherChangeReceiver,?filter);
????????filter?=?new?IntentFilter();
????????filter.addAction(Intent.ACTION_MEDIA_SHARED);
????????filter.addAction(ACTION_MEDIA_UNSHARED);
????????filter.addDataScheme("file");
????????context.registerReceiver(mTetherChangeReceiver,?filter);
????????if?(intent?!=?null)?mTetherChangeReceiver.onReceive(context,?intent);
????}
????public?boolean?isUsbShareOpened()?{
????????return?isUsbShareOpened;
????}
????private?class?TetherChangeReceiver?extends?BroadcastReceiver?{
????????@Override
????????public?void?onReceive(Context?content,?Intent?intent)?{
????????????String?action?=?intent.getAction();
????????????if?(action.equals(ACTION_TETHER_STATE_CHANGED))?{
????????????????//?TODO?-?this?should?understand?the?interface?types
????????????????ArrayList<String>?available?=?intent.getStringArrayListExtra(
????????????????????????EXTRA_AVAILABLE_TETHER);
????????????????ArrayList<String>?active?=?intent.getStringArrayListExtra(
????????????????????????EXTRA_ACTIVE_TETHER);
????????????????ArrayList<String>?errored?=?intent.getStringArrayListExtra(
????????????????????????EXTRA_ERRORED_TETHER);
????????????????updateState(available.toArray(new?String[available.size()]),
????????????????????????active.toArray(new?String[active.size()]),
????????????????????????errored.toArray(new?String[errored.size()]));
????????????}?else?if?(action.equals(Intent.ACTION_MEDIA_SHARED))?{
????????????????mMassStorageActive?=?true;
????????????????updateState();
????????????}?else?if?(action.equals(ACTION_MEDIA_UNSHARED))?{
????????????????mMassStorageActive?=?false;
????????????????updateState();
????????????}?else?if?(action.equals(ACTION_USB_STATE))?{
????????????????mUsbConnected?=?intent.getBooleanExtra(USB_CONNECTED,?false);
????????????????updateState();
????????????}
????????}
????}
????private?void?updateState()?{
????????String[]?available?=?getTetherableIfaces();
????????String[]?tethered?=?getTetheredIfaces();
????????String[]?errored?=?getTetheringErroredIfaces();
????????updateState(available,?tethered,?errored);
????}
????private?void?updateState(String[]?available,?String[]?tethered,
?????????????????????????????String[]?errored)?{
????????updateUsbState(available,?tethered,?errored);
????}
????private?void?updateUsbState(String[]?available,?String[]?tethered,
????????????????????????????????String[]?errored)?{
????????mUsbRegexs?=?getTetherableUsbRegexs();
????????if(mUsbRegexs?==?null)?{
????????????Log.e(TAG,?"mUsbRegexs?==?null?");
????????????return;
????????}
????????boolean?usbTethered?=?false;
????????for?(String?s?:?tethered)?{
????????????for?(String?regex?:?mUsbRegexs)?{
????????????????if?(s.matches(regex))?usbTethered?=?true;
????????????}
????????}
????????isUsbShareOpened?=?usbTethered;
????}
????//hide方法
????private?String[]?getTetherableUsbRegexs()?{
????????return?getCmHideMethods("getTetherableUsbRegexs");
????}
????private?String[]?getTetherableIfaces()?{
????????return?getCmHideMethods("getTetherableIfaces");
????}
????private?String[]?getTetheredIfaces()?{
????????return?getCmHideMethods("getTetheredIfaces");
????}
????private?String[]?getTetheringErroredIfaces()?{
????????return?getCmHideMethods("getTetheringErroredIfaces");
????}
????private?String[]?getCmHideMethods(String?methodName)?{
????????try?{
????????????Method?method?=?cm.getClass().getDeclaredMethod(methodName);
????????????method.setAccessible(true);
????????????String[]?result?=?(String[])?method.invoke(cm);
????????????return?result;
????????}?catch?(NoSuchMethodException?e)?{
????????????e.printStackTrace();
????????}?catch?(IllegalAccessException?e)?{
????????????e.printStackTrace();
????????}?catch?(InvocationTargetException?e)?{
????????????e.printStackTrace();
????????}
????????return?null;
????}
}
如何獲取藍牙物理MAC? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
#################################################################################################
https://blog.csdn.net/kehyuanyu/article/details/49074847? (有關于獲取藍牙物理的影子,順著果真能找到存儲藍牙物理 mac的文件)
1)
2)
? ??
3)
4)
5)
#################################################################################################
設備信息-本機信息:
順著路徑找到這個類,找到藍牙獲取的方法。
獲取藍牙mac的調用順序:
BluetoothAdapter-->BluetoothManagerService
很明顯上面用到AIDL技術
搜索消息關鍵字? ?MESSAGE_BLUETOOTH_SERVICE_CONNECTED ,找到消息發送的地方
上面的就是Binder機制了 ,注意注意的代碼。(由后面的分析可知arg1應該是AdapterService)
然后根據
找到bind的地方:
第1處:enable藍牙的地方,注意intent的參數是IBluetooth
第2處:注意intent的參數是IBluetoothGatt
還有一處無關的doBind調用。
注意到這里的intent的構造參數,是IBluetoothGatt。
看doBind方法
注意解析intent組件的這個方法,最后應該是與GattService或者AdapterService進行了綁定。
那么到底是哪個service呢,后面發現AdapterService才有getAddress()方法,所以綁定的應該是AdapterService。
所以獲取藍牙物理mac的調用順序又清楚了一步
BluetoothAdapter-->BluetoothManagerService-->AdapterService
看AdapterService,通過它的AdapterServiceBinder與BluetoothManagerService通訊
Binder會調用AdapterService的getAddress()方法
?
??
? 由上面的順序可知:
? 在AdapterService里創建了AdapterProperties,創建JniCallbacks,JniCallbacks封裝了AdapterProperties。
?
注意JniCallbacks這個類,它是與底層cpp交互的橋梁,包括它的adapterPropertyChangedCallback方法。
注意上面的寫法,怎么通過jni調用的JniCallbacks這個類的。
static?void?adapter_properties_callback(bt_status_t?status,?int?num_properties, ????????????????????????????????????bt_property_t?*properties)?{ ???????... ???? ????????callbackEnv->CallVoidMethod(sJniCallbacksObj,?method_adapterPropertyChangedCallback,?types, ????????????????????????????????????????????props); ????????checkAndClearExceptionFromCallback(callbackEnv,?__FUNCTION__); ????????callbackEnv->DeleteLocalRef(props); ????????callbackEnv->DeleteLocalRef(types); ????????return; ???? ????}
查詢adapter_properties_callback方法的調用? (注意CPP的回調是通過傳入方法名進行回調的)
最終是由HAL層回調過來的
xref: /hardware/libhardware/hardware.c,分析這個類。
獲取module:
https://blog.csdn.net/u014135607/article/details/79840130? (參考資料)
https://blog.csdn.net/u011913612/article/details/52576831?(超級詳細)
?調用HMI
?注意dlopen和dlsym這2個方法
? ? 上面這個dlsym方法屬于“<dlfcn.h>”這個接口,看它的實現類:
? ?注意這個類在bionic包下
? ?
??
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。