???? 博主 libin9iOak帶您 Go to New World.???
?? 個(gè)人主頁——libin9iOak的博客??
?? 《面試題大全》 文章圖文并茂??生動形象??簡單易學(xué)!歡迎大家來踩踩~??
?? 《IDEA開發(fā)秘籍》學(xué)會IDEA常用操作,工作效率翻倍~??
???? 希望本文能夠給您帶來一定的幫助??文章粗淺,敬請批評指正!????
《移動互聯(lián)網(wǎng)技術(shù)》課程簡介
《移動互聯(lián)網(wǎng)技術(shù)》課程是軟件工程、電子信息等專業(yè)的專業(yè)課,主要介紹移動互聯(lián)網(wǎng)系統(tǒng)及應(yīng)用開發(fā)技術(shù)。課程內(nèi)容主要包括移動互聯(lián)網(wǎng)概述、無線網(wǎng)絡(luò)技術(shù)、無線定位技術(shù)、Android應(yīng)用開發(fā)和移動應(yīng)用項(xiàng)目實(shí)踐等五個(gè)部分。移動互聯(lián)網(wǎng)概述主要介紹移動互聯(lián)網(wǎng)的概況和發(fā)展,以及移動計(jì)算的特點(diǎn)。無線網(wǎng)絡(luò)技術(shù)部分主要介紹移動通信網(wǎng)絡(luò)(包括2G/3G/4G/5G技術(shù))、無線傳感器網(wǎng)絡(luò)、Ad hoc網(wǎng)絡(luò)、各種移動通信協(xié)議,以及移動IP技術(shù)。無線定位技術(shù)部分主要介紹無線定位的基本原理、定位方法、定位業(yè)務(wù)、數(shù)據(jù)采集等相關(guān)技術(shù)。Android應(yīng)用開發(fā)部分主要介紹移動應(yīng)用的開發(fā)環(huán)境、應(yīng)用開發(fā)框架和各種功能組件以及常用的開發(fā)工具。移動應(yīng)用項(xiàng)目實(shí)踐部分主要介紹移動應(yīng)用開發(fā)過程、移動應(yīng)用客戶端開發(fā)、以及應(yīng)用開發(fā)實(shí)例。
課程的教學(xué)培養(yǎng)目標(biāo)如下:
1.培養(yǎng)學(xué)生綜合運(yùn)用多門課程知識以解決工程領(lǐng)域問題的能力,能夠理解各種移動通信方法,完成移動定位算法的設(shè)計(jì)。
2.培養(yǎng)學(xué)生移動應(yīng)用編程能力,能夠編寫Andorid應(yīng)用的主要功能模塊,并掌握移動應(yīng)用的開發(fā)流程。
3. 培養(yǎng)工程實(shí)踐能力和創(chuàng)新能力。
通過本課程的學(xué)習(xí)應(yīng)達(dá)到以下目的:
1.掌握移動互聯(lián)網(wǎng)的基本概念和原理;
2.掌握移動應(yīng)用系統(tǒng)的設(shè)計(jì)原則;
3.掌握Android應(yīng)用軟件的基本編程方法;
4.能正確使用常用的移動應(yīng)用開發(fā)工具和測試工具。
第十章 系統(tǒng)與通信
本章小結(jié):
1**、本單元學(xué)習(xí)目的**
通過學(xué)習(xí)Android的系統(tǒng)架構(gòu)和系統(tǒng)底層的進(jìn)程通信,重點(diǎn)掌握Android提供的多種進(jìn)程間通信方式,包括:IPC-Binder、AIDL、網(wǎng)絡(luò)編程等技術(shù)。
2**、本單元學(xué)習(xí)要求**
(1) 掌握Android系統(tǒng)的分層架構(gòu)設(shè)計(jì)思想和基于組件的設(shè)計(jì)模式;
(2) 掌握Android系統(tǒng)組件之間的交互方式與信息傳遞;
3**、本單元學(xué)習(xí)方法**
結(jié)合教材以及Android Studio軟件,對進(jìn)程間通信進(jìn)行編程練習(xí),運(yùn)行調(diào)試,并在模擬器中觀察運(yùn)行情況。
4**、本單元重點(diǎn)難點(diǎn)分析**
重點(diǎn)
(1) Android****系統(tǒng)架構(gòu)
Android 是基于Linux平臺的開源手機(jī)操作系統(tǒng)。Android的系統(tǒng)架構(gòu)和其操作系統(tǒng)一樣,采用了分層架構(gòu)。系統(tǒng)架構(gòu)一共有四個(gè)層次,從高到低,分別是應(yīng)用層、應(yīng)用程序框架層、系統(tǒng)運(yùn)行庫層和內(nèi)核層
- 應(yīng)用層
Android平臺不僅僅是操作系統(tǒng),它也包含了許多應(yīng)用程序,比如:電話撥號程序、SMS短信程序、聯(lián)系人、電子郵件、日歷、瀏覽器、照片、媒體播放器、鬧鐘等等。這些應(yīng)用程序都是用Java語言編寫,沒有固化在系統(tǒng)內(nèi)部,可以被開發(fā)人員開發(fā)的其他應(yīng)用程序所代替,因此更加靈活和個(gè)性化。
- 應(yīng)用程序框架層
應(yīng)用程序框架是Android開發(fā)的基礎(chǔ),它采用組件的方式,以方便開發(fā)者重用。開發(fā)人員可以直接使用這些系統(tǒng)提供的組件,也可以通過繼承來擴(kuò)展功能。應(yīng)用程序框架層包含的組件。
應(yīng)用程序框架包括一系列的服務(wù)和管理器:Activity Manager(活動管理器)管理各個(gè)活動的生命周期以及操作功能;Content Provider(內(nèi)容提供器)讓不同應(yīng)用程序可以分享數(shù)據(jù);Package Manager(包管理器)用來獲取Android系統(tǒng)中應(yīng)用程序的信息;Resource Manager(資源管理器)提供應(yīng)用程序使用的各種資源;View System(視圖系統(tǒng))包括列表(lists)、網(wǎng)格(grids)、文本框(text boxes)、按鈕(buttons)等界面元素;此外,還有很多針對不同功能的管理模塊為上層應(yīng)用程序提供API接口,包括系統(tǒng)級服務(wù)進(jìn)程的實(shí)現(xiàn)等等。它們一般由Java語言編寫。
- 系統(tǒng)運(yùn)行庫層
系統(tǒng)運(yùn)行庫層大多采用C/C++實(shí)現(xiàn),它包括兩個(gè)部分:一個(gè)是程序庫,另一個(gè)是Android 運(yùn)行時(shí)環(huán)境。程序庫主要包括基本的C庫、多媒體庫、2D和3D圖形引擎、瀏覽器引擎、本地?cái)?shù)據(jù)庫等等。Android Runtime(運(yùn)行時(shí))分為核心庫和Dalvik 虛擬機(jī)。核心庫包含了Android的一些核心API,如Android.os、Android.net、Android.media等等。Dalvik 虛擬機(jī)負(fù)責(zé)解釋和執(zhí)行生成的Dalvik格式的字節(jié)碼。采用Dalvik 虛擬機(jī),每一個(gè) Android 應(yīng)用都擁有一個(gè)自己的 Dalvik 虛擬機(jī)實(shí)例。相較于傳統(tǒng)的虛擬機(jī),它是一種基于寄存器的Java虛擬機(jī),并且針對移動設(shè)備做了優(yōu)化處理。Android 4.4以后系統(tǒng)開始使用ART虛擬機(jī)。Dalvik采用即時(shí)編譯技術(shù),而ART虛擬機(jī)采用預(yù)編譯技術(shù)。ART虛擬機(jī)極大的提升了應(yīng)用的啟動速度。
- 硬件抽象層和內(nèi)核層
硬件抽象層是對Linux內(nèi)核驅(qū)動程序的封裝,用以屏蔽低層的實(shí)現(xiàn)細(xì)節(jié)。硬件設(shè)備廠商從商業(yè)的角度考慮不希望公布源代碼,而只提供驅(qū)動程序的二進(jìn)制代碼。Linux內(nèi)核源代碼版權(quán)遵循GNU License,它要求在發(fā)布產(chǎn)品時(shí)必須公布源代碼。因此,Android把對硬件支持的所有代碼都放在硬件抽象層HAL。Android系統(tǒng)不再依賴于某一個(gè)具體的硬件驅(qū)動,而是依賴于HAL代碼,這樣第三方廠商將自己不開源的代碼封裝在HAL層,這樣就只需要提供二進(jìn)制代碼。通過這種方式,使Android系統(tǒng)和底層的驅(qū)動分離,通過抽象層向上提供接口屏蔽了低層的實(shí)現(xiàn)細(xì)節(jié)。
Android 的核心依賴于 Linux 2.6 內(nèi)核,核心系統(tǒng)服務(wù),比如內(nèi)存管理、進(jìn)程管理、網(wǎng)路協(xié)議、驅(qū)動模型以及安全性都依賴于Linux內(nèi)核。 此外,在內(nèi)核層中還有電源管理、鍵盤驅(qū)動等等。在進(jìn)程通信方面,雖然Linux提供了多種進(jìn)程間通信方式,但是Android采用Binder來實(shí)現(xiàn)自己的進(jìn)程間通信。把以上四個(gè)層次放在一起就構(gòu)建了 Andriod 的系統(tǒng)架構(gòu)。
(2) 進(jìn)程間通信方法
進(jìn)程間通信或者跨進(jìn)程通信(Inter-Process Communication,IPC)是指兩個(gè)進(jìn)程之間進(jìn)行數(shù)據(jù)交換的過程。操作系統(tǒng)都有相應(yīng)的IPC機(jī)制,比如Windows操作系統(tǒng)通過剪貼板、管道等進(jìn)行進(jìn)程間通信;Linux操作系統(tǒng)的進(jìn)程間通信方式包括:管道(Pipe)、信號(Signal)和跟蹤(Trace)、消息隊(duì)列(Message)、共享內(nèi)存(Share Memory)和信號量(Semaphore)等等。
Android是基于Linux內(nèi)核的移動操作系統(tǒng)。在Linux操作系統(tǒng)中,每個(gè)進(jìn)程都運(yùn)行在一個(gè)獨(dú)立的內(nèi)存中,并在其中完成各自的任務(wù),進(jìn)程之間不允許直接訪問對方的數(shù)據(jù)。但是,有時(shí)進(jìn)程間也需要傳遞數(shù)據(jù)或者委托完成某些任務(wù),這時(shí)必須通過系統(tǒng)的底層操作來完成間接通信。
Android的進(jìn)程間通信方式并不完全來自于Linux,它構(gòu)建了自己的進(jìn)程間通信方式。Android系統(tǒng)提供的進(jìn)程間通信方式包括:Binder、AIDL(Android Interface definition language)、Bundle、文件共享、Messenger、ContentProvider和Socket等等。
Binder中文翻譯為粘合劑,在Android系統(tǒng)中是一種進(jìn)程間的通訊方式(IPC),用于“粘合”兩個(gè)不同的進(jìn)程。從Android Framework角度來看,Binder是ServiceManager連接各種Manager和相應(yīng)ManagerService的橋梁。從Android應(yīng)用層來說,Binder是客戶端和服務(wù)端進(jìn)行通信的媒介。當(dāng)調(diào)用BindService時(shí),服務(wù)端會返回一個(gè)Binder對象,通過這個(gè)對象,客戶端可以獲取服務(wù)端提供的服務(wù)或者數(shù)據(jù),服務(wù)包括普通服務(wù)和基于AIDL的服務(wù)。
AIDL是Android內(nèi)部進(jìn)程通信接口的描述語言。通過AIDL可以處理服務(wù)器端接收的大量并發(fā)請求,也可以實(shí)現(xiàn)跨進(jìn)程的方法調(diào)用。AIDL支持一對多并發(fā)通信,并且支持實(shí)時(shí)通信,但實(shí)現(xiàn)較為復(fù)雜。
Android系統(tǒng)的四大組件中Activity、Service、BroadcastReceiver都可以通過Intent傳遞Bundle數(shù)據(jù)。Bundle實(shí)現(xiàn)了Parcelable接口,可以在不同的進(jìn)程間傳輸數(shù)據(jù)。Bundle簡單易用,適用于四大組件的進(jìn)程間通信。
采用共享文件方式通信,兩個(gè)進(jìn)程可以通過讀/寫同一個(gè)文件交換數(shù)據(jù),例如:P進(jìn)程把數(shù)據(jù)寫入文件,Q進(jìn)程通過讀取這個(gè)文件來獲取數(shù)據(jù)。由于 Android 系統(tǒng)的并發(fā)讀/寫沒有限制,當(dāng)多個(gè)進(jìn)程對同一個(gè)文件進(jìn)行寫操作時(shí),會導(dǎo)致數(shù)據(jù)異常。共享文件方式適用于交換簡單的數(shù)據(jù),不適合高并發(fā)場景,并且無法實(shí)現(xiàn)進(jìn)程間即時(shí)通信。
Messenger是一種輕量級的IPC實(shí)現(xiàn)方式,它的底層通過AIDL來實(shí)現(xiàn)。由于Messenger采用串行處理方式,一次處理一個(gè)請求,因此在服務(wù)端不需要考慮線程同步的問題,而服務(wù)端也不能執(zhí)行并發(fā)操作。Messenger就像郵遞員,通過它在不同進(jìn)程中傳遞“信件”(Message對象),只要將需要傳遞的數(shù)據(jù)放入Message對象,即可實(shí)現(xiàn)數(shù)據(jù)的進(jìn)程間傳輸。Messenger常用于低并發(fā)的一對多即時(shí)通信,但是不能很好地處理高并發(fā)情況,不支持遠(yuǎn)程過程調(diào)用(RPC)。
ContentProvider用于不同應(yīng)用間的數(shù)據(jù)共享,其底層實(shí)現(xiàn)使用了Binder。因?yàn)橄到y(tǒng)對共享做了封裝,讓開發(fā)人員不需要關(guān)心實(shí)現(xiàn)細(xì)節(jié)即可完成進(jìn)程間通信,使得ContentProvider的使用方式比AIDL更簡單。ContentProvider主要以表格的形式組織數(shù)據(jù),對底層的數(shù)據(jù)存儲方式?jīng)]有任何要求,既可以使用SQlite數(shù)據(jù)庫,也可以使用文件,甚至可以使用內(nèi)存中的對象來存儲。
Socket套接字是一種常用的網(wǎng)絡(luò)通信機(jī)制,包括流式套接字(SOCK_STREAM)和數(shù)據(jù)報(bào)套接字(SOCK_DGRAM)兩種,它們分別對應(yīng)網(wǎng)絡(luò)傳輸層中的TCP協(xié)議和UDP協(xié)議。Socket主要用于跨網(wǎng)絡(luò)和本機(jī)上的進(jìn)程間低速通信,其特點(diǎn)是開銷較大,傳輸效率較低。Socket實(shí)現(xiàn)細(xì)節(jié)比較繁瑣,不支持直接的遠(yuǎn)程過程調(diào)用。
Bundle用于傳遞數(shù)據(jù),它保存的數(shù)據(jù)以鍵值對(key-value)的形式存在。四大組件中的三大組件(Activity、Service、BroadcastReceiver)都支持 Intent 中傳遞 Bundle 數(shù)據(jù)。此外,由于 Bundle 實(shí)現(xiàn)了 Parcelable 接口,因此它可以在進(jìn)程間傳輸數(shù)據(jù)。
Bundle位于android.os包中,是一個(gè)final類,因此Bundle不能被繼承。使用Bundle在Activity之間傳遞數(shù)據(jù),傳遞的數(shù)據(jù)可以是boolean、byte、int、long、float、double、string等基本類型或它們對應(yīng)的數(shù)組,也可以是對象或?qū)ο髷?shù)組。當(dāng)Bundle傳遞的是對象或?qū)ο髷?shù)組時(shí),必須實(shí)現(xiàn)Serializable 或Parcelable接口。
Bundle還提供clear函數(shù),該方法用于移除Bundle中的所有數(shù)據(jù)。在Bundle內(nèi)部維護(hù)了一個(gè)ArrayMap對象,它以鍵值對的方式存儲數(shù)據(jù),具體定義在其父類BaseBundle中:
// Invariant - exactly one of mMap / mParcelledData will be null
// (except inside a call to unparcel)
ArrayMap<String, Object> mMap = null;
用Bundle在Activity之間傳遞數(shù)據(jù),首先使用Intent的putExtra函數(shù)來存放附加信息,通過它將Quiz類的參數(shù)信息放置到Bundle實(shí)例中。
Intent Intent = new Intent(“pers.cnzdy.tutorial.ACTION_QUIZ”);
Bundle bundle = new Bundle();
bundle.putInt(“id”, 1);
bundle.putString(“statement”, " Service是一個(gè)可以與用戶交互的Android應(yīng)用組件。");
Intent.putExtras(bundle);
startActivity(Intent);
在接收端,Activity將Bundle中的數(shù)據(jù)提取出來。
Intent intent = getIntent();
Bundle bundle = Intent.getExtras();
int id = bundle.getInt(“id”);
String name = bundle.getString(“statement”);
一個(gè)實(shí)體(用類表示),比如知識點(diǎn)類KPoint,如果要封裝到Bundle消息中,需要實(shí)現(xiàn)Parcelable接口或者Serializable接口。在用Bundle傳遞對象時(shí),KPoint類需要實(shí)現(xiàn)Serializable接口,然后用putSerializable(String key, Serializable value)來保存數(shù)據(jù);在接收數(shù)據(jù)時(shí),用Serializable getSerizlizble(String key)取出數(shù)據(jù)。
Bundle是一個(gè)數(shù)據(jù)容器,本身比較簡單,沒有復(fù)雜的生命周期。對開發(fā)者來說,只需要了解Bundle的基本功能,使用場景并掌握常用的數(shù)據(jù)存取方法。
難點(diǎn)
(1) 通信接口描述語言
AIDL(Android Interface Definition Language)是Android系統(tǒng)自定義的接口描述語言,用于定義服務(wù)端和客戶端之間的通信接口,它可以生成用于進(jìn)程間通信的代碼。AIDL為避免開發(fā)人員重復(fù)編寫代碼,通過類似模板的方式來生成IInterface的實(shí)例代碼。
AIDL語法與Java語言類似,其中AIDL文件以 .aidl 為后綴名。AIDL支持的基本數(shù)據(jù)類型包括:byte、char、short、int、long、float、double、boolean;其他支持的類型有String、CharSequence、實(shí)現(xiàn)Parcelable接口的數(shù)據(jù)類型、List 類型、以及Map類型。List和Map中存放的數(shù)據(jù)類型必須是AIDL支持的類型,或者是其它聲明的AIDL對象。
AIDL文件分為兩類:一類用來聲明實(shí)現(xiàn)了Parcelable接口的數(shù)據(jù)類型,以供其他AIDL文件使用非默認(rèn)支持的數(shù)據(jù)類型;另一類用來定義接口方法,聲明提供服務(wù)的接口,以便客戶端調(diào)用。在接口中,定向Tag用來標(biāo)注這些方法的參數(shù)值,它表示跨進(jìn)程通信中數(shù)據(jù)的流向,分為 in、out、inout 三種方式。in 表示數(shù)據(jù)只能由客戶端流向服務(wù)端;out表示數(shù)據(jù)只能由服務(wù)端流向客戶端,服務(wù)端獲取到傳遞的數(shù)據(jù)后,對該數(shù)據(jù)的任何操作,會同步到客戶端;而 inout表示數(shù)據(jù)可在服務(wù)端與客戶端之間雙向流通?;緮?shù)據(jù)類型、String、CharSequence或者其他AIDL文件定義的方法接口參數(shù)值的定向 Tag 默認(rèn)是in;除了這些類型以外,其他參數(shù)值都需要明確標(biāo)注使用哪種定向Tag。另外,在AIDL文件中需要明確標(biāo)明引用到的數(shù)據(jù)類型所在的包名,即使兩個(gè)文件處在同一個(gè)包名下。
下面通過Quiz示例來說明AIDL的使用方式。Quiz示例的服務(wù)端接收客戶端請求,并提供查詢Quiz列表的信息,同時(shí)可以讓客戶端添加新的題目。
首先實(shí)現(xiàn)服務(wù)端。第一步編寫AIDL文件,將客戶端的請求抽象成接口;然后編寫一個(gè) Service來實(shí)現(xiàn)接口功能,以處理客戶端請求,并且返回Binder;最后,還需要在AndroidManifest中配置Service,以便將Service告知系統(tǒng)。
創(chuàng)建工程IPCServer,包名定義為 pers.cnzdy.ipcserver。在服務(wù)端創(chuàng)建一個(gè) Quiz 類。因?yàn)镼uiz類在服務(wù)端和客戶端都要用到,所以需要在AIDL文件中聲明Quiz類。創(chuàng)建時(shí),需要先建立 Quiz AIDL 文件,然后再創(chuàng)建 Quiz類,以避免出現(xiàn)類名重復(fù)導(dǎo)致無法創(chuàng)建文件的問題。在包名上點(diǎn)擊右鍵,新建一個(gè)AIDL文件,命名為Quiz。
系統(tǒng)會默認(rèn)創(chuàng)建一個(gè)aidl文件夾,它的子文件夾是工程的包名pers.cnzdy.ipcserver,包名下面是Quiz.aidl文件。在Quiz.aidl文件中會生成一個(gè)默認(rèn)函數(shù)basicTypes,將它刪除;并且修改Quiz.aidl,將它改為聲明Parcelable數(shù)據(jù)類型的AIDL文件。Quiz.aidl文件中的代碼如下:
pers.cnzdy.ipcserver
parcelable Quiz;
現(xiàn)在定義Quiz類,并且實(shí)現(xiàn) Parcelable 接口。Quiz類中包含一個(gè) statement(題干)屬性。
public class Quiz implements Parcelable {
private String statement;
public Quiz(String statement) {
this.statement = statement;
}
protected Quiz(Parcel in) {
statement = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(statement);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<Quiz> CREATOR = new Creator<Quiz>() {
@Override
public Quiz createFromParcel(Parcel in) {
return new Quiz(in);
}
@Override
public Quiz[] newArray(int size) {
return new Quiz[size];
}
};
public String getStatement() {
return statement;
}
public void setStatement(String statement) {
this.statement = statement;
}
@Override
public String toString() {
return "Quiz statement:" + statement;
}
public void readFromParcel(Parcel dest) {
statement = dest.readString();
}
}
服務(wù)端要給客戶端提供服務(wù),包括獲取Quiz列表和增加新Quiz兩個(gè)函數(shù),這兩個(gè)函數(shù)定義在IQuiz.aidl文件中。
package pers.cnzdy.ipcserver;
import pers.cnzdy.ipcserver.Quiz;
interface IQuiz {
List getQuizList();
void addQuiz(inout Quiz quiz);
}
編譯代碼,系統(tǒng)將根據(jù)AIDL文件來生成代碼,可以在generated目錄中查看系統(tǒng)生成的文件。在進(jìn)程通信中會用到生成的靜態(tài)抽象類 Stub。接下來創(chuàng)建QuizService類供客戶端遠(yuǎn)程綁定。
public class QuizService extends Service {
private final String TAG = “Server”;
private List QuizList;
public QuizService() {
}
@Override
public void onCreate() {
super.onCreate();
QuizList = new ArrayList<>();
initData();
}
private void initData() {
Quiz Quiz1 = new Quiz(“簡述Intent過濾器的定義和功能?!?;
Quiz Quiz2 = new Quiz(“說明Handler異步消息處理的流程。”);
Quiz Quiz3 = new Quiz(“簡述Service的基本原理和用途。”);
Quiz Quiz4 = new Quiz(“簡述移動計(jì)算的主要特點(diǎn)?!?;
Quiz Quiz5 = new Quiz(“什么是多路復(fù)用?頻分、時(shí)分和碼分多路復(fù)用?”);
Quiz Quiz6 = new Quiz(“簡述競爭信道的工作過程?!?;
QuizList.add(Quiz1);
QuizList.add(Quiz2);
QuizList.add(Quiz3);
QuizList.add(Quiz4);
QuizList.add(Quiz5);
QuizList.add(Quiz6);
}
private final IQuiz.Stub stub = new IQuiz.Stub() {
@Override
public List getQuizList() throws RemoteException {
return QuizList;
}
@Override
public void addQuiz(Quiz quiz) throws RemoteException {
if (quiz != null) {
Log.e(TAG, "服務(wù)器新增一道題目");
QuizList.add(quiz);
} else {
Log.e(TAG, "接收到一個(gè)空對象");
}
}
};
@Override
public IBinder onBind(Intent intent) {
return stub;
}
}
最后,因?yàn)榉?wù)端的Service需要客戶端遠(yuǎn)程綁定,所以客戶端要能找到這個(gè)Service。在AndroidManifest文件中定義Service,并設(shè)置intent-filter標(biāo)簽。通過指定包名來設(shè)置intent-filter的action值。
<service android:name=".QuizService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="pers.cnzdy.ipcserver.action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
接下來編寫客戶端代碼。首先創(chuàng)建IPCClient工程,包名為pers.cnzdy.ipcclient;然后,拷貝服務(wù)端的整個(gè)aidl 文件夾,將其粘貼到IPCClient工程目錄下,aidl文件夾和java文件夾同級。
另外,把服務(wù)端的Quiz類也復(fù)制到IPCClient工程:先在IPCClient中創(chuàng)建一個(gè)新的包,包名與服務(wù)端Quiz類所在的包名相同,然后將Quiz類復(fù)制到這個(gè)包中。
修改activity_client.xml布局文件,添加兩個(gè)按鈕。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<Button
android:id="@+id/btn_getQuizList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查詢題目列表" />
<Button
android:id="@+id/btn_addQuiz"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="增加新的題目" />
</LinearLayout>
ClientActivity通過 Intent 的方式來啟動服務(wù)端的Service。Service 的“pers.cnzdy.ipcserver.action”啟動后,將服務(wù)端返回的 Binder 保存下來并轉(zhuǎn)換成對應(yīng)的實(shí)例quizOperator。如果要和服務(wù)端通信,直接通過quizOperator即可調(diào)用服務(wù)端的函數(shù)。
import pers.cnzdy.ipcserver.IQuiz;
import pers.cnzdy.ipcserver.Quiz;
public class ClientActivity extends AppCompatActivity {
private final String TAG = “Client”;
private IQuiz quizOperator;
private boolean connected;
private List quizList;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
quizOperator = IQuiz.Stub.asInterface(service);
connected = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
connected = false;
}
};
private View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_getQuizList:
if (connected) {
try {
quizList = quizOperator.getQuizList();
} catch (RemoteException e) {
e.printStackTrace();
}
log();
}
break;
case R.id.btn_addQuiz:
if (connected) {
Quiz quiz = new Quiz(“簡述RTS/CTS握手協(xié)議?!?;
try {
quizOperator.addQuiz(quiz);
Log.e(TAG, “向服務(wù)端以InOut方式新增一道題目?!?;
Log.e(TAG, “題目:” + quiz.getStatement());
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_getQuizList).setOnClickListener(clickListener);
findViewById(R.id.btn_addQuiz).setOnClickListener(clickListener);
bindService();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (connected) {
unbindService(serviceConnection);
}
}
private void bindService() {
Intent intent = new Intent();
intent.setPackage(“pers.cnzdy.ipcserver”);
intent.setAction(“pers.cnzdy.ipcserver.action”);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private void log() {
for (Quiz quiz : quizList) {
Log.e(TAG, quiz.toString());
}
}
}
運(yùn)行客戶端程序,顯示兩個(gè)按鈕分別用于獲取服務(wù)端的Quiz列表和新增Quiz。以上示例實(shí)現(xiàn)了客戶端與服務(wù)端之間的通信,客戶端獲取到服務(wù)端的數(shù)據(jù),同時(shí)也向服務(wù)端傳送數(shù)據(jù)。
(2) Binder****進(jìn)程間通信原理
Android建立了一套新的IPC機(jī)制——通過Binder機(jī)制來滿足系統(tǒng)對傳輸性能、安全性和穩(wěn)定性的要求。Binder采用面向?qū)ο蟮乃枷朐O(shè)計(jì),以Client-Server模式進(jìn)行通信,傳輸過程中只需要執(zhí)行一次數(shù)據(jù)拷貝,在性能上僅次于共享內(nèi)存。在安全性上,Binder在底層為發(fā)送方添加UID/PID身份,既支持實(shí)名Binder也支持匿名Binder,提高了通信的安全性。Binder采用Client-Server模式,服務(wù)端提供某個(gè)特定服務(wù)的訪問接入點(diǎn),客戶端通過訪問接入點(diǎn)(服務(wù)地址)向服務(wù)端發(fā)送請求來使用該服務(wù)。對客戶端來說,Binder是通向服務(wù)端的管道入口,如果要和某個(gè)服務(wù)端通信,必須建立這個(gè)管道并獲得管道入口。
Android 應(yīng)用由多個(gè)組件(Activity、Service、Broadcast Receiver 和 Content Provide等)構(gòu)成。進(jìn)程A中的BpBinder表示“Binder的代理”,用于向遠(yuǎn)端發(fā)送請求;進(jìn)程B中的Bbinder表示“Binder響應(yīng)方”,主要用于提供響應(yīng)服務(wù)。此外,Android 系統(tǒng)對應(yīng)用層提供的各種服務(wù),比如:ActivityManagerService、PackageManagerService 等都是基于Binder IPC機(jī)制來實(shí)現(xiàn)。
采用面向?qū)ο蟮膶?shí)現(xiàn)方式,Android系統(tǒng)將進(jìn)程間通信轉(zhuǎn)化為:獲取某個(gè)Binder對象的引用,然后再調(diào)用該對象的方法。Binder對象是一個(gè)可以跨進(jìn)程引用的對象,它提供一組函數(shù)為客戶端提供服務(wù),其實(shí)體位于一個(gè)進(jìn)程(Server)中。在客戶端,可以通過Binder的引用來訪問服務(wù)端??蛻舳说腂inder引用就像指向這個(gè)Binder對象的“指針”,一旦獲取了這個(gè)“指針”就可以通過調(diào)用該對象的函數(shù)來訪問服務(wù)端。對開發(fā)者來說,通過Binder引用調(diào)用服務(wù)端提供的方法和通過指針調(diào)用任何本地對象的方法一樣,只是前者的實(shí)體位于遠(yuǎn)端服務(wù)器中,而后者的實(shí)體位于本地內(nèi)存。Binder引用可以從一個(gè)進(jìn)程傳給其它進(jìn)程,就像把一個(gè)對象的引用賦值給另一個(gè)引用一樣,這樣多個(gè)進(jìn)程可以通過Binder引用訪問同一個(gè)服務(wù)端。而對Binder對象來說,它的引用將遍布于系統(tǒng)的各個(gè)進(jìn)程之中。
從通信的角度來說,客戶端中的Binder可以看作是服務(wù)端Binder的“代理”,它在本地代表遠(yuǎn)端服務(wù)器為客戶端提供服務(wù)。Binder的通信方式消除了進(jìn)程間的邊界,淡化了通信過程,整個(gè)系統(tǒng)就像運(yùn)行在一個(gè)程序中,Binder對象及其引用就是粘接各個(gè)應(yīng)用的膠水。
從結(jié)構(gòu)上來看,Binder由四個(gè)部分組成,分別是:Binder客戶端、Binder服務(wù)端、Binder驅(qū)動和ServiceManager模塊。客戶端、服務(wù)端和Service Manager運(yùn)行在用戶空間,而Binder驅(qū)動程序運(yùn)行在內(nèi)核空間。進(jìn)程通信的核心組件是Binder驅(qū)動程序。Service Manager提供輔助管理的功能。客戶端和服務(wù)端在Binder驅(qū)動和Service Manager的基礎(chǔ)上,完成通信。Android系統(tǒng)實(shí)現(xiàn)了Binder驅(qū)動程序和ServiceManager,開發(fā)者只需要在用戶空間編寫自己的客戶端和服務(wù)端代碼。
Binder驅(qū)動負(fù)責(zé)建立進(jìn)程之間的Binder通信,在進(jìn)程之間傳遞Binder,管理Binder的引用計(jì)數(shù),在進(jìn)程之間傳遞數(shù)據(jù)包和執(zhí)行交互等一系列底層操作。在Android系統(tǒng)的應(yīng)用框架層,對Binder的底層操作進(jìn)行了封裝,并且通過 JNI 技術(shù)來調(diào)用 Native(C/C++)層的 Binder 接口。在Native層,Binder以ioctl(設(shè)備驅(qū)動程序中管理設(shè)備I/O通道的函數(shù))方式與內(nèi)核層的Binder 驅(qū)動進(jìn)行通信。Binder驅(qū)動為穿過進(jìn)程邊界的Binder創(chuàng)建位于內(nèi)核中的實(shí)體節(jié)點(diǎn)以及ServiceManager對實(shí)體的引用;同時(shí),將Binder的名字以及新建的引用打包傳遞給ServiceManager。
ServiceManager是一個(gè)守護(hù)進(jìn)程,它用于管理系統(tǒng)中的各個(gè)服務(wù)端,并且向客戶端提供查詢服務(wù)端接口的能力。它將字符形式的Binder名字轉(zhuǎn)換為客戶端中該Binder的引用,這樣客戶端就能夠通過Binder的名字來獲取Server中Binder實(shí)體的引用。服務(wù)端向ServiceManager注冊了Binder實(shí)體及其名字后,客戶端就可以通過名字獲得該Binder的引用。這時(shí)Binder對象有兩個(gè)引用:一個(gè)位于ServiceManager,另一個(gè)位于發(fā)起請求的客戶端。當(dāng)有其他的客戶端請求該Binder時(shí),系統(tǒng)中就會有多個(gè)引用指向該Binder,就象Java程序中一個(gè)對象有多個(gè)引用;同時(shí)只要系統(tǒng)中存在Binder引用,就不會釋放Binder實(shí)體。
ServiceManager與其它進(jìn)程一樣也是采用Binder進(jìn)行通信。ServiceManager是服務(wù)端,它有自己的Binder對象(實(shí)體),而其它進(jìn)程都是客戶端,需要通過這個(gè)Binder的引用來完成Binder的注冊、查詢和獲取。ServiceManager的Binder比較特殊,它沒有名字也不需要注冊。這個(gè)Binder的引用在所有客戶端中都固定為0號引用而無須通過其它方式來獲取。如果一個(gè)進(jìn)程的Server向ServiceManager發(fā)起注冊請求,它的Binder需要通過0引用號與ServiceManager的Binder通信。這時(shí),相對于ServiceManager,進(jìn)程中提供服務(wù)的Server是客戶端。而0號引用就像域名服務(wù)器的地址,需要預(yù)先手工或動態(tài)配置??蛻舳艘餐ㄟ^保留的0號引用向ServiceManager請求訪問某個(gè)Binder。比如:申請獲得名字為“IQuiz”的Binder引用。
在Binder工作過程中,為客戶端和服務(wù)端分別設(shè)置一個(gè)代理:客戶端代理Proxy和服務(wù)端代理Stub。進(jìn)程A中的Proxy和進(jìn)程B中的Stub通過Binder驅(qū)動和ServiceManager進(jìn)行數(shù)據(jù)傳輸,即服務(wù)端和客戶端直接調(diào)用Proxy和Stub的接口傳輸數(shù)據(jù),。
ServiceManager是第一個(gè)啟動的服務(wù),其他服務(wù)端進(jìn)程啟動后,需要在ServiceManager中進(jìn)行注冊。當(dāng)ServiceManager收到客戶端的連接請求,從請求數(shù)據(jù)包里獲得Binder的名字,在查找表里找到該名字對應(yīng)的條目,從條目中取出Binder引用,將該引用發(fā)送給發(fā)起請求的客戶端。
客戶端通過ServiceManager來獲取服務(wù)端的服務(wù)列表。當(dāng)調(diào)用服務(wù)器端的函數(shù)時(shí),客戶端直接調(diào)用Proxy。ServiceManager屏蔽了Binder的實(shí)現(xiàn)細(xì)節(jié),因此客戶端不需要知道Binder的具體工作方式。
在Android系統(tǒng)中有兩種Binder,分別是:實(shí)名Binder和匿名Binder。實(shí)名Binder是注冊了名字的Binder,就像互聯(lián)網(wǎng)上的網(wǎng)站除了IP地址外還有自己的網(wǎng)址。服務(wù)端創(chuàng)建Binder實(shí)體后,給它賦予一個(gè)容易記憶的名字,并將這個(gè)Binder連同它的名字以數(shù)據(jù)包的形式通過Binder驅(qū)動發(fā)送給ServiceManager,通知ServiceManager注冊這個(gè)帶有名字的Binder。ServiceManager收數(shù)據(jù)包后,從中取出名字和引用填入一張查找表中。
匿名Binder是沒有向ServiceManager提交注冊的Binder。當(dāng)已經(jīng)建立了Binder通信連接,返回Binder引用的時(shí)候,Binder驅(qū)動保存這個(gè)Binder實(shí)體的各種數(shù)據(jù)。服務(wù)端可以將Binder的引用傳遞給某個(gè)客戶端,客戶端收到這個(gè)匿名Binder引用,通過該引用向位于服務(wù)端中的實(shí)體發(fā)送請求。由于這個(gè)Binder沒有向ServiceManager注冊名字,所以稱為匿名Binder。注意建立的Binder連接必須通過實(shí)名Binder來實(shí)現(xiàn)。匿名Binder為通信進(jìn)程建立了一條私密通道,只要服務(wù)端不把匿名Binder發(fā)給其他進(jìn)程,其他進(jìn)程就無法通過猜測或窮舉等方式獲取該Binder引用,從而無法請求服務(wù)。
(3) 網(wǎng)絡(luò)編程
Android支持TCP/UDP網(wǎng)絡(luò)通信API,可以使用Socket來建立基于TCP/IP協(xié)議的網(wǎng)絡(luò)通信;也可以使用數(shù)據(jù)報(bào)Socket(DatagramSocket)建立基于UDP協(xié)議的網(wǎng)絡(luò)通信。另外,Android也支持URL、URLConnection等網(wǎng)絡(luò)通信API。
Socket是基于TCP/IP通信協(xié)議是一種網(wǎng)絡(luò)通信方式,通信雙方通過Socket可以在通信兩端建立起一個(gè)網(wǎng)絡(luò)虛擬鏈路,兩端的程序可以通過虛擬鏈路進(jìn)行通信。下面創(chuàng)建一個(gè)Android應(yīng)用客戶端,通過Socket連接一個(gè)用Python程序?qū)崿F(xiàn)一個(gè)服務(wù)端程序。Android應(yīng)用的界面中包含一個(gè)按鈕和一個(gè)文本框,按鈕發(fā)起連接,文本框用于輸入發(fā)送的數(shù)據(jù)和顯示從服務(wù)器端接收到的字符串?dāng)?shù)據(jù)。要連接服務(wù)端程序,需要知道對方的IP地址和端口號。在連接服務(wù)器函數(shù)中,開啟一個(gè)線程,在線程中調(diào)用tcpClient函數(shù)實(shí)現(xiàn)Socket通信。
public class SocketActivity extends AppCompatActivity {
private static final String TAG = “SocketActivity”;
TextView textView;
*// serverIp**服務(wù)端的**IP
* private static final String serverIp = “192.168.1.105”;
private static final int port = 12345; //connection**另一端的端口
public void connectServerSocket(View view){
Thread thread = new Thread(){
@Override
public void run(){ tcpClient();}
};
thread.start();
}
首先,創(chuàng)建一個(gè)指定IP和端口的Socket對象,然后,構(gòu)建一個(gè)緩沖讀取器,讀取的數(shù)據(jù)來自于Socket接收的數(shù)據(jù)。Socket的getInputStream函數(shù),返回該Socket對象對應(yīng)的輸入流,通過該輸入流可以從Socket中取出服務(wù)端發(fā)送的數(shù)據(jù)。getOutputStream函數(shù)類似,它返回的輸出流可以向Socket中輸出數(shù)據(jù),也就是向服務(wù)端發(fā)送數(shù)據(jù)。
private void tcpClient(){
try{
Socket socketClient = new Socket(serverIp, port);
Log.*i*(*TAG*,"新建套接字...");
BufferedReader in = new BufferedReader(
new InputStreamReader(
socketClient.getInputStream()));
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(
socketClient.getOutputStream()));
String outMsg = “TCP 連接端口:” + port + " Hello Server!"; *
* Log.i(TAG,“開始發(fā)送數(shù)據(jù)…”);
out.write(outMsg); *//發(fā)送數(shù)據(jù)
* out.flush();
Log.*i*(*TAG*, "Tcp客戶端發(fā)送: " + outMsg);
Log.*i*(*TAG*,"開始接收數(shù)據(jù)...");
String inMsg = in.readLine();
showResponse(inMsg);
socketClient.close();
} catch (UnknownHostException e) {
e.printStackTrace();
}
catch (IOException e){ e.printStackTrace();}
}
通過輸出緩沖對象out,可以向socket中寫入發(fā)送給服務(wù)端的數(shù)據(jù),服務(wù)端在接收到數(shù)據(jù)以后,會發(fā)送響應(yīng)消息給Android應(yīng)用,通過輸入緩沖對象in,可以讀取Socket傳送過來的信息,調(diào)用showResponse函數(shù)將服務(wù)端的信息顯示在界面上。注意完成通信以后,需要關(guān)閉Socket。在傳輸過程中,可能出現(xiàn)各種異常,比如服務(wù)端沒有啟動,網(wǎng)絡(luò)中斷等,因此,通過異常處理機(jī)制,能夠處理各種通信異常情況。
通常應(yīng)用的網(wǎng)絡(luò)通信在后臺運(yùn)行,這樣就不會影響前臺界面的用戶操作。前后臺要通信,比如將網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)顯示在應(yīng)用界面上,不能直接操作界面控件。在這里通過開啟一個(gè)線程將數(shù)據(jù)傳給文本顯示控件。更標(biāo)準(zhǔn)的交互方式是通過handler等異步消息機(jī)制來實(shí)現(xiàn)。由于Socket通信需要訪問互聯(lián)網(wǎng),因此還需要為該Android應(yīng)用賦予訪問互聯(lián)網(wǎng)的權(quán)限。
通過使用URL來訪問一個(gè)指定的網(wǎng)址,并獲取網(wǎng)頁中的圖片,在界面上設(shè)置了一個(gè)按鈕和一個(gè)ImageView控件。點(diǎn)擊按鈕將訪問指定的網(wǎng)址并下載圖像顯示在imageView控件上。在URL活動中,定義了一個(gè)URL對象和一個(gè)線程對象。與Socket通信一樣,在線程中通過URL實(shí)現(xiàn)網(wǎng)絡(luò)通信,為了顯示網(wǎng)絡(luò)傳輸?shù)膱D片,通過handler來設(shè)置imageView控件上顯示的圖片。
public class URLActivity extends AppCompatActivity {
public static final int SHOWIMAGEMSG = 1;
private String strURL;
private URL url;
private Bitmap bitmap;
private String fileName;
private ImageView imageView;
Thread thread;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOWIMAGEMSG) {
imageView.setImageBitmap(bitmap); } }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
… …
imageView = findViewById(R.id.image_view_url_get);
strURL = “https://edu-image.nosdn.127.net/” +
“BB7D91BE8141EE86A261E3857BAFE188.png?” +
“imageView&thumbnail=510y288&quality=100”;
fileName = “mobilecomputing.png”;
thread = new Thread() {
public void run() {
getImage();
}
};
}
在活動的onCreate函數(shù)中,指定了應(yīng)用訪問的URL地址,這里是一個(gè)網(wǎng)頁中的圖片。在線程中,調(diào)用getImage函數(shù)來下載該圖片。下載圖片時(shí),首先根據(jù)網(wǎng)址創(chuàng)建url對象,調(diào)用openStream函數(shù)打開傳輸流,接著調(diào)用得出decodeStream函數(shù)將流數(shù)據(jù)解碼生成bitmap對象,并通過handler發(fā)送“顯示圖像”消息,在界面上顯示圖片;最后,將下載的圖片通過OutputStream保存到移動設(shè)備的data\data\ 目錄下。Filename是指定的圖像文件名。
private void getImage() {
try {
url = new URL(strURL);
InputStream is = url.openStream();
bitmap = BitmapFactory.decodeStream(is);
handler.sendEmptyMessage(SHOWIMAGEMSG);
OutputStream os = openFileOutput(fileName, *MODE_PRIVATE*);
byte[] buff = new byte[1024];
int hasRead = 0;
* while ((hasRead = is.read(buff)) > 0) {
os.write(buff, 0, hasRead);
}
is.close();
os.close();
} catch (Exception e) { e.printStackTrace(); }
}
本章習(xí)題:
1**、本單元考核點(diǎn)**
Android系統(tǒng)的分層架構(gòu),每一層的功能模塊。
Android系統(tǒng)的各種進(jìn)程間通信方式。
2**、本單元課后習(xí)題**
1、AIDL的全稱是什么?如何工作?能處理哪些類型的數(shù)據(jù)??
答案:AIDL:Android Interface Definition Language,即Android接口描述語言。Android系統(tǒng)中的進(jìn)程之間不能共享內(nèi)存,因此,需要提供一些機(jī)制在不同進(jìn)程之間進(jìn)行數(shù)據(jù)通信。
為了使其他的應(yīng)用程序也可以訪問本應(yīng)用程序提供的服務(wù),Android系統(tǒng)采用了遠(yuǎn)程過程調(diào)用( Remote Procedure Call,RPC) 方式來實(shí)現(xiàn)。與很多其他的基于RPC 的解決方案一樣,Android 使用一種接口定義語言(Interface Definition Language,IDL)來公開服務(wù)的接口。因此,可以將這種可以跨進(jìn)程訪問的服務(wù)稱為AIDL( Android Interface Definition Language) 服務(wù)。
如果需要在一個(gè)Activity中,訪問另一個(gè)Service中的某個(gè)對象,需要先將對象轉(zhuǎn)化成AIDL可識別的參數(shù)(可能是多個(gè)參數(shù)),然后使用AIDL來傳遞這些參數(shù),在消息的接收端,使用這些參數(shù)組裝成自己需要的對象
AIDL支持的數(shù)據(jù)類型:
(1) 不需要import聲明的簡單Java編程語言類型(int, boolean等);
(2) String、CharSequence不需要特殊聲明;
(3) List、Map和Parcelables類型,這些類型內(nèi)所包含的數(shù)據(jù)成員也只能是簡單數(shù)據(jù)類型,String等其他支持的類型。
2、什么是嵌入式實(shí)時(shí)操作系統(tǒng),Android操作系統(tǒng)屬于實(shí)時(shí)操作系統(tǒng)嗎?
答案:嵌入式實(shí)時(shí)操作系統(tǒng)是指當(dāng)外界事件或數(shù)據(jù)產(chǎn)生時(shí),能夠接受并以足夠快的速度予以處理,其處理的結(jié)果又能在規(guī)定的時(shí)間之內(nèi)來控制生產(chǎn)過程或?qū)μ幚硐到y(tǒng)作出快速響應(yīng),并控制所有實(shí)時(shí)任務(wù)協(xié)調(diào)一致運(yùn)行的嵌入式操作系統(tǒng)。主要用于工業(yè)控制、軍事設(shè)備、航空航天等領(lǐng)域,對系統(tǒng)的響應(yīng)時(shí)間有苛刻的要求,這就需要使用實(shí)時(shí)系統(tǒng)。又可分為軟實(shí)時(shí)和硬實(shí)時(shí)兩種,而android是基于linux內(nèi)核的,因此屬于軟實(shí)時(shí)。
3、談?wù)凙ndroid的IPC機(jī)制。
答案:IPC是內(nèi)部進(jìn)程通信的簡稱,是共享"命名管道"的資源。Android中的IPC機(jī)制是為了讓Activity和Service之間可以隨時(shí)的進(jìn)行交互,故在Android中,該機(jī)制只適用于Activity 和Service之間的通信,類似于遠(yuǎn)程方法調(diào)用,類似于C/S模式的訪問。通過定義AIDL接口文件來定義IPC接口。Servier端實(shí)現(xiàn)IPC接口, Client 端調(diào)用IPC接口本地代理。
參考資源:
1、林學(xué)森著.深入理解Android內(nèi)核設(shè)計(jì)思想.北京:人民郵電出版社,2014.
2、任玉剛著.Android開發(fā)藝術(shù)探索.北京:電子工業(yè)出版社,2015.
原創(chuàng)聲明
=======
作者: [ libin9iOak ]
本文為原創(chuàng)文章,版權(quán)歸作者所有。未經(jīng)許可,禁止轉(zhuǎn)載、復(fù)制或引用。
作者保證信息真實(shí)可靠,但不對準(zhǔn)確性和完整性承擔(dān)責(zé)任。
未經(jīng)許可,禁止商業(yè)用途。
如有疑問或建議,請聯(lián)系作者。
感謝您的支持與尊重。文章來源:http://www.zghlxwxcb.cn/news/detail-577396.html
點(diǎn)擊
下方名片
,加入IT技術(shù)核心學(xué)習(xí)團(tuán)隊(duì)。一起探索科技的未來,共同成長。文章來源地址http://www.zghlxwxcb.cn/news/detail-577396.html
到了這里,關(guān)于《移動互聯(lián)網(wǎng)技術(shù)》 第十章 系統(tǒng)與通信: 掌握Android系統(tǒng)的分層架構(gòu)設(shè)計(jì)思想和基于組件的設(shè)計(jì)模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!