MeeGo Touch服務框架
介紹
用戶進程接口被稱這個服務框架是這樣的一種IPC機制,這個機制允許應用單元簡便地使用或者服務于一個接口。在這個文檔,用為“使用者”,而提供者進程接口被稱為“提供者”。
這個服務框架的目的如下:
-
為了提供一個可簡單使用的IPC機制
-
為了確保在服務的使用者和提供者之間沒有運行時二進制依賴關系
-
為了允許用戶在使用一個接口時不用擔心選擇或者連接到一個接口時的具體邏輯
-
為了允許用戶能查詢提供者的列表,并且能從中選擇一個
基本的服務機制
上圖展示了當一個服務端的用戶(SU)使用一個接口(IF)時將發生什么.
-
服務端使用者舉例,一個接口去請求服務映射器給出實現那個接口的服務提供者的名稱
-
這個服務器映射器維護著一張服務和接口之間的映射關系表(通過查看dbus服務目錄,通常為/usr/share/dbus-1/services這個目錄)同時服務器映射器還有一套選擇服務的規則.它選擇一個服務,然后將服務的名稱返回給SU的接口.
-
SU的接口接著創建一個正當的dbus連接到一個已經給出名稱的服務,然后調用一個合適的方法
當IF有一個新的SP時,服務映射器就會發送一個信號給適當的SU接口通知他們,或者如果IF沒有更多的SP,SU也會發送通知。當有事件發生時,應用程序將會通過連接到在IF中的一個信號得到通知并采取相應的動作。例如,一個圖片應用程序可能希望允許一個用戶通過EMAIL去發送一個照片,它可以監聽“沒有更多的SP給IF”這個信號,從而知道什么時候去使這個操作失效。
服務框架的典型使用案例
-
從一個應用程序的界面啟動或顯示另一個應用程序的指定畫面。
-
在設備上得到一個有效的視頻內容的列表或者縮略圖
-
啟動一個網頁瀏覽器顯示指定的頁面
-
從一個有效的內容里選擇或者顯示指定圖片
-
顯示最近的聯系人記錄
-
顯示2042年第13個星期五的日程安排
服務框架不應該被使用做一般的IPC通訊或者例如介于兩個小程序之間的通訊,這些應該使用其他方法來完成,例如,使用像DuiValueSpace一樣可以提供數值改變通知的數據后端的方法。
用法
作為一個服務提供者(SP)
SP的開發者需要準備2樣東西:
二進制文件
當一個服務端用戶應用程序試圖連接到這個服務時,這個二進制文件將被加載(如果它沒有正在運行)。
接口
服務端用戶應用程序的開發者需要的文件包括如下內容:
-
duiservicefwbaseif.h/cpp文件,這些文件對于所有的接口層都是通用的
duiservicefwbaseif.h文件是libdui-dev包的一部分,duiservicefwbaseif.cpp會被編譯到libdui,所以他們都是libdui0包的一部分 -
需要給接口提供XML文件,頭文件,庫和一個.serveice文件
接口特定的頭文件和接口的XML文件將共同成為maemo-interfaces-dev包的一部分,然后相應的cpp文件需要編譯到接口特定的庫文件里面,這些庫又是maemo-interfaces包的一部分。.service文件也將會成為maemo-interfaces包的一部分。
二進制文件
-
創建一個用于定義接口的XML文件.
如果你希望一個方法連接到當前的應用,你可以添加一個chainTask="true"屬性到這個方法標簽。如果你希望一個方法是異步的,你可以添加一個asyncTask="true"屬性到這個方法的標簽里。注意這些方法必須不含有任何的'out'參數。
例如:

<node>
<interfacename="com.nokia.TextProcessorInterface">
<methodname="reverse" chainTask="true">
<arg name="message"type="s" direction="in"/>
<arg name=""type="s" direction="out"/>
</method>
<method name="blinkScreen"asyncTask="true">
<arg name="message"type="s" direction="in"/>
</method>
</interface>
</node>
運行dui-servicefwgen工具,產生相關.h和.cpp文件,命令如下:
-
修改你的代碼。
修改主要分為三個步驟,如下面的代碼段所示:

MyService myService;
//2.創建一個適配器去連接dbus和myService中的方法
//按照QDBusAbstractAdaptor(),它必須是創建在堆上的,
//并且內存是由QDBusAbstractAdaptor管理的,因此不需要保存指針
new MyServiceIfAdaptor( &myService );
//3.連接到會話并注冊這個服務
QDBusConnection connection =QDBusConnection::sessionBus();
boolret=connection.registerService("com.nokia.TextProcessor");
//繼續程序剩余的部分編寫
return app.exec();
接口
定義一個接口有三個步驟:
-
創建一個定義接口的XML文件與上面描述的是同一個XML文件.
-
運行dui-servicefwgen這個工具,產生.h和.cpp文件,命令如下:
- 需要產生服務相關的庫.
以上的文件需要被放進maemo-interfaces包,庫需要包含在maemo-interfaces里面,頭文件和XML文件也需要包含在maemo-interfaces-dev中。
接口和方法的文檔說明可以加在'<doc>''</doc>'之間,例如:

<doc>
<argtag="brief">brief documentation for the interface</arg>
<argtag="details">detailed documentation for theinterface</arg>
</doc>
<method name="showPage">
<doc>
<argtag="brief">brief documentation for showPage()method</arg>
<argtag="details">detailed documentation for showPage()method</arg>
</doc>
<arg name="targetPage"type="s" direction="in" />
<arg name="previousPage"type="s" direction="in" />
<arg name="" type="b"direction="out"/>
</method>
....etc
作為一個服務使用者
-
安裝libdui-dev debian包,它會提供給你服務映射dbus守護進程,頭文件和庫文件。
-
安裝maemo-interfaces-dev包(包含代理頭、庫和封裝包的頭文件)
-
添加-ldui和-l<接口名字>到你工程文件的LIBS中。
-
在你的源文件中,包含這個接口頭文件,接著創建一個接口實例,然后調用serviceName()方法去得到這個接口的提供者
-
通過'isValid()'方法確認這個服務是否可用。
-
調用想要用的接口方法。
-
實現并連接slots以處理有服務映射器發送出來'serviceAvailable()','serviceUnavailable()' 和'serviceChanged()'這些signals
演示和代碼例子
在libdui/demos/servicefw/中,有個例子示范了3個服務提供者和一個服務使用者。com.nokia.textprocessor和org.maemo.textprocessor服務都實現了相同的接口-com.nokia.TextProcessorInterface.因為有2個服務,所以我們可以嘗試去移除服務,然后觀察服務用戶從一個服務轉換到另一個。有一個腳本工具/dui-servicefwgen,這個腳本工具被用來產生源文件,這些源文件是被用來給服務用戶定義接口的。下面開始運行這個演示:
-
cd libdui
-
qmake && make && make instal(或者在duiservicemapper目錄中至少執行一個make iinstall的操作)
-
cd demos/servicefw
-
pushd misc; sudo ./INSTALL; popd(這個操作將把dbus服務的相關文件安裝到/usr/share/dbus-1/services目錄中)
-
LD_LIBRARY_PATH=lib bin/user
-
這一步將打開一個小窗口允許你輸入字符,這些字符將通過接口發送到一個服務中,而服務將返回被反轉后的字符。
在這個演示中,你可以從/usr/share/dbus-1/services中移除若干個服務去模擬服務被移除的情況(然后再添加),以此來驗證服務使用者程序是否能執行正確的操作。