<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    冰浪

    哥已不再年輕 - 堅定夢想,畢生追求!
    posts - 85, comments - 90, trackbacks - 0, articles - 3
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    [轉]組件間的交互和進程間IPC通信

    Posted on 2010-01-15 00:15 冰浪 閱讀(465) 評論(0)  編輯  收藏 所屬分類: Android
    在Android中窗體與窗體之間如何互相調用和交換數據?窗體(Activity)和后臺的服務(Service)如何通信?基于Unix(Linux)的系統都有一個很優秀的傳統,就是倡導非常輕便的進程間通信(IPC)機制;倡導進程通過IPC來互相協作;倡導功能單一,小巧而強壯的進程,而不是又大又復雜的“萬金油”。同樣,在Android中我們可以將我們的Activity和Service放在不同的進程中運行,我們可以在我們的Task 中加載其他進程的Activity,這些機制都鼓勵我們“盡量利用已有的功能,利用IPC和包含這些已有功能的程序協作,來完成一個完整的應用”,例如在我們的程序中充分利用Google Map的相關窗體和服務。所有這些都建立在一套輕便好用的IPC機制上。


    Android的組件和進程間通信都建立在一種基于稱為Intent的消息基礎之上。Intent就是一種消息,它包含了兩個重要的內容:1. 消息的目的,即這個消息是發給哪個組件的?(消息的目的中不會包含“消息是發給哪個進程”這樣的信息,這里Android有意淡化進程的概念,而只讓我們關心組件,因為了解太多關于進程的具體信息會加大復雜度,而又如何做到進程間的消息傳遞呢?下文會說到一種Android中關于這點比較特別的設計方式,我認為是一種簡捷有用又符合手機特點的設計);2. 消息所攜帶的數據內容,即需要傳遞給目標的數據。下面是一個簡單的利用Intent來啟動一個Service并向其傳遞數據的代碼示例:


    Intent serviceIntent = new Intent(context, svrMain.class);
    serviceIntent.putExtra(“Network_Report”, networkStatus);
    context.startService(serviceIntent);


    上面的代碼首先構造了一個Intent對象,并在構造的時候指定了這個Intent的目的地,即“svrMain.class”,表示這個Intent是要傳遞給一個類名叫svrMain的Service。然后向這個Intent中放入了一個數據,數據的key為“Network_Report”,value為一個叫networkStatus的int類型變量,用來指明當前網絡的狀態。最后我們使用系統提供的上下文API,將這個Intent傳遞給指定的Service。


    Intent的消息目的地分為兩種模式,一種是顯式的,一種是隱式的。我們上面的例子中看到的就是一個顯式消息的例子。顯式消息直接指定消息目的地組件的類元信息,例如上面例子中svrMain就是我們寫的一個類名為svrMain的Service,class操作符就是獲取其類元信息。這種模式的消息由于已經確切知道了消息目標的確切信息,所以只適用于同一進程內的不同組件之間通信,例如打開一個子窗體,和同一進程中的service通信等。對應的,隱式消息就一般用于跨進程的通信了,隱式消息沒有確定的消息目的地,除了數據外,隱式消息只是包含了一些用于表征消息特征的描述字段。而一些需要收到某種特定特征消息的某個程序中的某個組件,需要通過在其所在程序的AndroidMainifest.xml中注冊一種被稱為intent-filter的消息特征篩選器,然后Android系統會按照一定的匹配規則來匹配發出的消息特征和所有擁有響應這種特征的intent-filter的組件(無論是同一進程內的組件還是不同程序中的組件),匹配到的組件就會接受到相應的消息。前面的描述多少有些拗口,我們舉個實際的例子來說明,如果我們想開啟一個子窗體(無論這個窗體來自同一進程還是不同進程),我們除了使用顯式消息外,我們還可以使用隱式消息:


    Intent openSomeDiagIntent = new Intent();
    openSomeDiagIntent.setAction(“edwin.demo.fooActivity”);
    this.startActivity(openSomeDiagIntent);


    上面的隱式消息不包含具體的目的地,而是僅包含一個名位“Action”的特征字符串,Action就是上文所說的Intent特征的一種。從字面上來理解,可以理解為這個消息所代表的是完成某一個動作的含義,由action來標明動作的名字。所有能夠處理這種動作的Activity都可以收到該消息。對應的,可能在同一個程序或者另外的某個程序的AndroidMainifest.xml中聲明了下面這樣的一個Activity:


    <activity android:name=”.fooActivity”>
    <intent-filter>
    <action android:name=”edwin.demo.fooActivity” />
    </intent-filter>
    </activity>


    那么這就表示這個Activity能夠收到并處理action為“edwin.demo.fooActivity”的消息。所以上面的代碼串起來的效果就是,打開了這個名為.fooActivity的窗口,無論這個窗口是在當前的進程中還是另外的一個程序中。


    除了Action這種消息特征外,Intent還有category,data這兩個特征描述屬性。Category同樣是一個字符串,從字面上理解就是“消息的分類特征”。從程序上看其和Action的不同在于,一個Intent只能有惟一的一個Action名稱,但是卻可以包含多個Category字符串;一個Intent-Filter可以包含多個Action節點但至少要包含一個,另一方面一個Intent-Filter可以包含零到多個Category節點。Android在做Intent-Filter匹配的時候,Intent的Action屬性匹配到Intent-Filter中的任何一個action節點,就表明擁有這個Intent-Filter的組件能夠處理這種消息;而對于Category來講一個Intent中的所有的Category都必須存在于Intent-Filter中的Category節點中時,才表明匹配成功。Data屬性可以描述一個Intent所要傳遞的數據類型和URI,每一個Intent只能包含一個Data屬性。其中數據的類型使用MIME類型描述方式來描述,例如video/mpeg表示編碼格式為mpeg的視頻,這里也可以使用通配符,例如video/*表示任意格式的視頻文件類型;數據的URI由scheme(協議),host,port,path四部分組成:scheme://host:port/path,例如http://test.com:8080/file/file1 或者content://edwin.demo.contentProvider:100/forder/content1,其中path部分也是可以支持通配符的。Data屬性是一個很有用的描述特征,例如下面這樣的一個包含data節點的Intent-Filter:


    <activity android:name=”.actHttpVideoMan”>
    <intent-filter>
    <action android:name=”edwin.demo.actHttpVideoMan.Main” />
    <data android:scheme=”http” android:type=”video/*” />
    </intent-filter>
    </activity>


    它表示窗體actHttpVideoMan能夠處理來自web服務器的視頻文件。這樣的filter有什么作用呢?最典型的情況就是配合瀏覽器工作。瀏覽器在打開一個鏈接的時候首先會嘗試顯示這個鏈接對應的html頁面,如果這個鏈接不是一個html頁面,而是一個視頻文件或者其他瀏覽器本身不能處理的格式的話,瀏覽器會使用隱式消息嘗試開啟一個能夠處理這種數據格式的Activity來處理,瀏覽器發出的隱式消息就是一個包含data屬性,其中URI scheme為http,數據類型為video/*的消息,如果有能夠匹配這個intent的組件,例如我們上面的那個activity,瀏覽器就會啟動這個窗體,接著這個窗體會根據data屬性指定的URI去播放在線視頻,如果沒有可以處理這個intent的Activity,瀏覽器才會調用下載管理器下載文件。


    隱式消息這個設計簡單有效,它忽略了進程的細節,讓IPC在一個更高的更接近人腦思維模式的層次工作,讓系統中的不同進程協作看起來就像是同一程序中的協作一樣,這種簡單的IPC機制在很大的程度上鼓勵我們和其他進程協作,通過協作的進程來完成一個復雜的任務,而不是把什么功能都做到一個大而全的程序里面。不過上文還有一些細節沒有提到,例如如果一個intent有多個可匹配的處理組件,系統如何處理?這就要分響應消息的組件類型來說了,如果是service,那么這些service都可以啟動并處理消息,如果是Activity,則android會彈出一個對話框讓用戶進行選擇。比如我們安裝了多個可以處理在線視頻的軟件,當我們在瀏覽器中點擊一個在線視頻的鏈接時,系統會讓用戶選擇使用哪個軟件來觀看。另外大家一定會想到安全性的問題,如果不同進程間的組件可以通過隱式消息互相通信,那我們的程序不是可以輕易調用到其他的程序或者系統中的一些敏感程序的組件,這樣會不會很不安全呢?其實Android在安全方面有一個統一,完備和輕便的安全策略模型,Intent的安全自然是被考慮在內的,關于android的安全模型我會在后續的系列blog中專門說明。


    最后,除了Intent這種基于消息的進程內和進程間通信模型外,android中也有一種相比起來稍顯笨重一些的IPC機制,它采用類似遠程方法調用的方案,通過接口定義文件AIDL來定義一個IPC接口,然后通過接收方實現接口,調用方調用接口的本地代理實現來完成IPC。這種模型只適用于Activity和Service間的通信,之所以需要這種稍顯重量的模式,是因為Activity除了發送intent去啟動一個service外,可能還需要能夠在Service的運行過程中連接到service,對Service發送一些控制請求。例如音樂播放程序,其后臺的播放服務往往獨立運行,以方便我們在使用其他程序界面時也能聽到音樂。同時這個后臺播放服務也會定義一個控制接口,包含比如播放,暫停,快進之類的方法,任何時候播放程序的界面都可以通過使用bindService API連接到播放服務,獲取這個接口的包含IPC細節的實現代理,通過這組控制接口方法對其進行控制,這時這種IPC的方案就顯的更方便更直觀一些了。有關使用AIDL這種IPC的更詳細描述,Google的官方文檔已做了詳細的講解。

    轉自:http://hkbarton.sacredfir.com/?p=93
    主站蜘蛛池模板: 国产一区二区三区在线观看免费| 99精品视频在线免费观看| 免费做爰猛烈吃奶摸视频在线观看| 亚洲欧洲日产国码无码网站| 国产精品美女免费视频观看| 国产亚洲精品a在线观看| 人妻仑乱A级毛片免费看| 亚洲伊人久久成综合人影院| 一区二区三区在线免费| 国产精品亚洲高清一区二区| 国产免费A∨在线播放| 亚洲高清国产AV拍精品青青草原| 日本免费中文字幕| 亚洲最大黄色网址| 99精品全国免费观看视频| 亚洲GV天堂无码男同在线观看| 国产小视频在线免费| 一级女性全黄久久生活片免费| 国产日产亚洲系列最新| 黄色免费在线网站| 亚洲福利视频网站| 日韩免费三级电影| 一个人免费播放在线视频看片| 国产亚洲综合成人91精品 | 伊人久久大香线蕉亚洲五月天 | 99热这里只有精品免费播放| 亚洲毛片基地日韩毛片基地 | 亚洲国产精品狼友中文久久久| a级毛片毛片免费观看久潮喷| 亚洲国产精品专区| 国产精品久久久久影院免费| 中文字幕乱码免费看电影| 亚洲国产视频网站| 免费人成网站在线播放| 免费在线观影网站| 亚洲区日韩精品中文字幕| 亚洲人成影院在线无码按摩店| 免费观看美女用震蛋喷水的视频| 老司机亚洲精品影院在线观看| 亚洲av无码成h人动漫无遮挡| 在线免费观看一级毛片|