• 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.


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.

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 voipde 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"

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"

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"

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"

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>