《電子技術應用》
您所在的位置:首頁 > 通信與網絡 > 設計應用 > 基于Android的VoIP系統實現原理
基于Android的VoIP系統實現原理
OFweek電子工程網
摘要: 隨著我國三網融合的推進,VoIP與IPTV一起成為這一龐大工程的重要標志。而目前手機中,VoIP的解決方案并不是很多,特別是在Google公司推出的開源操作系統Android中。
Abstract:
Key words :

  0 引言

  VoIP" title="VoIP">VoIP(Voice over Internet Protocol)即首先數字化語音信號并壓縮成幀,轉換為IP數據包在網絡上傳輸,以此完成語音通話的業務,是一種利用IP協議傳輸語音數據的、新興的通信技術。

  隨著我國三網融合" title="三網融合">三網融合的推進,VoIP與IPTV(Interactive Personality TV)一起成為這一龐大工程的重要標志。而目前手機中,VoIP的解決方案并不是很多,特別是在Google公司推出的開源操作系統Android" title="Android">Android中。盡管該系統推出時間不長,憑借強大的功能、良好的界面、廣泛的商業支持,為用戶帶來很好的體驗,成為2010年最熱門且發展最快的手機操作系統。因此,兩者的結合,將是未來的發展趨勢。本文提出一種基于PJSIP協議棧的解決方案,通過Android本地開發工具(NDK),實現一個高效、穩定且功能強大的VoIP系統,具有較高的參考和實用價值。

  1 VoIP設計方案

  1.1 設計目標

  本方案所設計的系統包含以下功能:首先,完成用戶終端(如手機)中語音數據的采集與編碼,并通過RTP(實時傳輸協議)/RTCP(RTP傳輸控制協議)進行傳輸和控制;其次,完成會話的控制,包括會話的注冊、發起、維護與結束、注銷等;再次,作為一個應用程序,必須實現一個良好的界面,與用戶交互;最后,作為一個開放系統,需具有良好的可擴展性。

  1.2 總體設計

  本方案基本上符合Android的NDK框架的開發規范,將系統分為4層,如圖1所示。最上層為應用層,該層將在Android SDK的框架內,采用Java語言來實現;第二層為JNI層,SIP協議棧有很多種實現,其中,采用C語言的SIP協議棧在效率、速度、系統占用方面有著超越其他庫(如Java協議棧)的優勢,因此,該方案將在第三層采用純C語言實現的PJSIP協議棧。為了讓Java應用層能調用協議棧層,在兩層之間需要一個銜接的橋梁,這就是JNI層。最后一層是驅動層,這部分一般是由手機廠商來實現的,本文將不做重點介紹。

  

  2 VoIP的具體實現

  這里將實現一個完整的VoIP系統,包括協議棧的實現、JNI的編寫以及上層UI的設計實現等。

  2.1 SIP協議棧及UA

  SIP協議棧直接關系到整個系統的質量與效率,本文將采用純C語言開發的PJSIP庫。該庫采用C語言開發,且源碼開放,在兼容性與效率上有明顯優勢,不僅體積?。ㄍ暾腟IP封裝也不過150 KB),同時還實現了一個內存池,使得安全系數與運行效率大為提高,該系統所采用的就是優化后的PJSIP庫。

  2.1.1 PJSIP協議棧

  PJSIP協議棧遵循標準的SIP協議,采用分層架構:SIP/SDP消息編碼解析層、傳輸管理層、SIP終端、事務層、會話層以及應用層等。由于SIP協議采用文本消息發送請求和響應,所以首先需要將SIP消息按照巴斯克范式(ABNF)編碼和解析,這就是SIP/SDP消息編碼解析層所完成的功能。傳輸管理層用來管理用戶代理與服務器之間的請求和相應;SIP終端是PJSIP中轉機制的實現,它主要負責管理各個SIP組建,例如像SIP終端實例注冊組件,分發消息到事務層、會話層及應用層,回傳處理結果,管理定時器、I/O隊列等;事務層通過狀態機機制管理SIP信令,每一次狀態機狀態的改變都將觸發回調函數;會話層負責會話的發起與響應,一般與應用層結合在一起,用于用戶交互,不同的平臺有不同的實現,本文使用Andriod的GUI來實現。

  PJSIP是一個高度封裝的庫,實際上它是通過PJSUA子庫來實現應用的。一個完整的PJSUA生命周期,首先需要初始化,通過函數init()來實現。在這個函數中,將創建代理、初始化變量和堆棧,以及創建一個UDP傳輸并在最后啟動代理;第二步將為UA添加用戶,如果需要的話,還要向服務器注冊用戶;當用戶添加成功后,此時可以建立一個呼叫連接,發起會話;當會話連接成功后,就可以使用SRTP協議實時傳輸加密后的數據,進行通話。最后的過程是掛起或銷毀呼叫。

  2.1.2 UA原理

  UA(User Agency)是協議棧的具體實現,PJSIP通過封裝了的PJSUA來實現,在這一點上,大部分的SIP庫都大同小異,在此將介紹UA的工作原理。

  一個典型的UA包含UAC(User Agency Client)和UAS(User Agency Server)兩部分。會話由UAC發起。當呼叫發起時,UAC將首先發送“IN-VITE”消息給SIP代理服務器,服務器收到“INVITE”消息后將返回一個應答“200 OK”,并回答“ACK”進行確認,同時通知主叫用戶(即會話發起用戶)上線通話。如果主叫端(用戶端)主動結束會話,UAC將返回“BYE”消息,同時通知服務器;如果用戶端收到服務器傳來的“BY-E”消息,回答“200”,并結束會話。

  服務器端,UAS收到UAC(用戶端)發來的“INVITE”消息,首先從消息中提取出主、被叫對象,然后檢查當前是否有空閑信道,若沒有則返回“486 BUSY HERE”(即系統忙)消息;接著將檢查被叫用戶是否在服務區,如果被叫對象不在服務范圍,則返回“404 NOT FOUND”(即用戶不在服務區);若被叫用戶成功上線,則返回“200 OK”,同時準備開始會話。

  SIP協議棧一般使用SIP統一資源定位符(URL)來標識,它根據URL來尋址,如集群用戶“200”,“300”分別對應SIP用戶為“200@192.168. 1.100”,“300@192.168.1.100”。本文中也使用這種方式來測試通信。

  2.2 JNI的實現

  PJSIP庫和Java類連接是通過JNI來實現的,這也是Android NDK的實現機制,JNI是SUN公司推出的用于Java調用其他語言的接口。

  首先需要一個中間類,這個類中主要建立一些方法用于調用C/C++本地函數。它們的類型均為“publicstatic native int”,以便其他的Java類能夠調用。

  2.2.1 新建PJSIP類

  為各個待實現的類新建一個包,可以命名為“com.android.VoIP.pjsip”,在該包中添加該系統相關的一些類,主要有如下6個類:

  

  這些類分別為上節中原理各個步驟的實現。這部分僅僅是為C庫的調用提供一個接口,因此具體的實現將放在本地C/C++程序中。

  2.2.2 頭文件的生成

  C庫與Java間還需通過一個后綴為“.h”的頭文件來銜接,這個頭文件可以手動編寫,也可以通過“Javah”來生成,該工具包含在JDK中,是由SUN公司提供的。

  Javah生產的頭文件包含一定的規則,例如,本例中,它將生成的函數聲明為“Java_com_android_IMSandroid_pjsip_**”的形式,以便在調用C庫時能正確識別。

  由于Java中的數據類型與C/C++不盡相同,因此還必須注意參數傳遞時參數類型的轉換。本文所涉及到的Java數據類型有String和int型,Javah生成的頭文件中會先定義好需要傳遞的參數類型以及函數返回類型,例如方法“add_account(String sip_user,Stringsip_dom-ain,String sip_passwd)”,在頭文件中將定義函數的形式為“JNIEXPORT jint JNICALL Java_com_android_IMSandroid_pjsip_add_lac-count(JNIEnv*,jclass,jstring,jstring,jstring)”,其中JNIEXPORT為JNI外部函數聲明,jint是“jni.h”中定義C語言中整形的對應類型,JNCALL是JNI關鍵字。比較特殊的是JNIEnv,它是一個指向類型為JNIEnv_的一個特殊JNI數據結構的指針,它的每個元素都指向一個JNI函數的指針,jclass會根據引用Java類的不同而不同,本文中“pjsip.class”是靜態類,因此這里的jclass指的是類本身,如果是非靜態類則指的是對象。后面幾個就是pjsip類需要傳遞的參數,根據“jni.h”的定義,String類型對應jstring,int對應jint。然而這只是函數申明與類中方法的形式對應,參數的具體傳遞還需要相應的轉化,具體實現將在下一節詳細介紹。

  2.2.3 JNI接口函數的實現

  創建了pjsip庫類和頭文件之后,必須應用一個庫接口函數,這部分是pjsip接口的實現,限于篇幅,本文只講解幾個重要函數的實現。

 ?。?)init函數

  首先是init函數,對應的接口函數為JNICALL Java_com_android_IMSandroid_pjsip_init。該函數在系統初始化時調用,其作用是配置相關參數,并發起一個pjsua應用。它先通過函數“pjsua_create()”創建一個“pjsua”應用,然后通過三個函數“pjsua_config_default(&cfg)”,“pjsua_logging_config_default(&log_cfg”),“pjsua_media_config_default(&media_cfg)”配置其相關參數,其中cfg是pjsua的相關參數,主要是狀態改變時的回調函數;log_cfg用來配置log級別;media_cfg中包含時鐘頻率、聲道數目等相關參數。

  完成配置之后就可以使用pjsua_init(&cfg,&log_cfg,&media_cfg)將先前配置的參數初始化。在初始化之后,還需為pjsua添加一個udp傳輸,這一步是通過pjsua_transport_create(PJSIP_TRANSPORT_UDP,&cfg,NULL)來實現的,cfg中包含指定的通訊端口,3GPP建議使用5060。

  需要注意的是,配置完以上參數之后,還需指定SPEEX編碼優先級,一般將其設為最大,可以通過函數pisua_codec_set_priority(&-speex_codec_id,255)來實現。所有配置完成之后,就可以發起pjsua,即最后調用pjsua_start()。成功的話,本函數的返回類型為PJ_SUCCESS。

 ?。?)make_call函數

  另一個很重要的函數是make_call,其在本接口文件中對應的函數為Java_com_Android_IMSandroid_pjsip_make_lcall,這個函數一般在發起會話時調用,它與上一個函數在結構上最大的不同在于本函數需要傳遞一個字符串參數,前面提到,Java與C/C++在參數結構上并不完全相同,因此這里需要將Java傳遞過來的String類型的參數轉化,可以通過“url_ptr=(char*)env-》GetStringUTFChars(url,&iscopy)”來實現。env-》GetStringUTFChars在“jni.h”中定義,其功能是將jsting類型(Java)的url復制到char*類型(C)的url_ptr中,以此來完成參數類型的轉換。

  為了保證傳遞地址的有效性,還需要使用pjsua_verify_sip_url(url_ptr)驗證,這個函數主要驗證url_ptr是符合SIP的規則,即是否是一個合法的SIP地址。然而char*型的地址pjsua中還是不能直接使用的,這是因為pjsua重新封裝了參數類型,所以最后還需要將其轉化成pj_ str_t類型,pjlib提供pj_str()函數可以完成轉化。在完成了參數的轉化后,調用“pjsua_call_make_call()”,將發起會話。

 ?。?)hangup函數和pjsua_destroy函數

  這兩個函數用來銷毀和掛斷會話,一般在需結束的時候調用,它們在接口函數中對應Java_com_android_

  IMSandroid_pjsip_hangup和Java_com_android_IMSandroid_pjsip_destroy,由于沒有參數傳遞,也沒有其他的調用,因此這兩個函數非常簡單,基本上直接調用pjsua提供的pjsua_call_hangup_all()和pjsua_destroy()就能實現。pisua中這兩個函數將完成內存釋放、賬戶注銷等工作。

  (4)add_account函數

  該函數在基本的pjsua中并不是必須的,但如果要使用SIP服務器的話,就必須實現該函數,它在接口函數中對應“Java_com_android_I-MSandroid_pjsip_add_1account”,同“make_call”一樣,也需要傳遞參數,不同的是,它傳遞三個參數,只是原理大體一樣。

  首先它將參數轉化后保持到cfg,通過“pjsua_acc_add(&cfg,PJ_TRUE,&ace_id)”將參數添加到pjsua。pjsua將以其中的sip服務器為目的地址,注冊會話發起申請,經過一系列的操作之后,與目的地址發起會話。

  0 引言

  VoIP(Voice over Internet Protocol)即首先數字化語音信號并壓縮成幀,轉換為IP數據包在網絡上傳輸,以此完成語音通話的業務,是一種利用IP協議傳輸語音數據的、新興的通信技術。

  隨著我國三網融合的推進,VoIP與IPTV(Interactive Personality TV)一起成為這一龐大工程的重要標志。而目前手機中,VoIP的解決方案并不是很多,特別是在Google公司推出的開源操作系統Android中。盡管該系統推出時間不長,憑借強大的功能、良好的界面、廣泛的商業支持,為用戶帶來很好的體驗,成為2010年最熱門且發展最快的手機操作系統。因此,兩者的結合,將是未來的發展趨勢。本文提出一種基于PJSIP協議棧的解決方案,通過Android本地開發工具(NDK),實現一個高效、穩定且功能強大的VoIP系統,具有較高的參考和實用價值。

  1 VoIP設計方案

  1.1 設計目標

  本方案所設計的系統包含以下功能:首先,完成用戶終端(如手機)中語音數據的采集與編碼,并通過RTP(實時傳輸協議)/RTCP(RTP傳輸控制協議)進行傳輸和控制;其次,完成會話的控制,包括會話的注冊、發起、維護與結束、注銷等;再次,作為一個應用程序,必須實現一個良好的界面,與用戶交互;最后,作為一個開放系統,需具有良好的可擴展性。

  1.2 總體設計

  本方案基本上符合Android的NDK框架的開發規范,將系統分為4層,如圖1所示。最上層為應用層,該層將在Android SDK的框架內,采用Java語言來實現;第二層為JNI層,SIP協議棧有很多種實現,其中,采用C語言的SIP協議棧在效率、速度、系統占用方面有著超越其他庫(如Java協議棧)的優勢,因此,該方案將在第三層采用純C語言實現的PJSIP協議棧。為了讓Java應用層能調用協議棧層,在兩層之間需要一個銜接的橋梁,這就是JNI層。最后一層是驅動層,這部分一般是由手機廠商來實現的,本文將不做重點介紹。

  

  2 VoIP的具體實現

  這里將實現一個完整的VoIP系統,包括協議棧的實現、JNI的編寫以及上層UI的設計實現等。

  2.1 SIP協議棧及UA

  SIP協議棧直接關系到整個系統的質量與效率,本文將采用純C語言開發的PJSIP庫。該庫采用C語言開發,且源碼開放,在兼容性與效率上有明顯優勢,不僅體積?。ㄍ暾腟IP封裝也不過150 KB),同時還實現了一個內存池,使得安全系數與運行效率大為提高,該系統所采用的就是優化后的PJSIP庫。

  2.1.1 PJSIP協議棧

  PJSIP協議棧遵循標準的SIP協議,采用分層架構:SIP/SDP消息編碼解析層、傳輸管理層、SIP終端、事務層、會話層以及應用層等。由于SIP協議采用文本消息發送請求和響應,所以首先需要將SIP消息按照巴斯克范式(ABNF)編碼和解析,這就是SIP/SDP消息編碼解析層所完成的功能。傳輸管理層用來管理用戶代理與服務器之間的請求和相應;SIP終端是PJSIP中轉機制的實現,它主要負責管理各個SIP組建,例如像SIP終端實例注冊組件,分發消息到事務層、會話層及應用層,回傳處理結果,管理定時器、I/O隊列等;事務層通過狀態機機制管理SIP信令,每一次狀態機狀態的改變都將觸發回調函數;會話層負責會話的發起與響應,一般與應用層結合在一起,用于用戶交互,不同的平臺有不同的實現,本文使用Andriod的GUI來實現。

  PJSIP是一個高度封裝的庫,實際上它是通過PJSUA子庫來實現應用的。一個完整的PJSUA生命周期,首先需要初始化,通過函數init()來實現。在這個函數中,將創建代理、初始化變量和堆棧,以及創建一個UDP傳輸并在最后啟動代理;第二步將為UA添加用戶,如果需要的話,還要向服務器注冊用戶;當用戶添加成功后,此時可以建立一個呼叫連接,發起會話;當會話連接成功后,就可以使用SRTP協議實時傳輸加密后的數據,進行通話。最后的過程是掛起或銷毀呼叫。

  2.1.2 UA原理

  UA(User Agency)是協議棧的具體實現,PJSIP通過封裝了的PJSUA來實現,在這一點上,大部分的SIP庫都大同小異,在此將介紹UA的工作原理。

  一個典型的UA包含UAC(User Agency Client)和UAS(User Agency Server)兩部分。會話由UAC發起。當呼叫發起時,UAC將首先發送“IN-VITE”消息給SIP代理服務器,服務器收到“INVITE”消息后將返回一個應答“200 OK”,并回答“ACK”進行確認,同時通知主叫用戶(即會話發起用戶)上線通話。如果主叫端(用戶端)主動結束會話,UAC將返回“BYE”消息,同時通知服務器;如果用戶端收到服務器傳來的“BY-E”消息,回答“200”,并結束會話。

  服務器端,UAS收到UAC(用戶端)發來的“INVITE”消息,首先從消息中提取出主、被叫對象,然后檢查當前是否有空閑信道,若沒有則返回“486 BUSY HERE”(即系統忙)消息;接著將檢查被叫用戶是否在服務區,如果被叫對象不在服務范圍,則返回“404 NOT FOUND”(即用戶不在服務區);若被叫用戶成功上線,則返回“200 OK”,同時準備開始會話。

  SIP協議棧一般使用SIP統一資源定位符(URL)來標識,它根據URL來尋址,如集群用戶“200”,“300”分別對應SIP用戶為“200@192.168. 1.100”,“300@192.168.1.100”。本文中也使用這種方式來測試通信。

  2.2 JNI的實現

  PJSIP庫和Java類連接是通過JNI來實現的,這也是Android NDK的實現機制,JNI是SUN公司推出的用于Java調用其他語言的接口。

  首先需要一個中間類,這個類中主要建立一些方法用于調用C/C++本地函數。它們的類型均為“publicstatic native int”,以便其他的Java類能夠調用。

  2.2.1 新建PJSIP類

  為各個待實現的類新建一個包,可以命名為“com.android.VoIP.pjsip”,在該包中添加該系統相關的一些類,主要有如下6個類:

  

  這些類分別為上節中原理各個步驟的實現。這部分僅僅是為C庫的調用提供一個接口,因此具體的實現將放在本地C/C++程序中。

  2.2.2 頭文件的生成

  C庫與Java間還需通過一個后綴為“.h”的頭文件來銜接,這個頭文件可以手動編寫,也可以通過“Javah”來生成,該工具包含在JDK中,是由SUN公司提供的。

  Javah生產的頭文件包含一定的規則,例如,本例中,它將生成的函數聲明為“Java_com_android_IMSandroid_pjsip_**”的形式,以便在調用C庫時能正確識別。

  由于Java中的數據類型與C/C++不盡相同,因此還必須注意參數傳遞時參數類型的轉換。本文所涉及到的Java數據類型有String和int型,Javah生成的頭文件中會先定義好需要傳遞的參數類型以及函數返回類型,例如方法“add_account(String sip_user,Stringsip_dom-ain,String sip_passwd)”,在頭文件中將定義函數的形式為“JNIEXPORT jint JNICALL Java_com_android_IMSandroid_pjsip_add_lac-count(JNIEnv*,jclass,jstring,jstring,jstring)”,其中JNIEXPORT為JNI外部函數聲明,jint是“jni.h”中定義C語言中整形的對應類型,JNCALL是JNI關鍵字。比較特殊的是JNIEnv,它是一個指向類型為JNIEnv_的一個特殊JNI數據結構的指針,它的每個元素都指向一個JNI函數的指針,jclass會根據引用Java類的不同而不同,本文中“pjsip.class”是靜態類,因此這里的jclass指的是類本身,如果是非靜態類則指的是對象。后面幾個就是pjsip類需要傳遞的參數,根據“jni.h”的定義,String類型對應jstring,int對應jint。然而這只是函數申明與類中方法的形式對應,參數的具體傳遞還需要相應的轉化,具體實現將在下一節詳細介紹。

  2.2.3 JNI接口函數的實現

  創建了pjsip庫類和頭文件之后,必須應用一個庫接口函數,這部分是pjsip接口的實現,限于篇幅,本文只講解幾個重要函數的實現。

 ?。?)init函數

  首先是init函數,對應的接口函數為JNICALL Java_com_android_IMSandroid_pjsip_init。該函數在系統初始化時調用,其作用是配置相關參數,并發起一個pjsua應用。它先通過函數“pjsua_create()”創建一個“pjsua”應用,然后通過三個函數“pjsua_config_default(&cfg)”,“pjsua_logging_config_default(&log_cfg”),“pjsua_media_config_default(&media_cfg)”配置其相關參數,其中cfg是pjsua的相關參數,主要是狀態改變時的回調函數;log_cfg用來配置log級別;media_cfg中包含時鐘頻率、聲道數目等相關參數。

  完成配置之后就可以使用pjsua_init(&cfg,&log_cfg,&media_cfg)將先前配置的參數初始化。在初始化之后,還需為pjsua添加一個udp傳輸,這一步是通過pjsua_transport_create(PJSIP_TRANSPORT_UDP,&cfg,NULL)來實現的,cfg中包含指定的通訊端口,3GPP建議使用5060。

  需要注意的是,配置完以上參數之后,還需指定SPEEX編碼優先級,一般將其設為最大,可以通過函數pisua_codec_set_priority(&-speex_codec_id,255)來實現。所有配置完成之后,就可以發起pjsua,即最后調用pjsua_start()。成功的話,本函數的返回類型為PJ_SUCCESS。

 ?。?)make_call函數

  另一個很重要的函數是make_call,其在本接口文件中對應的函數為Java_com_Android_IMSandroid_pjsip_make_lcall,這個函數一般在發起會話時調用,它與上一個函數在結構上最大的不同在于本函數需要傳遞一個字符串參數,前面提到,Java與C/C++在參數結構上并不完全相同,因此這里需要將Java傳遞過來的String類型的參數轉化,可以通過“url_ptr=(char*)env-》GetStringUTFChars(url,&iscopy)”來實現。env-》GetStringUTFChars在“jni.h”中定義,其功能是將jsting類型(Java)的url復制到char*類型(C)的url_ptr中,以此來完成參數類型的轉換。

  為了保證傳遞地址的有效性,還需要使用pjsua_verify_sip_url(url_ptr)驗證,這個函數主要驗證url_ptr是符合SIP的規則,即是否是一個合法的SIP地址。然而char*型的地址pjsua中還是不能直接使用的,這是因為pjsua重新封裝了參數類型,所以最后還需要將其轉化成pj_ str_t類型,pjlib提供pj_str()函數可以完成轉化。在完成了參數的轉化后,調用“pjsua_call_make_call()”,將發起會話。

 ?。?)hangup函數和pjsua_destroy函數

  這兩個函數用來銷毀和掛斷會話,一般在需結束的時候調用,它們在接口函數中對應Java_com_android_

  IMSandroid_pjsip_hangup和Java_com_android_IMSandroid_pjsip_destroy,由于沒有參數傳遞,也沒有其他的調用,因此這兩個函數非常簡單,基本上直接調用pjsua提供的pjsua_call_hangup_all()和pjsua_destroy()就能實現。pisua中這兩個函數將完成內存釋放、賬戶注銷等工作。

 ?。?)add_account函數

  該函數在基本的pjsua中并不是必須的,但如果要使用SIP服務器的話,就必須實現該函數,它在接口函數中對應“Java_com_android_I-MSandroid_pjsip_add_1account”,同“make_call”一樣,也需要傳遞參數,不同的是,它傳遞三個參數,只是原理大體一樣。

  首先它將參數轉化后保持到cfg,通過“pjsua_acc_add(&cfg,PJ_TRUE,&ace_id)”將參數添加到pjsua。pjsua將以其中的sip服務器為目的地址,注冊會話發起申請,經過一系列的操作之后,與目的地址發起會話。

  2.2.4 主程序與用戶界面

  系統的主程序是一個標準的Android應用程序,它使用Java語言開發,符合SDK規范。與一般的SDK程序不同的是,該類中必須使用Syst-em.loadLibrary加載PJSIP庫文件。形式如下:

  System.loadLibrary(“pjsip-jni”);

  其中,pjsip-jni就是上節中PJSIP協議棧生成的庫。

  主程序中的基本方式均按照上節中的過程,創建并初始化PJSUA;當call按鍵被觸發時發起會話,調用make-call()方法;當用戶接受通話時,點擊hang或cancel按鍵,觸發hang()或采用destry()方法等。

  用戶接口是通過Android SDK來實現的,這部分幾乎全都是Java語言,由于UI不是本文的重點,因此只介紹一個簡單的界面,實際應用中用戶交互是非常重要的。為了實現所需的功能,至少需要一個文本框來提供SIP地址,以及兩個按鍵來控制會話發起和結束。另外,在呼叫與通話過程中,還需要一個頁面來顯示,這里可以通過對話框來顯示,最后的界面如圖2所示。

  

  3 封裝與調試

  為了能在Android平臺上方便地使用該系統,在實現了PJSIP協議棧、JNI接口以及UI之后,還需將上面所有的模塊進行封裝。Android SDK提供了一些很有用的工具,如aapt等,由于本文重點不在AndriodSDK,所以可以采用集成開發工具(如集成在Eclipse中的ADT)來封裝。在工程libs(如果不存在則新建)目錄下新建一個名為armeabi的目錄,將上節生成的.so庫文件放到該目錄下。ADT在封裝資源時會自動將該庫文件封裝到apk文件中,apk是Android操作系統中應用程序的封裝形式,在所有android平臺中均能使用。

  封裝后安裝到Android手機、MID或虛擬機中,并發起會話。與開源SIP軟件Linphone通信的結果如圖2所示。

  4 結語

  通過測試表明,該系統能夠對發起并很好地控制SIP信令,該系統由于采用SIP協議,因此與所有采用這一協議的軟件均能通信,如Lin-phone,Kphone等,功能測試中表現良好,實現了VoIP的基本需求。同時如果要增加功能,可以在Java類中添加相應的方法并在應用層調用即可,具有一定的可擴展性。

  由于手機等手持設備在規格和配置上的差異,該系統在具體的設備上使用時,界面略有不同,但是同系統架構的手機使用時并不影響功能,在HTC Desire和MOTO Milestone上測試均能正常使用。但是,當移植到不同的架構時(即使同時ARM架構),仍需做一定的優化,一般采取主流平臺的多種版本方式來解決,這也是所有多廠商移動設備上一個無法避免的問題。

此內容為AET網站原創,未經授權禁止轉載。
热re99久久精品国产66热_欧美小视频在线观看_日韩成人激情影院_庆余年2免费日韩剧观看大牛_91久久久久久国产精品_国产原创欧美精品_美女999久久久精品视频_欧美大成色www永久网站婷_国产色婷婷国产综合在线理论片a_国产精品电影在线观看_日韩精品视频在线观看网址_97在线观看免费_性欧美亚洲xxxx乳在线观看_久久精品美女视频网站_777国产偷窥盗摄精品视频_在线日韩第一页
  • <strike id="ygamy"></strike>
  • 
    
      • <del id="ygamy"></del>
        <tfoot id="ygamy"></tfoot>
          <strike id="ygamy"></strike>
          最新精品在线| 激情成人综合网| 欧美体内谢she精2性欧美| 久久精品伊人| 亚洲午夜国产一区99re久久| 另类专区欧美制服同性| 久久久天天操| 欧美视频在线免费看| 一本色道婷婷久久欧美| 欧美中文字幕在线播放| 欧美激情中文不卡| 中日韩视频在线观看| 亚洲国产精品精华液2区45| 久久久一区二区三区| 午夜在线视频观看日韩17c| 欧美成人一区二区在线| 亚洲午夜91| 午夜视频在线观看一区二区三区| 一区二区三区不卡视频在线观看| 一本色道综合亚洲| 制服丝袜亚洲播放| 伊人久久综合| 国产欧美日韩精品在线| 国产一区二区三区四区在线观看| 一区二区自拍| 欧美三级乱码| 欧美黄色aa电影| 亚洲美女区一区| 国产一区二区丝袜高跟鞋图片| 欧美一级视频免费在线观看| 亚洲精品日韩久久| 久久嫩草精品久久久久| 亚洲亚洲精品在线观看| 久久www免费人成看片高清| 免费人成精品欧美精品| 国产一区二区黄| 欧美一区91| 欧美日韩国产不卡| 欧美日韩精品不卡| 久久噜噜亚洲综合| 久久久久久有精品国产| 在线性视频日韩欧美| 精东粉嫩av免费一区二区三区| 国产精品视频xxx| 一本久道久久综合狠狠爱| 亚洲一级在线观看| 国产精品久久久久77777| 好吊成人免视频| 亚洲影视综合| 亚洲高清毛片| 欧美日韩综合在线免费观看| 国产免费成人av| 欧美日精品一区视频| 亚洲黑丝一区二区| 亚洲第一网站免费视频| 国产区日韩欧美| 欧美激情一二区| 国产精品高潮呻吟久久av无限| 亚洲久久一区二区| 1000部精品久久久久久久久| 欧美一二三区精品| 国产精品久久婷婷六月丁香| 亚洲无线一线二线三线区别av| 国产精品免费视频xxxx| 亚洲电影免费在线观看| 亚洲欧美网站| 蜜桃av一区二区三区| 国语精品中文字幕| 欧美电影在线免费观看网站| 久久久久成人精品| 好吊成人免视频| 久久久最新网址| 国产日韩欧美综合精品| 国产一区二区三区久久悠悠色av| 欧美一区二区视频观看视频| 在线视频亚洲一区| 欧美成人有码| 亚洲精华国产欧美| 欧美插天视频在线播放| 国产婷婷色一区二区三区| 这里只有精品丝袜| 欧美一级成年大片在线观看| 黄色精品一区二区| 国产精品日本欧美一区二区三区| 亚洲免费小视频| 午夜精彩国产免费不卡不顿大片| 91久久中文字幕| 一本久久综合| 欧美丰满高潮xxxx喷水动漫| 在线成人av网站| 国产一区二区三区在线播放免费观看| 亚洲激情黄色| 欧美一区二区免费观在线| 欧美精品一区二区三区在线播放| 精品福利av| 亚洲欧美另类久久久精品2019| 国产精品一区二区三区观看| 久热成人在线视频| 欧美乱妇高清无乱码| 国产精品毛片在线看| 久久久爽爽爽美女图片| 亚洲一区在线免费观看| 国产精品久久久久久久久久妞妞| 亚洲精品乱码久久久久久蜜桃麻豆| 性欧美video另类hd性玩具| 欧美精品一区二区在线观看| 亚洲成色777777在线观看影院| 在线播放日韩专区| 久久国内精品自在自线400部| 国产精品进线69影院| 蘑菇福利视频一区播放| 亚洲一区二区高清视频| 国产一区久久久| 国产综合18久久久久久| 久久久久久伊人| 美女脱光内衣内裤视频久久网站| 午夜视频久久久| 国产欧美1区2区3区| 亚洲影院高清在线| 激情欧美一区| 久久人人97超碰人人澡爱香蕉| 亚洲黑丝在线| 亚洲在线视频一区| 欧美性感一类影片在线播放| 国产精品少妇自拍| 欧美一二三区在线观看| 久久精品国产第一区二区三区最新章节| 欧美一区二区三区的| 一区二区国产精品| 一本色道久久综合亚洲二区三区| 欧美一区二区成人| 在线观看日韩www视频免费| 在线不卡欧美| 亚洲国产精品热久久| 欧美va天堂在线| 欧美xx视频| 麻豆精品一区二区av白丝在线| 影音先锋日韩有码| 欧美日韩精品一区二区天天拍小说| 亚洲欧美另类久久久精品2019| 国产精品一区免费观看| 在线观看亚洲一区| 欧美激情精品久久久久久大尺度| 国产精品美女久久久久久免费| 亚洲午夜久久久久久久久电影网| 午夜精品一区二区三区电影天堂| 亚洲精品欧美日韩专区| 欧美在线视频导航| 美女亚洲精品| 午夜精品视频在线观看| 国产日韩欧美日韩大片| 国产精品久久看| 欧美丰满少妇xxxbbb| 欧美在线观看视频| 日韩视频免费| 久久精品1区| 99这里只有久久精品视频| 久久av在线看| 亚欧成人精品| 亚洲日本一区二区三区| 久久久久88色偷偷免费| 欧美一区二区在线视频| 在线观看成人av电影| 一本大道久久a久久精二百| 好吊一区二区三区| 欧美日韩1234| 国产日韩欧美在线一区| 国产精品日韩专区| 欧美一区三区二区在线观看| 久久综合狠狠综合久久综青草| 欧美一区在线视频| 黄色成人在线观看| 国产精品永久免费视频| 欧美精品一区二区三区在线看午夜| 欧美精品在线免费播放| 国产欧美精品久久| 亚洲图片欧洲图片av| 亚洲砖区区免费| 国产精品久久久久9999高清| 欧美日本韩国一区| 国产精品va在线播放我和闺蜜| 午夜国产一区| 久久se精品一区精品二区| 欧美日韩一级大片网址| 欧美 日韩 国产 一区| 欧美韩国日本一区| 欧美高清在线视频| 亚洲免费综合| 免费精品99久久国产综合精品| 亚洲欧洲在线免费| 久久亚洲春色中文字幕久久久| 久久久一二三| 国产精品白丝av嫩草影院| 国产一区高清视频| 在线播放精品| 国产精品日韩欧美| 欧美中文字幕在线视频| 午夜精品久久| 欧美一区二区三区四区在线观看地址| 国产精品夜色7777狼人| 欧美精品18videos性欧美| 国产精品爱啪在线线免费观看| 模特精品裸拍一区| 欧美视频日韩视频在线观看| 国产精品永久在线| 欧美高清视频| 久久精品综合| 久久在线免费视频| 欧美日韩一区在线| 欧美日韩1区2区3区| 亚洲影视中文字幕| 久久国产黑丝| 欧美中文在线字幕| 麻豆freexxxx性91精品| 国产精品免费看久久久香蕉| 国产精品―色哟哟| 在线观看av不卡| 亚洲欧洲日产国产综合网| 欧美性猛交xxxx乱大交退制版| 免费成人在线视频网站| 亚洲欧美日韩综合国产aⅴ| 亚洲国产天堂久久综合网| 欧美一区二区精美| 欧美亚州一区二区三区| 久久精品国产免费观看| 欧美日韩少妇| 国产精品视频免费| 亚洲精品一区二区三区不| 国产视频精品免费播放| 欧美人体xx| 欧美日韩国产一区精品一区| 伊甸园精品99久久久久久| 在线日韩中文| 欧美日韩另类一区| 一区二区三区黄色| 亚洲精品激情| 亚洲精品久久在线| 欧美视频免费在线| 久久久免费精品| 性欧美xxxx视频在线观看| 国产三区二区一区久久| 欧美高清在线精品一区| 久久久噜噜噜久久中文字幕色伊伊| 欧美揉bbbbb揉bbbbb| 亚洲一区日韩| 久久综合狠狠综合久久综合88| 国产精品久久久久三级| 99精品欧美一区| 亚洲高清网站| 欧美亚洲一级| 亚洲免费黄色| 久久成人久久爱| 99riav国产精品| 亚洲欧洲视频在线| 在线观看日韩| 在线日本高清免费不卡| 国产乱肥老妇国产一区二| 国产日韩在线看| 亚洲激情图片小说视频| 女女同性女同一区二区三区91| 国产欧美一区二区三区久久人妖| 欧美日韩美女在线| 国产精品久久久久77777| 裸体素人女欧美日韩| 久久久久国产一区二区| 鲁鲁狠狠狠7777一区二区| 欧美华人在线视频| 欧美日韩在线精品一区二区三区| 91久久精品国产| 欧美日本亚洲| 欧美另类久久久品| 国产免费观看久久| 欧美日韩国产精品一区| 亚洲激情婷婷| 亚洲欧洲一区二区在线观看| 久久视频在线看| 欧美日韩国产成人高清视频| 一区二区在线免费观看| 夜夜狂射影院欧美极品| 国产精品拍天天在线| 国产精品视频午夜| 欧美日韩国产限制| 久久视频国产精品免费视频在线| 亚洲福利精品| 亚洲神马久久| 亚洲国产日韩一区| 国产伦精品一区二区三区在线观看| 美女视频黄a大片欧美| 欧美三级乱码| 久久成人这里只有精品| 欧美视频网址| 亚洲视频一二三| 欧美午夜宅男影院| 在线成人免费视频| 亚洲中字黄色| 久久手机精品视频| 亚洲电影视频在线| 欧美日韩中国免费专区在线看| 日韩视频免费在线观看| 伊人精品久久久久7777| 欧美视频日韩| 久久久精品日韩欧美| 久久久久**毛片大全| 欧美凹凸一区二区三区视频| 欧美夜福利tv在线| 亚洲国产美女久久久久| 久久久综合香蕉尹人综合网| 久久精品国产99国产精品澳门| 亚洲男人第一av网站| 亚洲午夜激情免费视频| 狠狠干成人综合网| 国产一区二区成人| 亚洲免费观看高清完整版在线观看熊| 一区二区三区免费网站| 国产亚洲成av人在线观看导航| 午夜国产不卡在线观看视频| 久久本道综合色狠狠五月| 国产精品久久久久77777| 欧美激情一区二区三区不卡| 亚洲精品视频在线看| 亚洲一区二区高清视频| 欧美破处大片在线视频| 欧美色区777第一页| 嫩草国产精品入口| 欧美激情在线有限公司| 在线观看成人av电影| 欧美色一级片| 99国产精品久久久|