版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android源碼個(gè)個(gè)擊破之“設(shè)置”
6.0設(shè)置源碼分析:/zrf1335348191/article/details/51469058?locationNum=8
1.
源碼位置:/packages/apps/Settings/2.
Settings.java即是應(yīng)用的首頁(yè)3.
|SettingsActivity.java
(和Settings.java就在一個(gè)包下,不要全局搜索,否則會(huì)搜到多個(gè)SettingsActivity這個(gè)類)4.
Android6.0源碼分析:
1-1:清單文件分析
通過(guò)清單文件可以知道設(shè)置應(yīng)用的啟動(dòng)類是Settings.java
看看清單文件里,可以發(fā)現(xiàn)很多的activity都有這樣的meta標(biāo)簽定義,這些activity都是Settings.java的內(nèi)部類,UI都是通過(guò)Fragment來(lái)實(shí)現(xiàn)的。
1-2:Settings.java分析
繼承自SettingsActivity,其它的都是一些內(nèi)部類,雖然是空實(shí)現(xiàn),但是都繼承了SettingsActivity.
說(shuō)實(shí)話,這么詭異的寫(xiě)法我生平還是第一次見(jiàn)!
1-3:SettingsActivity分析
第一步:看onCreate方法
首先調(diào)用了一個(gè)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從清單文件里解析當(dāng)前Activity的信息,并且從META_DATA獲取到了對(duì)應(yīng)的Fragment的類名。
private
static
final
String
META_DATA_KEY_FRAGMENT_CLASS
=212
"com.android.settings.FRAGMENT_CLASS";
這個(gè)正與清單文件里的meta的key一樣。
1-4:Usb網(wǎng)絡(luò)共享界面
/kc58236582/article/details/48313315
項(xiàng)目有個(gè)需要,需要判斷一下USB網(wǎng)絡(luò)共享開(kāi)關(guān)是否打開(kāi)。但是百度幾乎是沒(méi)有答案的,我就想著研究一下源碼,看看設(shè)置里的那個(gè)頁(yè)面是怎么去刷新這個(gè)UI的。
找到網(wǎng)絡(luò)共享設(shè)置頁(yè)面:TetherSettings.java
TetherSettings
|SettingsPreferenceFragment
|InstrumentedPreferenceFragment
|PreferenceFragment
布局是在PreferenceFragment這個(gè)類里實(shí)現(xiàn)的,默認(rèn)使用布局<LinearLayout
xmlns:android="/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>
這些設(shè)置里的按鈕,是如何更新UI的呢?
可以看到USB網(wǎng)絡(luò)共享的開(kāi)關(guān)是通過(guò)mUsbTether這個(gè)對(duì)象來(lái)控制的。至此,USB網(wǎng)絡(luò)共享是否開(kāi)啟的代碼也就找到了。
findPreference是父類PreferenceFragment的方法:
方法引用了PreferenceManager對(duì)象,對(duì)象在fragment創(chuàng)建時(shí)創(chuàng)建:
通過(guò)代碼可以判斷刷新布局的應(yīng)該這個(gè)方法:
將preferenceScreen這個(gè)對(duì)象與前面提到的布局里的ListView綁定起來(lái)。
這個(gè)preferenceScreen對(duì)象通過(guò)下面的方法賦值:
那么,問(wèn)題來(lái)了,這兩個(gè)方法什么在哪里被調(diào)用的呢?
文件內(nèi)容如下:<PreferenceScreen
xmlns:android="/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里的這些開(kāi)關(guān),并不是單獨(dú)使用switchButtont等控制堆疊起來(lái)的,而是通過(guò)解析res/xml下的xml文件,將標(biāo)簽解析(采用XmlPullParser)出現(xiàn),轉(zhuǎn)化成PreferenceScreen對(duì)象,
再將PreferenceBean對(duì)象與布局里的ListView綁定起來(lái)。
當(dāng)然,設(shè)置里的源碼粘貼過(guò)來(lái),不能直接使用,很多字段和方法是hide的,需要通過(guò)反射來(lái)搞定。下面是我測(cè)試過(guò)的判斷usb網(wǎng)絡(luò)共享是否開(kāi)啟的源碼: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
.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.
*
監(jiān)聽(tīng)USB網(wǎng)絡(luò)共享是否開(kāi)啟
*/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
=
".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
=
"ent.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;
}}如何獲取藍(lán)牙物理MAC
#################################################################################################/kehyuanyu/article/details/49074847
(有關(guān)于獲取藍(lán)牙物理的影子,順著果真能找到存儲(chǔ)藍(lán)牙物理mac的文件)1)2)
3)4)5)#################################################################################################設(shè)備信息-本機(jī)信息:順著路徑找到這個(gè)類,找到藍(lán)牙獲取的方法。獲取藍(lán)牙m(xù)ac的調(diào)用順序:BluetoothAdapter-->BluetoothManagerService很明顯上面用到AIDL技術(shù)搜索消息關(guān)鍵字
MESSAGE_BLUETOOTH_SERVICE_CONNECTED,找到消息發(fā)送的地方上面的就是Binder機(jī)制了,注意注意的代碼。(由后面的分析可知arg1應(yīng)該是Ad
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026上半年云南事業(yè)單位聯(lián)考文山州招聘143人考試備考題庫(kù)及答案解析
- 2026鄱陽(yáng)湖湖泊濕地綜合研究站實(shí)驗(yàn)支撐崗位招聘1人考試參考題庫(kù)及答案解析
- 2026年中核五〇四醫(yī)院?甘肅(蘭州)國(guó)際陸港中心醫(yī)院招聘司機(jī)筆試參考題庫(kù)及答案解析
- 2026年度黃山市歙縣事業(yè)單位統(tǒng)一公開(kāi)招聘工作人員51名筆試參考題庫(kù)及答案解析
- 2026重慶龍璟紙業(yè)有限公司招聘1人筆試備考試題及答案解析
- 浙商銀行嘉興分行2026年一季度社會(huì)招聘考試備考題庫(kù)及答案解析
- 2026銅陵分行社會(huì)招聘筆試參考題庫(kù)及答案解析
- 2026年1月黑龍江大慶市肇州縣招聘公益性崗位人員35人筆試備考試題及答案解析
- 2026年房地產(chǎn)行業(yè)中的網(wǎng)絡(luò)營(yíng)銷效益評(píng)估
- 2026年地震后的建筑評(píng)估與修復(fù)
- 2024-2025學(xué)年上學(xué)期深圳高一物理期末模擬卷1
- 胸痛中心聯(lián)合例會(huì)培訓(xùn)
- 臥式橢圓封頭儲(chǔ)罐液位體積對(duì)照表
- 國(guó)家職業(yè)技術(shù)技能標(biāo)準(zhǔn) 4-10-01-02 育嬰員 人社廳發(fā)201947號(hào)
- 天鵝到家合同模板
- 全球鈷礦資源儲(chǔ)量、供給及應(yīng)用
- 中考字音字形練習(xí)題(含答案)-字音字形專項(xiàng)訓(xùn)練
- 消防安全責(zé)任人任命書(shū)
- MOOC 數(shù)據(jù)挖掘-國(guó)防科技大學(xué) 中國(guó)大學(xué)慕課答案
- 2024屆新高考物理沖刺復(fù)習(xí):“正則動(dòng)量”解決帶電粒子在磁場(chǎng)中的運(yùn)動(dòng)問(wèn)題
- 中學(xué)體育與健康課程與教學(xué)論P(yáng)PT高職完整全套教學(xué)課件
評(píng)論
0/150
提交評(píng)論