android夯實總結(設計、細節及思想)
判斷App位於前臺或者後臺的6種方法-- http://mp.weixin.qq.com/s/HGLBRw7VcTxzCzw0aZbJzA
1)Android App的生命週期是什麼;
>前臺 後臺 關閉 啟用 未啟用的狀態等2)四大元件很熟悉了吧,ContentProvider的生命週期是什麼;
>ContentProvider通過工具ContentResolver啟用,使用者自行管理cursor的生命週期.
3)Android裝置開機的啟動過程; http://blog.jobbole.com/67931/
》Boot ROM ->Boot Loader ->Kernel ->init ->Daemon Zygote Runtime Dalvik Vm ->System Servers Service Manager Managers
>>當電源按下,引導晶片程式碼開始從預定義的地方(固化在ROM)開始執行。載入載入程式到RAM,然後執行。 >>載入程式是在Android作業系統開始執行前的一個小程式。載入程式是執行的第一個程式,因此它是針對特定的主機板與晶片的。裝置製造商要麼使用很受歡迎的載入程式比如redboot、uboot、qi bootloader或者開發自己的載入程式,它不是Android作業系統的一部分。載入程式是OEM廠商或者運營商加鎖和限制的地方。>>Android核心與桌面linux核心啟動的方式差不多。核心啟動時,設定快取、被保護儲存器、計劃列表,載入驅動。當核心完成系統設定,它首先在系統檔案中尋找”init”檔案,然後啟動root程式或者系統的第一個程式。>>init是第一個程式,我們可以說它是root程式或者說有程式的父程式。init程式有兩個責任,一是掛載目錄,比如/sys、/dev、/proc,二是執行init.rc指令碼。>>Zygote讓Dalvik虛擬機器共享程式碼、低記憶體佔用以及最小的啟動時間成為可能。Zygote是一個虛擬器程式,正如我們在前一個步驟所說的在系統引導的時候啟動。Zygote預載入以及初始化核心庫類。通常,這些核心類一般是隻讀的,也是Android SDK或者核心框架的一部分。在Java虛擬機器中,每一個例項都有它自己的核心庫類檔案和堆物件的拷貝。>>Zygote建立新的程式去啟動系統服務。系統服務或服務.>>一旦系統服務在記憶體中跑起來了,Android就完成了引導過程。在這個時候“ACTION_BOOT_COMPLETED”開機啟動廣播就會發出去。
第一部分:Bootloader啟動
一、Bootloader的定義和種類
二、Arm特定平臺的Bootloader
三、U-boot啟動流程分析
第二部分:Linux啟動
一、zImage是怎樣煉成的?
二、linux的c啟動階段
第三部分:Android啟動
一、init程式
二、init啟動的各種服務
三、android啟動圖示
4)Activity的檢視層次是什麼?開啟一個對話方塊的時候,這個對話方塊是如何加入到檢視上去的?
>每一個Activity元件的UI內容和佈局都是通過與其所關聯的一個Window物件的內部的一個View物件來實現的。
getWindow().getDecorView()就是根檢視了,當然用Activity.getWindow.getDecorView()
Activity的對話方塊管理機制。
5)Dialog、PopupWindow、WindowManager載入檢視的區別;
>如PhoneStatusBar,ActivityThread,PhoneWindow,PopupWindow,Activity,Toast,Dialog 等等。那這裡感覺就比較明顯了,這些熟悉的控制元件和類,就是通過windowmanager ,來把自己的view和介面加到系統中了。
應用層面的介面都是通過windowmanager 加入到framework 中的,ViewRootImpl 是framework對view 的抽象, 介面管理的根節點。
Window是一塊電子屏,PhoneWindow是一塊手機電子屏,DecorView就是電子屏要顯示的內容,Activity就是手機電子屏安裝位置。
6)Service與Thread的區別;
> Thread:Thread 是程式執行的最小單元,它是分配CPU的基本單位。可以用 Thread 來執行一些非同步的操作。
Service:Service 是android的一種機制,當它執行的時候如果是Local Service,那麼對應的 Service 是執行在主程式的 main 執行緒上的。如:onCreate,onStart 這些函式在被系統呼叫的時候都是在主程式的 main 執行緒上執行的。如果是Remote Service,那麼對應的 Service 則是執行在獨立程式的 main 執行緒上。
Thread 的執行是獨立於 Activity 的,也就是說當一個 Activity 被 finish 之後,如果你沒有主動停止 Thread 或者 Thread 裡的 run 方法沒有執行完畢的話,Thread 也會一直執行。因此這裡會出現一個問題:當 Activity 被 finish 之後,你不再持有該 Thread 的引用,也就是你下次啟動的時候,無法控制之前建立的執行緒,而service則可以。另一方面,你沒有辦法在不同的 Activity 中對同一 Thread 進行控制。你也可以在 Service 裡註冊 BroadcastReceiver,在其他地方通過傳送 broadcast 來控制它,這些是 Thread 做不到的。
根據程式優先順序,Thread在後臺執行(Activty stop)的優先順序低於後臺執行的Service,如果執行系統資源緊張,會優先殺死前一種,後臺執行的Service一般情況下不會被殺死,如果被殺死,系統空閒時會重新啟動service.
一.在應用中,如果是長時間的在後臺執行,而且不需要互動的情況下,使用服務。
同樣是在後臺執行,不需要互動的情況下,如果只是完成某個任務,之後就不需要執行,而且可能是多個任務,需需要長時間執行的情況下使用執行緒。
二.如果任務佔用CPU時間多,資源大的情況下,要使用執行緒。
7)ServiceManager、ActivityManager、XXXManager是幹什麼的?
》C/S框架及代理 框架IOC
8)為什麼一定要在UI執行緒更新檢視,為什麼要這麼設計;
>UI執行緒及Android的單執行緒模型原則當應用啟動,系統會建立一個主執行緒(main thread)。這個主執行緒負責向UI元件分發事件(包括繪製事件),也是在這個主執行緒裡,應用和Android的UI元件(components from the Android UI toolkit (components from the android.widget and android.view packages))發生互動。
google這樣設計的原因就在於讓UI執行緒做的事情更純粹一些,都是介面方面的事情,如果在ui執行緒執行耗時的操作,在做UI操作的時候會有卡頓的感覺。即從更新View的角度來說,最好是UI執行緒,非UI執行緒也不是不能更新UI。
Android的單執行緒模型有兩條原則:
1.不要阻塞UI執行緒。
2.不要在UI執行緒之外訪問Android UI toolkit(主要是這兩個包中的元件:android.widget and android.view)。
9)能不能直接New一個Activity並啟動它;打包APK的過程幹了什麼;
》singleTop,singleTask啟動模式會呼叫onNewIntent(Intent intent)
10)安裝APK的過程幹了什麼;
>Android應用安裝有如下四種方式
11)啟動APK的過程幹了什麼;
>Java程式的啟動比較特殊,Java程式是zygote啟動的,zygote在folk程式之後,並沒有執行execve指令,因此是共享了zygote的程式碼段和資料段。其它的java程式,可以看做都是zygote的克隆,克隆之後的程式,各自根再據自己的需求(java程式碼),解釋java語言。
12)怎麼玩DexLoader(動態升級);
>Android 外掛化 —— 指將一個程式劃分為不同的部分,比如一般 App 的皮膚樣式就可以看成一個外掛
Android 元件化 —— 這個概念實際跟上面相差不那麼明顯,元件和外掛較大的區別就是:元件是指通用及複用性較高的構件,比如圖片快取就可以看成一個元件被多個 App 共用
Android 動態載入 —— 這個實際是更高層次的概念,也有叫法是熱載入或 Android 動態部署,指容器(App)在運?狀態下動態載入某個模組,從而新增功能或改變某?部分行為
13)MVP模式是啥;
> MVC (Model-View-Controller):M是指邏輯模型,V是指檢視模型,C則是控制器。一個邏輯模型可以對於多種檢視模型,比如一批統計資料你可以分別用柱狀圖、餅圖來表示。一種檢視模型也可以對於多種邏輯模型。使用MVC的目的是將M和V的實現程式碼分離,從而使同一個程式可以使用不同的表現形式,而C存在的目的則是確保M和V的同步,一旦M改變,V應該同步更新,
1) 檢視層(View):一般採用XML檔案進行介面的描述,使用的時候可以非常方便的引入。當然,如何你對Android瞭解的比較的多了話,就一定可以想到在Android中也可以使用JavaScript+HTML等的方式作為View層,當然這裡需要進行Java和JavaScript之間的通訊,幸運的是,Android提供了它們之間非常方便的通訊實現。
2) 控制層(Controller):Android的控制層的重任通常落在了眾多的Acitvity的肩上,這句話也就暗含了不要在Acitivity中寫程式碼,要通過Activity交割Model業務邏輯層處理,這樣做的另外一個原因是Android中的Acitivity的響應時間是5s,如果耗時的操作放在這裡,程式就很容易被回收掉。
3) 模型層(Model):對資料庫的操作、對網路等的操作都應該在Model裡面處理,當然對業務計算等操作也是必須放在的該層的。就是應用程式中二進位制的資料。
14)View的生命週期是啥;
>android view有以下14個週期:
1、onFinishInflate() 當View中所有的子控制元件均被對映成xml後觸發 。
2、onMeasure( int , int ) 確定所有子元素的大小 。
3、onLayout( boolean , int , int , int , int ) 當View分配所有的子元素的大小和位置時觸發 。
4、onSizeChanged( int , int , int , int ) 當view的大小發生變化時觸發 。
5、onDraw(Canvas) view渲染內容的細節。
6、onKeyDown( int , KeyEvent) 有按鍵按下後觸發 。
7、onKeyUp( int , KeyEvent) 有按鍵按下後彈起時觸發 。
8、onTrackballEvent(MotionEvent) 軌跡球事件 。
9、onTouchEvent(MotionEvent) 觸屏事件 。
10、onFocusChanged( boolean , int , Rect) 當View獲取或失去焦點時觸發 。
11、onWindowFocusChanged( boolean ) 當視窗包含的view獲取或失去焦點時觸發 。
12、onAttachedToWindow() 當view被附著到一個視窗時觸發 。
13、onDetachedFromWindow() 當view離開附著的視窗時觸發,Android123提示該方法和 onAttachedToWindow() 是相反的。
14、onWindowVisibilityChanged( int ) 當視窗中包含的可見的view發生變化時觸發。
15)TWEEN動畫跟熟悉動畫在View的繪製過程是怎麼作用的;
> 檢視動畫注意事項:特別特別注意:補間動畫執行之後並未改變View的真實佈局屬性值。切記這一點,譬如我們在Activity中有一個Button在螢幕上方,我們設定了平移動畫移動到螢幕下方然後保持動畫最後執行狀態呆在螢幕下方,這時如果點選螢幕下方動畫執行之後的Button是沒有任何反應的,而點選原來螢幕上方沒有Button的地方卻響應的是點選Button的事件。
16)自定義動畫玩過嗎,裡面的Matrix怎麼控制。res裡面的XML資源最終都要轉化成JavaCode,怎麼完全脫離 res,用純程式碼的方式實現res資源的功能,怎麼縮放一張點九圖;
> Matrix類:Translate—平移變換;Scale—縮放變換;Rotate—旋轉變換;Skew————錯切變換
Matrix提供了一些方法來控制圖片變換:
setTranslate(float dx,float dy):控制Matrix進行位移。
setSkew(float kx,float ky):控制Matrix進行傾斜,kx、ky為X、Y方向上的比例。
setSkew(float kx,float ky,float px,float py):控制Matrix以px、py為軸心進行傾斜,kx、ky為X、Y方向上的傾斜比例。
setRotate(float degrees):控制Matrix進行depress角度的旋轉,軸心為(0,0)。
setRotate(float degrees,float px,float py):控制Matrix進行depress角度的旋轉,軸心為(px,py)。
setScale(float sx,float sy):設定Matrix進行縮放,sx、sy為X、Y方向上的縮放比例。
setScale(float sx,float sy,float px,float py):設定Matrix以(px,py)為軸心進行縮放,sx、sy為X、Y方向上的縮放比例。
17)Binder原理是什麼,除了Binder之外,還能怎麼跟Service互動;
> Binder是Android系統程式間通訊(IPC)方式之一。Linux已經擁有的程式間通訊IPC手段包括(Internet Process Connection): 管道(Pipe)、訊號(Signal)和跟蹤(Trace)、插口(Socket)、報文佇列(Message)、共享記憶體(Share Memory)和訊號量(Semaphore)
Binder使用Client-Server通訊方式.
Binder框架定義了四個角色:Server,Client,ServiceManager(以後簡稱SMgr)以及Binder驅動。其中Server,Client,SMgr執行於使用者空間,驅動執行於核心空間。這四個角色的關係和網際網路類似:Server是伺服器,Client是客戶終端,SMgr是域名伺服器(DNS),驅動是路由器。
Binder使用Client-Server通訊方式,接收快取管理和執行緒池管理方式.
> AIDL
18)Touch事件的分發機制;
> 傳遞——dispatchTouchEvent()函式、攔截——onInterceptTouchEvent()函式、消費——onTouchEvent()函式和OnTouchListener(事件分發與消費)
19)能不能用程式碼模擬一組TOUCH事件(比如自動點選廣告,自動滾動);TOUCH事件傳遞及分發
》final long downTime = SystemClock.uptimeMillis();
final MotionEvent downEvent = MotionEvent.obtain(
downTime, downTime, MotionEvent.ACTION_DOWN, x, y, 0);
final MotionEvent upEvent = MotionEvent.obtain(
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);
mSeekBar.onTouchEvent(downEvent);
mSeekBar.onTouchEvent(upEvent);
downEvent.recycle();
upEvent.recycle();
。重點是需要知道兩個點:一是你模擬點選的座標,在這裡就是x和y,二就是你需要設定響應這個點選事件的View,這裡是一個SeekBar,
20)ROOT的原理是什麼,系統是怎麼管理APP的許可權的;
》Android的核心就是Linux,在Linux下獲取root許可權的時候就是執行sudo或者su。
Linux下su以後輸入密碼就可以root了,但Android裡的su和Linux裡的su是不一樣的,Android裡的su不是靠驗證密碼的,而是看你原來的許可權是什麼。意思就是如果你是root,那你可以通過su切換到別的使用者,比如說shell,wifi,audio什麼的。
需要把一個所有者是root的su拷貝到Android手機上,並且把su的許可權標誌位置成-rwsr-xr-x。能把這個事情搞定你就成功root了一個手機。大概意思就是兩行程式碼cp /data/tmp/su /system/bin/ #copy su 到/system/分割槽chown root:root su #su的所有者置成rootchmod 4775 /system/bin/su #把su置成-rwsr-xr-x
。已經有root許可權的程式都是出廠時候就裝到手機上的,程式碼寫死了,你沒法控制它執行你自己的程式碼啊。這個時候就需要你找漏洞了,比如用來破解Android2.3 root許可權的zergRush漏洞就是利用一個擁有root許可權的程式棧溢位漏洞。
》iphone的越獄其實和Android的root是一回事兒,都是越權操作。所以越獄的方式也都差不多,也是找IOS自帶程式的漏洞,只不過IOS安全性強一點,所以也比較難找。如果你發現你的iphone的某個自帶程式經過一些特定操作會出現系統崩潰重啟的現象,並且是可以復現的,那就很有可能可以用來越獄了。
關於sudoandroid的工程裡沒有sudo這個東西。sudo是為了給普通使用者臨時分配root許可權的,Android裡建立了很多使用者,比如wifi,shell等等,這些使用者可以訪問那個檔案,不可以訪問那個檔案,程式碼裡已經寫死了,許可權也分配的很分明。它們在執行的過程中不需要臨時獲得root許可權。所以Android不需要sudo這個程式。Android系統裡面沒有su這個可執行的檔案,提權就是利用Android系統漏洞把su裝入系統。
其實就是linux系統裡面的su命令,切換root使用者,等於window系統的超級管理員。
安卓基於linux,su命令的效果一樣。
root就是在你的安卓系統裡面新增一個su二進位制檔案,當app需要使用root許可權時(一般都是涉及系統檔案),就通過執行su檔案獲取一個root的許可權。
而我們需要一個管理app獲取root許可權的管理軟體,這個就是平時用到的超級使用者等app。只有安裝了這個管理軟體之後,我們才可以限制app的root許可權,不然的話,如果系統本身不識別你安裝的su檔案,app就可以直接使用root許可權。
1,Root 是什麼?
2,Android 手機Root 的原理?
3,什麼是SuperUser ?
4,su.c 的作用?
5,setUid() 和setGid() 的左右?
su 原始碼 下載地址:http://download.csdn.net/detail/jinzhu117/4821630
SuperUser 原始碼下載地址:http://download.csdn.net/detail/jinzhu117/4821569
21)Material Desgin這麼好看,為什麼不出相容包,讓5.0以下的系統也能要動畫效果
>使用support library或者使用開源控制元件。google官方,以及一些大牛,給我們提供了一些程式,讓我們在低版本上面可以實現Material風格的程式,V4、V7、V13等。
22)ART模式與Dalvik有什麼不同;
》Dalvik 經過優化,允許在有限的記憶體中同時執行多個虛擬機器的例項,並且每一個Dalvik 應用作為一個獨立的Linux 程式執行。獨立的程式可以防止在虛擬機器崩潰的時候所有程式都被關閉。
》安卓4.4的升級顛覆了手機執行速度和執行方式,安卓4.2以前的系統使用的是傳統Dalvik模式,
測試了電量,分別對Nexus 5的兩種模式進行了續航測試,在4小時的中等強度測試下發現ART模式下要略比Dalvik模式省電一些,開啟省電%5到%8左右的。
ART模式與Dalvik究竟有什麼本質的不同?比如Dalvik模式像一臺摺疊自行車,每次騎之前都要組裝後才能上路,ART(Android runtime)模式就是一個已經裝好的自行車,直接就能騎走了。
所以說適配ART模式,是目前最新的一種系統體驗!也是安卓系統解決吃硬體的最好解決方法!
Android4.4採用ART取代Dalvik,簡單理解就是Android程式執行的根本機制改變了,程式會啟動地更快,而且會更省資源。表現在使用者體驗上,就是Android更流暢了,同時續航能力顯著增加。
ART模式與Dalvik模式最大的不同在於,在啟用ART模式後,系統在安裝應用的時候會進行一次預編譯,在安裝應用程式時會先將程式碼轉換為機器語言儲存在本地,這樣在執行程式時就不會每次都進行一次編譯了,執行效率也大大提升。
》ART模式和Dalvik模式,相比較而言ART模式就很好的解決了這個問題,通過在安裝應用程式時,自動對程式進行程式碼預讀取編譯,讓程式直接編譯成機器語言,免去了Dalvik模式要時時轉換程式碼,實現高效率、省電、佔用更低的系統記憶體、手機執行流暢。但凡事總有正反兩面,ART在解決了該問題的同時,同時也有如:會佔用略高一些的儲存空間、安裝程式時要相比普通Dalvik模式要長一些時間來實現預編譯
》Android作業系統已經成熟,Google的Android團隊開始將注意力轉向一些底層元件,其中之一是負責應用程式執行的Dalvik執行時。Google開發者已經花了兩年時間開發更快執行效率更高更省電的替代ART執行時。 ART代表Android Runtime,其處理應用程式執行的方式完全不同於Dalvik,Dalvik是依靠一個Just-In-Time (JIT)編譯器去解釋位元組碼。開發者編譯後的應用程式碼需要通過一個直譯器在使用者的裝置上執行,這一機制並不高效,但讓應用能更容易在不同硬體和架構上運 行。ART則完全改變了這套做法,在應用安裝時就預編譯位元組碼到機器語言,這一機制叫Ahead-Of-Time (AOT)編譯。在移除解釋程式碼這一過程後,應用程式執行將更有效率,啟動更快。
ART優點:
1、系統效能的顯著提升。
2、應用啟動更快、執行更快、體驗更流暢、觸感反饋更及時。
3、更長的電池續航能力。
4、支援更低的硬體。
ART缺點:
1、更大的儲存空間佔用,可能會增加10%-20%。
2、更長的應用安裝時間。
23)Render Thread是怎麼工作的;以及檢視繪製
》在硬體加速渲染環境中,Android應用程式視窗的UI渲染是分兩步進行的。第一步是構建Display List,發生在應用程式程式的Main Thread中;第二步是渲染Display List,發生在應用程式程式的Render Thread中。Display List的渲染不是簡單地執行繪製命令,而是包含了一系列優化操作,例如繪製命令的合併執行。
Android系統--檢視繪製主要由以下幾部分組成:
1) Canvas(畫布)
提供畫圖所需要的所有工具,即各種draw函式;當前可用的畫布物件有:具有硬體加速的GLES20Canvas和GLES20RecordingCanvas,不使用硬體加速的CompatibleCanvas)。
2) View(檢視)
在具體畫布物件上完成各種繪製圖形的操作,可根據需要選擇以上三種畫布中的一種。
3) Gl20Renderer(把圖直接繪製到螢幕上)
它是硬體加速檢視繪製的引擎,負責整個與硬體加速相關的檢視繪製過程,具體功能如下:
(1) 建立以下例項物件
? GLES20Canvas (Canvas)
? GLES20DisplayList (DisplayList)
? GLES20TextureLayer (HardwareLayer)
? GLES20RenderLayer (HardwareLayer)
? SurfaceTexture
? Gl20Renderer (HardwareRenderer)
(2) 在GlRenderer.draw中呼叫View.getDisplayList()完成DisplayList命令的錄製,並返回DisplayList
注:只有View被attach到硬體加速,才能建立DisplayList;
真正的命令錄製工作在View.getDisplayList(DisplayList displayList, boolean isLayer)中完成。
(3) 在GlRenderer.draw中呼叫GLES20Canvas.drawDisplayList,把DisplayList中錄製的命令回放在畫布上。
(4) Gl20Renderer物件對應的畫布為GLES20Canvas,Gl20Renderer物件在畫布上的繪製實際上是繪製在OPENGL繪製上下文對應的主緩衝區。
4) GLES20DisplayList(把錄製命令錄製到Native的DiplayList中)
GLES20DisplayList物件建立具體的DisplayList物件及繪製用的畫布(GLES20RecordingCanvas畫布),完成檢視繪製操作的DisplayList命令錄製等工作。
5) GLES20RenderLayer(繪製到FOB Layer中,當作紋理)
負責建立硬體Layer層(GLES20Canvas.nCreateLayer)和繪製用到的畫布(GLES20Canvas,使用Layer例項化GLES20Canvas(layer, trans))等工作。
為了有效支援檢視的多層繪製,檢視物件可以建立一個HardwareLayer層完成檢視的圖形在硬體紋理上的繪製操作或者其它特效操作,這就是GLES20RenderLayer物件的作用,建立獨立的層並返回相應的畫布供檢視繪製使用。
1.1 View.draw(Canvas canvas)六步曲
此函式將把View自身及其所有的子子孫孫繪製到給定的畫布上。其畫圖過程主要分為以下六步:
1) 畫背景
2) 如果需要,儲存畫布的層為未來的淡入淡出做好準備
3) 畫View本身的內容
4) 畫它的孩子
5) 如果需要,畫淡入淡出的邊緣並恢復層
6) 畫裝飾部分(如:滾動條)
24)不把功能都用H5實現然後把需求都扔給前段的人去做;
》用h5開發出的web app體驗上並不比原生app差太多,但其跨平臺的特性大大減低了開發成本,而且可以快速迭代。
25)ServiceManager、ActivityManager、packageManager 、*****Manager 都弄懂了?
>在Android系統中用到最多的通訊機制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驅動程式組成。其中Client、Service和ServiceManager執行在使用者空間,而Binder驅動程式執行在核心空間。核心元件就是Binder驅動程式了,而ServiceManager提供輔助管理的功能,無論是Client還是Service進行通訊前首先要和ServiceManager取得聯絡。而ServiceManager是一個守護程式,負責管理Server並向Client提供查詢Server的功能。
>Service Manager存在的意義
1.Service Manager能集中管理系統內的所有服務,它能被施加許可權控制,並不是任何程式都能註冊服務的。
2.Service Manager支援通過字串名稱來查詢對應的Service。
3.由於各種原因的影響,Server程式可能生死無常。如果有了Service Manager做統一的管理,那麼Client只要向Service Manager做查詢,就能得到Server的最新資訊。
>Service Manager程式的主要工作如下:
1.初始化binder,開啟/dev/binder裝置;在記憶體中為binder對映128K位元組空間;
2.指定SM對應的代理binder的handle為0,當client嘗試與SM通訊時,需要建立一個handle為0的代理binder,這裡的代理binder其實就是第一節中描述的那個代理介面;
3.通知binder driver(BD)使SM成為BD的context manager;
4.維護一個死迴圈,在這個死迴圈中,不停地去讀核心中binder driver,檢視是否有可讀的內容;即是否有對service的操作要求, 如果有,則呼叫svcmgr_handler回撥來處理請求的操作。
5.SM維護了一個svclist列表來儲存service的資訊。
26)Binder 也搞清楚了?
>Android系統程式間通訊機制Binder的總體架構由Client、Server、ServiceManager和驅動程式Binder四個元件構成.
>binder通訊是一種client-server的通訊結構,
1.從表面上來看,是client通過獲得一個server的代理介面,對server進行直接呼叫;
2.實際上,代理介面中定義的方法與server中定義的方法是一一對應的;
3.client呼叫某個代理介面中的方法時,代理介面的方法會將client傳遞的引數打包成為Parcel物件;
4.代理介面將該Parcel傳送給核心中的binder driver.
5.server會讀取binder driver中的請求資料,如果是傳送給自己的,解包Parcel物件,處理並將結果返回;
6.整個的呼叫過程是一個同步過程,在server處理的時候,client會block住。
27)IPC 也弄明白了?
> 第一種方式就是Intent,Intent可以非常方便的通訊,但是它是非實時的,無法進行實時的像函式呼叫那樣的實時的通訊。
但是IPC的根本目的還是為了實現函式的呼叫,即使是傳遞資料也是要通過函式呼叫的方式,為什麼呢?因為程式執行總是要知道狀態,要有邏輯上的行為,因此必須通訊函式才能體現出行為
IPC的機制除了程式,或者說不同的應用程式之間進行通訊,同時也能夠讓不同的元件之間進行像普通物件那樣進行實時的呼叫。因為Android的元件都是由系統框架統一的進行構建和銷燬,所以你就無法建立物件,因此,就沒有辦法像普通的物件那樣進行組合或者聚合,從而也就沒有辦法進行直接呼叫。但是IPC的方式就可以讓Activity/Service獲取另外一個Service物件的引用,從而直接呼叫其上的方法。
還有,就是這些IPC方法總是產生客戶/服務端模式的呼叫,也即是客戶端元件(Activity/Service)持有服務端Service的元件,只能是客戶端主動呼叫服務端的方法,服務端無法反過來呼叫客戶端的方法,因為IPC的另一端Service無法獲取客戶端的物件。
>有三種方式可以進行IPC通訊:
1. 直接使用Binder物件,
缺點是這種方式不能進行跨程式,跨應用程式的函式呼叫。只能實現在同一個程式之中,同一個應用程式之中的不同的元件之間通訊。優點就是這種方式使用起來特別簡單,對於公開出來的方法沒有任何的限制,可以傳遞任何的物件,甚至是回撥等等。總體上來講如果不需要跨程式,這是最好的實現方式,可以完全實現像普通物件之間的組合和聚合。但是這裡,最好不要像Android文件中的示例那樣,直接返回Service物件,因為Service物件會有很多Public的方法,如果直接返回【Service】物件會導致公開很多不必須的方法,一旦Client端呼叫這些方法,將導致奇怪的現象和Bug,一個方法就是用Proxy對Service物件進行封裝,只公開需要的介面。
2. 使用Messenger物件,
這是利用了訊息迴圈佇列來進行通訊的,也就是說服務端封裝成了一個Handler,客戶端向這個Handler傳送Message,服務端再處理這個Message從而實現通訊。優點,最突出的優點就是它可以保證執行緒上的安全,或者說時序上的安全。因為客戶端是向Handler傳送訊息,而不是直接的函式呼叫,所以呢?Message都是按先後的順序放到服務端的訊息佇列當中,然後再由服務端Service決定如何處理這些Message。因為直接的函式呼叫會導致被呼叫的函式也會出現在呼叫者的執行緒之中,也就是說被呼叫到的函式也會繼續存在於呼叫者的呼叫棧中,因此有可能產生執行緒的問題。而Messenger方式,並不是直接的函式呼叫,而是僅向Service的Handler傳送一個Message,然後呼叫者就此返回,其呼叫棧也就此停止,Service可以選擇如何處理這一個Message。Messenger方式即可以在同一個程式之中,也可以跨程式實現真正的IPC。但是它的缺點也是相當的明顯的,就是它是傳送一個Message物件,而不是直接的函式呼叫,所以非常的不直觀,另外,Message物件也無法方便的攜帶過多的引數,如果超過一個物件,只能封裝打包成一個物件然後再放到Message.obj中。需要注意的是,如果是在同一個程式之中,Message可以攜帶任何物件,但如果是跨程式,則Message.obj中存放的必須是實現了Parcelable介面的物件,否則無法實現IPC,會有Exception。還有一個缺點,就是Message物件的標識(Message.what)必須是Client端和Service端都定義一致,否則就無法通訊,這在除錯的時候必須注意,因為這不會有編譯或者執行時錯誤,但就是無法正常工作,是比較隱蔽的Bug。
3. 使用AIDL程式通訊
這是最正統的IPC方式,實際上Messenger的跨程式通訊的底層也是通過AIDL來實現的。它的優點就是完全是為跨程式而設計的,介面由AIDL檔案指定,Client端和Service端都通過AIDL所描述的介面來進行呼叫和實現,不容易出錯。需要注意的是介面中的所有的物件都必須實現了Parcelable介面,即使僅僅是在同一個程式之中。它的缺點就是必須要在每一個想要通訊的地方定義一個完全一樣的AIDL檔案,否則IPC不會成功,而且它是嚴格的按照IPC的機制來的,所以即使是在同一程式之內,所有的介面的引數和返回值的物件必須是實現了Parcelable介面的,但Binder物件和Messenger就無此限制。需要一點:定義AIDL會嚴格按照IPC的方式程式即使是在同一個程式之中。所以,除非是真的要跨程式通訊,否則不要使用AIDL。
28)FrameWork 層的每個類都折騰了?
> 在寫android程式碼時,我們基本不會出現new MyActivity(), new MyService()等等這樣的程式碼,要知道android app的編寫語言是java,java的特點是什麼:“一切皆物件”。那麼問題來了,我們寫的activity,service等什麼時候被new出來了的呢,它們是怎樣被new出來的,帶著這個問題我們繼續看下去。
android framework層架構採用了ioc方式,程式設計師實現的activity,service等式在android的框架層new出來的,程式猿在完成一個activity後都需要在mainfest註冊。然後android framework層利用反射的方式動態的建立其物件。所以android採用這樣的方式將控制權全部掌握在框架層,客戶端程式設計師只需要按照其方式實現就行。
但是緊接著新的問題又會出現,既然我們客戶端程式設計師不需要new 元件物件,也就是說我們的各個元件間是相互獨立的。然後新的問題產生各元件之間的互動該如何處理呢,android framework為我們想到了這個問題,所以Intent信使產生了,android設計者通過Intent信使實現各個元件間的互動,不得不說框架的設計確實很好,這裡膜拜大神。
android的框架層牢牢掌控住客戶端的,包括物件的建立呼叫等。其中運用的很多好的設計模式以及方法值得我們學習。
關於framework,更多是做的應用層之下的系統層面的東西。比如電源管理、訊息佇列、包管理等等,還包括對硬體的支援及系統提供給上層的硬體功能呼叫介面。framework的學習必然離不開不斷編譯rom和刷機。這就要求有耐心有時間有興趣。而且由於framework層多數模組都是以JNI方式被呼叫的,因此你需要有比較紮實的C語言基礎,之少能看懂程式結構。除此之外,對你想要詳細研讀的模組在應用層的應用需要有必要的理解。我剛開始看原始碼的時候是從電源管理模組開始看的,就是因為當時對android系統自帶的電源提醒方式以及電量通知不太滿意,想重新定義更多層級的提醒。剛開始也是一頭霧水,但還是硬著頭皮一點點啃。這個過程中,為了防止忘記之前看過什麼,所以又不斷對看過的原始碼做註釋並做閱讀筆記。大概兩三個月,雖然瞭解的也比較淺顯,但是我的目的達到了。原始碼之路漫漫,看個三五年都不一定敢說能夠整體吃透。雖如此,但只要有鑽研的方向和基本的能力,相信工作中遇到的framework層的改動應當還是能夠負擔得住的。
29)Hook 會玩了?
>如果要攔截惡意軟體對電話、簡訊等API的呼叫,在Java或者Dalvik層面是不好進行的,因為這些層面都沒有提供Hook的手段,而在Native層面,我認為可行的方案是對電話、簡訊的執行庫so進行Hook(比如系統執行庫\system\lib\libreference-ril.so或\system\lib\libril.so),如果注入自己的so到上述程式後,並通過dlopen()和dlsym()獲取原有API地址,替換原有API地址為自己so中的API地址就可以達到Hook的目的。Hook的前提是程式注入,而Linux下最便捷的程式注入手段——ptrace.一種方案:程式碼主要功能是注入子程式的地址空間,Hook住子程式執行系統呼叫時的引數,並反轉其引數,從而逆序輸出ls命令的結果。
Intel官網上下載了Intel處理器開發手冊《64-ia-32-architectures-software-developer-vol-1-manual.pdf》方才解答我的問題,定址方式涉及兩個暫存器,DS和RSI,參考手冊的說法,DS表示資料段的selector,其實這個selector就是index索引的意思,由於x64下字長64bit,即8個位元組,索引乘以8即得資料段在記憶體中的基址,RSI表示資料段內偏移地址,與基址相加即可得出資料的絕對地址,使用此地址直接訪問記憶體就可以取出資料。
30)各種 SystemService 也知道怎麼執行的了?
31)View 的渲染你明白是怎麼回事了?
》父View與子View
》》訊息佇列有如下幾個好處,這大都是由其系統解耦和訊息快取兩點擴充套件而來的:
提升系統可靠性:
冗餘:Process_B崩潰之後,資料並不會丟失,因為MQ多采用put-get-delete模式,即,僅當確認message被完成處理之後,才從MQ中移除message;
可恢復:MQ實現解耦,部分程式崩潰,不會拖累整個系統癱瘓,例,Process_B崩潰之後,Process_A仍可向MQ中新增message,並等待Process_B恢復;
可伸縮:有較強的峰值處理能力,通常應用會有突發的訪問流量上升情況,使用足夠的硬體資源時刻待命,空閒時刻較長,資源浪費,而訊息佇列卻能夠平滑峰值流量,緩解系統元件的峰值壓力;
提升系統可擴充套件性:
調整模組:由於實現解耦,可以很容易調整,訊息入隊速率、訊息處理速率、增加新的Process;
其他:
單次送達:保證MQ中一個message被處理一次,並且只被處理一次。本質:get獲取一個message後,這一message即被預定,同一程式不會再次獲取這一message;當且僅當程式處理完這一message後,MQ中會delete這個message。否則,過一段時間後,這一message自動解除被預訂狀態,程式能夠重新預定這個message;
排序保證:即,滿足佇列的FIFO,先入先出策略;
非同步通訊:很多場景下,不會立即處理訊息,這是,可以在MQ中儲存message,並在某一時刻再進行處理;
資料流的階段效能定位:獲取使用者某一操作的各個階段(通過message來標識),捕獲不同階段的耗時,可用於定位系統瓶頸。
32)Intent 是如何實現 Activity、Service等之間的解耦合的?
》Intent與Android元件之間的關係
33)單元測試會寫了?
》Eclipse與Android Studio的環境配置。
34)Monkey 能跑多長時間?
35)效能測試通過了?
36)ClassLoader 和 DexLoader 會玩了?
40)Android翻頁效果原理實現之引來折線??
37)Context 是個啥你也知道了?
>Context字面意思上下文,或者叫做場景,也就是使用者與作業系統操作的一個過程,比如你打電話,場景包括電話程式對應的介面,以及隱藏在背後的資料.Activity、Service、Application都是Context的子類;Android系統的角度來理解:Context是一個場景,代表與作業系統的互動的一種過程。從程式的角度上來理解:Context是個抽象類,而Activity、Service、Application等都是該類的一個實現。在其內部引用了一個Activity作為Context,也就是說,我們的這個Activity只要我們的專案活著,就沒有辦法進行記憶體回收。而我們的Activity的生命週期肯定沒這麼長,所以造成了記憶體洩漏。
>因此應用程式App共有的Context數目公式為:
總Context例項個數 = Service個數 + Activity個數 + 1(Application對應的Context例項)
>避免context相關的記憶體洩露,記住以下幾點:
1. 不要讓生命週期長的物件引用activity context,即保證引用activity的物件要與activity本身生命週期是一樣的
2. 對於生命週期長的物件,可以使用application context
3. 避免非靜態的內部類,儘量使用靜態類,避免生命週期問題,注意內部類對外部物件引用導致的生命週期變化
38)許可權機制也弄清楚了?
>Android 是一個許可權分離的系統 。 這是利用 Linux 已有的許可權管理機制,通過為每一個 Application 分配不同的 uid 和 gid , 從而使得不同的 Application 之間的私有資料和訪問( native 以及 java 層通過這種 sandbox 機制,都可以)達到隔離的目的 。 與此 同時, Android 還 在此基礎上進行擴充套件,提供了 permission 機制,它主要是用來對 Application 可以執行的某些具體操作進行許可權細分和訪問控制,同時提供了 per-URI permission 機制,用來提供對某些特定的資料塊進行 ad-hoc 方式的訪問。
>Android 的許可權分離的基礎是建立在 Linux 已有的 uid 、 gid 、 gids 基礎上的 。
UID 。 Android 在 安裝一個應用程式,就會為 它 分配一個 uid (參考 PackageManagerService 中的 newUserLP 實現)。其中普通 A ndroid 應用程式的 uid 是從 10000 開始分配 (參見 Process.FIRST_APPLICATION_UID ), 10000 以下是系統程式的 uid 。
GID 。對 於普通應用程式來說, gid 等於 uid 。由於每個應用程式的 uid 和 gid 都不相同, 因此不管是 native 層還是 java 層都能夠達到保護私有資料的作用 。
GIDS 。 gids 是由框架在 Application 安裝過程中生成,與 Application 申請的具體許可權相關。 如果 Application 申請的相應的 permission 被 granted ,而且 中有對應的 gid s , 那麼 這個 Application 的 gids 中將 包含這個 gid s 。
>一個許可權主要包含三個方面的資訊:許可權的名稱;屬於的許可權組;保護級別。一個許可權組是指把許可權按照功能分成的不同的集合。每一個許可權組包含若干具體 許可權,例如在 COST_MONEY 組中包含 android.permission.SEND_SMS , android.permission.CALL_PHONE 等和費用相關的許可權。
每個許可權通過 protectionLevel 來標識保護級別: normal , dangerous , signature , signatureorsystem 。不同的保護級別代表了程式要使用此許可權時的認證方式。 normal 的許可權只要申請了就可以使用; dangerous 的許可權在安裝時需要使用者確認才可以使用; signature 和 signatureorsystem 的許可權需要使用者的 app 和系統使用同一個數字證照。
Package 的許可權資訊主要 通過在 AndroidManifest.xml 中通過一些標籤來指定。如 <permission> 標籤, <permission-group> 標籤 <permission-tree> 等標籤。如果 package 需要申請使用某個許可權,那麼需要使用 <use-permission> 標籤來指定。
39)觸屏事件的分發呢?Handler 、Message 和 Looper 是怎麼跑起來的?
>一個事件由down move up 三個動作組成,其中move動作可以有多個或者0個,但down 和up動作有且只有一個。這個三個動作中down是最先響應的,它是先驅,由它來決定move和up動作響應路線。
>Touch事件分發中只有兩個主角:ViewGroup和View。Activity的Touch事件事實上是呼叫它內部的ViewGroup的Touch事件,可以直接當成ViewGroup處理。
View在ViewGroup內,ViewGroup也可以在其他ViewGroup內,這時候把內部的ViewGroup當成View來分析。
ViewGroup的相關事件有三個:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。View的相關事件只有兩個:dispatchTouchEvent、onTouchEvent。
先分析ViewGroup的處理流程:首先得有個結構模型概念:ViewGroup和View組成了一棵樹形結構,最頂層為Activity的ViewGroup,下面有若干的ViewGroup節點,每個節點之下又有若干的ViewGroup節點或者View節點
總:在Android方面,自己擅長什麼?->業務邏輯控制稍微多點,有自己的一些模組的積累,對UI繪製稍微少點
相關文章
- Oracle細節及難點總結Oracle
- 細節總結
- UI設計細節及技巧UI
- MR核心程式設計思想總結程式設計
- android的元件、Intent及設計思想Android元件Intent
- 【程式設計素質】程式設計思想總結程式設計
- 《Linux/Unix 設計思想》的翻譯細節討論Linux
- 爬蟲細節總結爬蟲
- Oracle SQL細節總結(一)OracleSQL
- YYImage 設計思路,實現細節剖析
- 「完結」總結12大CNN主流模型架構設計思想CNN模型架構
- 減治思想——二分查詢詳細總結
- 看FCOS時的小細節總結
- Android的細節知識彙總系列(一)Android
- Android中Activity設計思想個人理解Android
- Java程式設計細節之十個最佳實踐Java程式設計
- android基礎夯實3Android
- android基礎夯實2Android
- 拋開技術細節,分享五年職場的個人感悟及道理總結
- 最詳細的 Android Toolbar 開發實踐總結Android
- 夯實基礎系列三:資料庫知識總結資料庫
- Path for iOS設計細節賞析iOS
- 那些容易被忽視的 JavaScript 細節總結JavaScript
- Golang併發程式設計優勢與核心goroutine及注意細節Golang程式設計
- 迴圈佇列的實現及細節佇列
- 最詳細的 Android NavigationDrawer 開發實踐總結AndroidNavigation
- 【我的總結——思想篇】
- 深入理解OkHttp原始碼及設計思想HTTP原始碼
- RxJava2 原始碼解析及設計思想RxJava原始碼
- 我總結的Android程式設計規範Android程式設計
- 生活細節如何影響遊戲設計?遊戲設計
- 那些害死程式設計師的細節程式設計師
- MySQL事務細枝末節總結與分析[更新]MySql
- Oracle SQL細節總結之constraint約束OracleSQLAI
- 慢慢細談Android 面試的細節Android面試
- XML 程式設計思想:踏著語義的節拍(轉)XML程式設計
- 設計模式總結(實踐篇1)設計模式
- 細節決定成敗!APP設計不容忽視的20個細節APP