Share via Share via... Twitter LinkedIn Facebook Pinterest Telegram WhatsApp Yammer Reddit TeamsRecent ChangesSend via e-MailPrintPermalink × Table of Contents Llamadas voice over IP Implementación Funciones de registro CreateProfile SetPassword SetProtocol SetPort SetSendKeepAlive SetOutboundProxy SetDisplayName SetProfileName AddProfile RegisterProfile UnRegisterProfile SetRingtone Funciones de llamada saliente MakeVoIPCall Funciones de llamada entrante AnswerVoIPCall Funciones de llamada HangVoIPCall SendDTMF EJEMPLO Llamadas voice over IP Esta función sólo está disponible en el framework Android. La versión del sistema operativo debe ser Android 2.3.X (Gingerbread) o superior. A la hora de desarrollar, es conveniente estar atento a los mensajes del logcat que vienen bajo el tag “xonevoip” y “sipmanager”, para solucionar errores. Implementación Para empezar, descargamos e instalamos el módulo de llamadas xonevoip desde xonesupport. Como las llamadas telefónicas son algo que se puede recibir en cualquier momento, usamos un objeto global como pueden ser las variables user(“”). Para ello, usamos createobject(“xonevoip”) y se lo asignamos a algo como MAP_VOIP. Si las funciones voip no están soportadas en este terminal, al crear el objeto saltará una excepción y mostrará un mensaje de aviso por pantalla. Necesitamos también definir en el nodo <app> de la aplicación el atributo phone-coll=“coleccionllamadaentrante”, que se llamará automáticamente cuando se reciba una llamada desde ese perfil y que debe contener, como mínimo, los botones de colgar y descolgar la llamada. La idea bajo esta implementación, es que el desarrollador cree los botones para hacer llamadas, recibirlas o registrarse con el servidor, y que diseñe una pantalla de llamadas a su gusto. Por ejemplo, se puede hacer que se registre al loguearse en la aplicación con los datos que se saquen de la base de datos y que haya una opción en algún menú para hacer las llamadas. Para las pruebas, se puede montar un servidor Asterisk® o usar algún proveedor gratuito como IPTel. A continuación se describen las funciones y más abajo se muestra un ejemplo de uso completo. Funciones de registro CreateProfile Nombre createprofile(usuario, servidor) Parámetro Descripción usuario Nombre de usuario de la cuenta SIP. servidor Dominio del servidor SIP. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").CreateProfile "usuario", "servidor.org" SetPassword Nombre setpassword(password) Parámetro Descripción password Define la contraseña de la cuenta SIP. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetPassword "pass" SetProtocol Nombre setprotocol(protocolo) Parámetro Descripción protocolo Protocolo para conectarse al servidor. Casi siempre es UDP. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetProtocol "UDP" SetPort Nombre setport(puerto) Parámetro Descripción puerto Puerto al que conectarse del servidor. Casi siempre es 5060. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetPort 5060 SetSendKeepAlive Nombre setsendkeepalive(keepalive) Parámetro Descripción keepalive Define si se debe enviar un paquete de keepalive al servidor. Puede ser true o false. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetSendKeepAlive "true" SetOutboundProxy Nombre setoutboundproxy(direccion) Parámetro Descripción direccion IP o dominio del servidor proxy para las llamadas salientes, si fuera necesario. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetOutboundProxy "212.212.212.212" SetDisplayName Nombre que se ve al hacer una llamada. Lo proporciona el proveedor voip Nombre setdisplayname(nombre) Parámetro Descripción nombre Nombre que se mostrará. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetProfileName "Test VoIP 01" SetProfileName Define el nombre del perfil que se puede ver en los ajustes de cuentas voip de Android. Nombre setprofilename(nombre) Parámetro Descripción nombre Nombre interno del perfil. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetProfileName "Test VoIP 01" AddProfile Da por válidos el resto de ajustes y crea el perfil. Nombre addprofile() Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").AddProfile RegisterProfile Una vez creado el perfil, lo registra para poder recibir llamadas. Nombre registerprofile() Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").RegisterProfile UnRegisterProfile Esta llamada desactiva el perfil y no deja pasar ni recibir llamadas. Según la versión de Android, esta llamada puede ser ignorada. [TODO] Nombre unregisterprofile() Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").UnRegisterProfile SetRingtone Nombre setringtone(fichero) Parámetro Descripción fichero Nombre del fichero de sonido que se reproducirá al recibir una llamada desde este perfil. Puede ser .WAV, .MP3 o lo que sea capaz de reproducir el terminal. Se recomienda usar un .WAV no demasiado pesado. Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SetRingtone "ringtone.mp3" Funciones de llamada saliente MakeVoIPCall Nombre makevoipcall(direccionsip) Parámetro Descripción direccionsip Dirección a la cual hacer la llamada Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").MakeVoIPCall "test@servidorsip.com" Funciones de llamada entrante AnswerVoIPCall Responde a la llamada entrante. Nombre answervoipcall() Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").MakeVoIPCall "test@servidorsip.com" Funciones de llamada HangVoIPCall Cuelga la llamada, se haya establecido o no. Nombre answervoipcall() Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").HangVoIPCall SendDTMF Envía tonos DTMF en la llamada activa. No suele funcionar, pues sólo existe un codec voip capaz de transportar esta clase de tonos en modo “in-band” (G711) y no es habitual en proveedores voip. Nombre senddtmf(numero) Parámetro Descripción numero Cadena con el número a enviar. Valores posibles: 0123456789ABCD Valor devuelto 0 si OK, -1 si error. Ejemplo de uso: user("MAP_VOIP").SendDTMF "1234" EJEMPLO Este es un ejemplo en plan “Walkie-Talkie”. Para usarlo cojemos dos teléfonos, en uno cargamos el primer mappings y en el otro el segundo. Perfil #1: <?xml version="1.0" encoding="iso-8859-1"?> <xml> <app prefix="gen" version="0.0.0.164" entry-point="TEST" autologon="true" phone-coll="LlamadaEntrante"> <!-- <style url="default.css"> <style url="default_hor.css" conditions="phone:horizontal"/> <style url="default_tablet.css" conditions="tablet:vertical"/> <style url="default_hor.css" conditions="tablet:horizontal"/> --> </app> <collprops type="general"> <coll name="Empresas" title="la empresa" sql="SELECT t1.ID,t1.CODIGO FROM ##PREF##Empresa t1" shadow="false" objname="Empresa" updateobj="Empresa" progid="ASGestion.CASEmpresa" fontsize="9" nomenmask="8" editwidth="101" editheight="97" filter="" sort=""> <group name="General" id="1" /> <prop name="CODIGO" visible="3" group="1" type="N" fieldsize="4" autosearch="true" /> </coll> <coll name="Usuarios" title="el usuario" sql="SELECT t1.ID,t1.IDEMPRESA,t1.LOGIN,t1.PWD,t1.NOMBRE FROM ##PREF##Usuarios t1" shadow="false" objname="Usuarios" updateobj="Usuarios" progid="ASGestion.CASUser" dropdown="true" editwidth="101" editheight="97" fontsize="9" filter="" sort=""> <group name="General" id="1" /> <prop name="IDEMPRESA" group="1" visible="0" type="N" mapcol="Empresas" mapfld="ID" /> <prop name="LOGIN" visible="3" group="1" type="T" fieldsize="10" fixed-text="true" size="10" /> <prop name="PWD" group="1" type="T" fieldsize="10" fixed-text="true" size="10" visible="" /> <prop name="NOMBRE" visible="3" group="1" type="T" fieldsize="30" fixed-text="true" size="30" /> <prop name="USERTYPE" visible="1" group="1" type="T" fieldsize="30" fixed-text="true" size="50" /> <create> <action name="setval" field="IDEMPRESA" value="##ENTID##" /> </create> </coll> <coll name="Empresas" title="la empresa" sql="SELECT t1.ID,t1.CODIGO FROM ##PREF##Empresa t1" shadow="false" objname="Empresa" updateobj="Empresa" progid="ASGestion.CASEmpresa" fontsize="9" nomenmask="8" editwidth="101" editheight="97" filter="" sort=""> <group name="General" id="1" /> <prop name="CODIGO" visible="3" group="1" type="N" fieldsize="4" autosearch="true" /> </coll> <coll name="Usuarios" title="el usuario" sql="SELECT t1.ID,t1.IDEMPRESA,t1.LOGIN,t1.PWD,t1.NOMBRE FROM ##PREF##Usuarios t1" shadow="false" objname="Usuarios" updateobj="Usuarios" progid="ASGestion.CASUser" dropdown="true" editwidth="101" editheight="97" fontsize="9" filter="" sort=""> <group name="General" id="1" /> <prop name="IDEMPRESA" group="1" visible="0" type="N" mapcol="Empresas" mapfld="ID" /> <prop name="LOGIN" visible="3" group="1" type="T" fieldsize="10" fixed-text="true" size="10" /> <prop name="PWD" group="1" type="T" fieldsize="10" fixed-text="true" size="10" visible="" /> <prop name="NOMBRE" visible="3" group="1" type="T" fieldsize="30" fixed-text="true" size="30" /> <prop name="USERTYPE" visible="1" group="1" type="T" fieldsize="30" fixed-text="true" size="50" /> <create> <action name="setval" field="IDEMPRESA" value="##ENTID##" /> </create> </coll> <coll name="LlamadaEntrante" fontsize="8" title="TEST" objname="TEST" updateobj="TEST" progid="ASData.CASBasicDataObj" sql="SELECT t1.ID FROM ##PREF##TEST t1" filter="" sort="" notab="true"> <group name="General" id="1" /> <frame id="aaa" name="aaa" width="100%" height="100%" /> <prop frame="aaa" name="MAP_TITULO02" type="TL" group="1" title="Llamada entrante!" width="100%" height="15%" labelwidth="10" /> <prop frame="aaa" name="MAP_HANG02" type="B" group="1" title="Colgar" method="ExecuteNode(hang)" width="100%" height="20%" labelwidth="10" /> <prop frame="aaa" name="MAP_RECIBIR02" type="B" group="1" title="Recibir" method="ExecuteNode(recibir)" width="100%" height="20%" labelwidth="10" /> <prop frame="aaa" name="MAP_DTMF02" type="B" group="1" title="Enviar DTMF prueba" method="ExecuteNode(dtmf)" width="100%" height="20%" labelwidth="10" /> <prop frame="aaa" name="MAP_SALIR02" type="B" group="1" title="Salir" method="ExecuteNode(salir)" width="100%" height="20%" labelwidth="10" /> <salir> <action name="runscript" type="runscript"> <script language="VBScript"> appdata.FailWithMessage -11888, "##EXITAPP##" </script> </action> </salir> <recibir> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").AnswerVoIPCall </script> </action> </recibir> <dtmf> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").SendDTMF "123456789" </script> </action> </dtmf> <hang> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").HangVoIPCall appdata.FailWithMessage -11888, "##EXITAPP##" </script> </action> </hang> </coll> <coll name="TEST" fontsize="8" title="TEST" objname="TEST" updateobj="TEST" progid="ASData.CASBasicDataObj" sql="SELECT t1.ID FROM ##PREF##TEST t1" filter="" sort="" notab="true"> <group name="General" id="1" /> <frame id="aaa" name="aaa" width="100%" height="100%" /> <prop frame="aaa" name="MAP_REGISTRARPERFIL01" type="B" group="1" title="Registrar con perfil #1" method="ExecuteNode(registrarperfil01)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_LLAMARPERFIL02" type="B" group="1" title="Llamar a perfil #2" method="ExecuteNode(llamarperfil02)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_HANG" type="B" group="1" title="Colgar" method="ExecuteNode(hang)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_UNREGISTER" type="B" group="1" title="Unregister" method="ExecuteNode(unregister)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_SALIR" type="B" group="1" title="Salir" method="ExecuteNode(salir)" width="100%" height="14%" labelwidth="10" /> <salir> <action name="runscript" type="runscript"> <script language="VBScript"> appdata.FailWithMessage -11888, "##EXITAPP##" </script> </action> </salir> <registrarperfil01> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP") = CreateObject("XOneVoIP") user("MAP_VOIP").CreateProfile "usuario", "iptel.org" user("MAP_VOIP").SetRingtone "testring.mp3" user("MAP_VOIP").SetPassword "contraseña" user("MAP_VOIP").SetProtocol "UDP" user("MAP_VOIP").SetPort 5060 user("MAP_VOIP").SetProfileName "Test VoIP 01" user("MAP_VOIP").AddProfile user("MAP_VOIP").RegisterProfile </script> </action> </registrarperfil01> <recibir> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").AnswerVoIPCall </script> </action> </recibir> <dtmf> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").SendDTMF "123456789" </script> </action> </dtmf> <llamarperfil02> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").MakeVoIPCall "direccionperfil2@iptel.org" </script> </action> </llamarperfil02> <hang> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").HangVoIPCall </script> </action> </hang> <unregister> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").UnRegisterProfile </script> </action> </unregister> </coll> </collprops> </xml> Perfil #2: <?xml version="1.0" encoding="iso-8859-1"?> <xml> <app prefix="gen" version="0.0.0.164" entry-point="TEST" autologon="true" phone-coll="LlamadaEntrante"> <!-- <style url="default.css"> <style url="default_hor.css" conditions="phone:horizontal"/> <style url="default_tablet.css" conditions="tablet:vertical"/> <style url="default_hor.css" conditions="tablet:horizontal"/> --> </app> <collprops type="general"> <coll name="Empresas" title="la empresa" sql="SELECT t1.ID,t1.CODIGO FROM ##PREF##Empresa t1" shadow="false" objname="Empresa" updateobj="Empresa" progid="ASGestion.CASEmpresa" fontsize="9" nomenmask="8" editwidth="101" editheight="97" filter="" sort=""> <group name="General" id="1" /> <prop name="CODIGO" visible="3" group="1" type="N" fieldsize="4" autosearch="true" /> </coll> <coll name="Usuarios" title="el usuario" sql="SELECT t1.ID,t1.IDEMPRESA,t1.LOGIN,t1.PWD,t1.NOMBRE FROM ##PREF##Usuarios t1" shadow="false" objname="Usuarios" updateobj="Usuarios" progid="ASGestion.CASUser" dropdown="true" editwidth="101" editheight="97" fontsize="9" filter="" sort=""> <group name="General" id="1" /> <prop name="IDEMPRESA" group="1" visible="0" type="N" mapcol="Empresas" mapfld="ID" /> <prop name="LOGIN" visible="3" group="1" type="T" fieldsize="10" fixed-text="true" size="10" /> <prop name="PWD" group="1" type="T" fieldsize="10" fixed-text="true" size="10" visible="" /> <prop name="NOMBRE" visible="3" group="1" type="T" fieldsize="30" fixed-text="true" size="30" /> <prop name="USERTYPE" visible="1" group="1" type="T" fieldsize="30" fixed-text="true" size="50" /> <create> <action name="setval" field="IDEMPRESA" value="##ENTID##" /> </create> </coll> <coll name="Empresas" title="la empresa" sql="SELECT t1.ID,t1.CODIGO FROM ##PREF##Empresa t1" shadow="false" objname="Empresa" updateobj="Empresa" progid="ASGestion.CASEmpresa" fontsize="9" nomenmask="8" editwidth="101" editheight="97" filter="" sort=""> <group name="General" id="1" /> <prop name="CODIGO" visible="3" group="1" type="N" fieldsize="4" autosearch="true" /> </coll> <coll name="Usuarios" title="el usuario" sql="SELECT t1.ID,t1.IDEMPRESA,t1.LOGIN,t1.PWD,t1.NOMBRE FROM ##PREF##Usuarios t1" shadow="false" objname="Usuarios" updateobj="Usuarios" progid="ASGestion.CASUser" dropdown="true" editwidth="101" editheight="97" fontsize="9" filter="" sort=""> <group name="General" id="1" /> <prop name="IDEMPRESA" group="1" visible="0" type="N" mapcol="Empresas" mapfld="ID" /> <prop name="LOGIN" visible="3" group="1" type="T" fieldsize="10" fixed-text="true" size="10" /> <prop name="PWD" group="1" type="T" fieldsize="10" fixed-text="true" size="10" visible="" /> <prop name="NOMBRE" visible="3" group="1" type="T" fieldsize="30" fixed-text="true" size="30" /> <prop name="USERTYPE" visible="1" group="1" type="T" fieldsize="30" fixed-text="true" size="50" /> <create> <action name="setval" field="IDEMPRESA" value="##ENTID##" /> </create> </coll> <coll name="LlamadaEntrante" fontsize="8" title="TEST" objname="TEST" updateobj="TEST" progid="ASData.CASBasicDataObj" sql="SELECT t1.ID FROM ##PREF##TEST t1" filter="" sort="" notab="true"> <group name="General" id="1" /> <frame id="aaa" name="aaa" width="100%" height="100%" /> <prop frame="aaa" name="MAP_TITULO02" type="TL" group="1" title="Llamada entrante!" width="100%" height="15%" labelwidth="10" /> <prop frame="aaa" name="MAP_HANG02" type="B" group="1" title="Colgar" method="ExecuteNode(hang)" width="100%" height="20%" labelwidth="10" /> <prop frame="aaa" name="MAP_RECIBIR02" type="B" group="1" title="Recibir" method="ExecuteNode(recibir)" width="100%" height="20%" labelwidth="10" /> <prop frame="aaa" name="MAP_DTMF02" type="B" group="1" title="Enviar DTMF prueba" method="ExecuteNode(dtmf)" width="100%" height="20%" labelwidth="10" /> <prop frame="aaa" name="MAP_SALIR02" type="B" group="1" title="Salir" method="ExecuteNode(salir)" width="100%" height="20%" labelwidth="10" /> <salir> <action name="runscript" type="runscript"> <script language="VBScript"> appdata.FailWithMessage -11888, "##EXITAPP##" </script> </action> </salir> <recibir> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").AnswerVoIPCall </script> </action> </recibir> <dtmf> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").SendDTMF "123456789" </script> </action> </dtmf> <hang> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").HangVoIPCall appdata.FailWithMessage -11888, "##EXITAPP##" </script> </action> </hang> </coll> <coll name="TEST" fontsize="8" title="TEST" objname="TEST" updateobj="TEST" progid="ASData.CASBasicDataObj" sql="SELECT t1.ID FROM ##PREF##TEST t1" filter="" sort="" notab="true"> <group name="General" id="1" /> <frame id="aaa" name="aaa" width="100%" height="100%" /> <prop frame="aaa" name="MAP_REGISTRARPERFIL02" type="B" group="1" title="Registrar con perfil #2" method="ExecuteNode(registrarperfil02)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_LLAMARPERFIL01" type="B" group="1" title="Llamar a perfil #1" method="ExecuteNode(llamarperfil01)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_HANG" type="B" group="1" title="Colgar" method="ExecuteNode(hang)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_UNREGISTER" type="B" group="1" title="Unregister" method="ExecuteNode(unregister)" width="100%" height="14%" labelwidth="10" /> <prop frame="aaa" name="MAP_SALIR" type="B" group="1" title="Salir" method="ExecuteNode(salir)" width="100%" height="14%" labelwidth="10" /> <salir> <action name="runscript" type="runscript"> <script language="VBScript"> appdata.FailWithMessage -11888, "##EXITAPP##" </script> </action> </salir> <registrarperfil02> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP") = CreateObject("XOneVoIP") user("MAP_VOIP").CreateProfile "contraseña", "iptel.org" user("MAP_VOIP").SetRingtone "testring.mp3" user("MAP_VOIP").SetPassword "contraseña" user("MAP_VOIP").SetProtocol "UDP" user("MAP_VOIP").SetPort 5060 user("MAP_VOIP").SetProfileName "Test VoIP 02" user("MAP_VOIP").AddProfile user("MAP_VOIP").RegisterProfile </script> </action> </registrarperfil02> <recibir> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").AnswerVoIPCall </script> </action> </recibir> <dtmf> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").SendDTMF "123456789" </script> </action> </dtmf> <llamarperfil01> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").MakeVoIPCall "direccionperfil1@iptel.org" </script> </action> </llamarperfil01> <hang> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").HangVoIPCall </script> </action> </hang> <unregister> <action name="runscript" type="runscript"> <script language="VBScript"> user("MAP_VOIP").UnRegisterProfile </script> </action> </unregister> </coll> </collprops> </xml>