新建PJSIP類 - 基于Android的VoIP系統設計
為各個待實現的類新建一個包,可以命名為“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接口的實現,限于篇幅,本文只講解幾個重要函數的實現。
(1)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。
(2)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()”,將發起會話。
(3)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服務器為目的地址,注冊會話發起申請,經過一系列的操作之后,與目的地址發起會話。
- 第 1 頁:基于Android的VoIP系統設計
- 第 2 頁:新建PJSIP類
- 第 3 頁:主程序與用戶界面
本文導航
非常好我支持^.^
(1) 100%
不好我反對
(0) 0%
相關閱讀:
- [電子說] 社區說|多才多藝: 探索 Android 應用更多可能 2023-10-24
- [電子說] 浩辰軟件正式登陸上交所科創板 2023-10-23
- [電子說] 鴻蒙原生應用,對開發者意味著什么? 2023-10-22
- [電子說] Android端自定義鈴聲 MobPush對安卓端自定義鈴聲的教程 2023-10-21
- [電子說] Android推送問題排查技巧 針對MobPush安卓端推送問題的解決辦法 2023-10-21
- [電子說] 如何使用Proxyman抓取Android的https請求? 2023-10-19
- [編程語言及工具] 基于OkHttp 3.10.0的源碼案例解析 2023-10-17
- [電子說] 基于MacroBenchmark的性能測試量化指標方案 2023-10-17
( 發表人:Spring )