Mando a distancia; Tethering con Delphi XE7
El tema de Tethering, del que ya he hablado antes en el blog (Tethering, operaciones básicas), se incorporó a la versión XE6 de RAD Studio. Hasta ese momento podíamos utilizar esta característica para conectar aplicaciones y dispositivos utilizando Wifi.
Para esta nueva versión XE7 se a añadido la posibilidad de conexión mediante Bluetooth.
Además, a las características ya existentes de conexión wifi, se han añadido opciones para poder filtrar o discriminar los dispositivos a los que nos vamos a conectar a partir de máscaras para la IP o para la subred.
Como ya he comentado anteriormente, el Tethering es una característica que podemos utilizar (aunque se haya introducido en las últimas versiones de Delphi) no sólo en aplicaciones FireMonkey (tanto móviles como de escritorio) sino también, en aplicaciones ”antiguas” diseñadas con la VCL.
Contenido
INTRODUCCIÓN
La idea de esta entrada es repasar más ampliamente en las características de Tethering, de las que ya hablé anteriormente, y profundizar en las posibilidades de esta tecnología, utilizando un proyecto más complejo y completo que el que vimos en la introducción.
Para ello utilizaremos 2 aplicaciones diferentes. Una basada en la VCL y otra desarrollada con Firemonkey para dispositivos móviles.
PROYECTO VCL
Como proyecto VCL he recuperado un antiguo reproductor que comencé a realizar hace un tiempo y que tenía aparcado pendiente de acabar. Inicialmente está programado en Delphi 6 y debería compilar sin problemas en esta versión y en posteriores (hasta Delphi XE7) a excepción de las características que le he añadido con esta última, como son los estilos y la inclusión de App Tethering.
Las características básicas con las que cuenta son las siguientes:
-
Para la visualización y las funciones básicas utiliza BASS.DLL. La librería BASS, para los que no la conozcáis, es una librería de audio bastante potente, multiplataforma y libre para uso no comercial. Para más detalles podéis echarle un vistazo a la web.
-
Utiliza conexión a Internet y los componentes Indy para obtener información de la canción que está reproduciendo en cada momento. Para ello utiliza la información del propio fichero tal y como os mostré en una entrada anterior del blog titulada “Obtener información de una canción”. Todo ello se encapsula en una clase que utiliza Threads para no bloquear el programa principal mientras se hacen las consultas.
-
Utilizando las ultimas versiones de delphi, le he añadido soporte para estilos, de forma que se puede cambiar entre varios de ellos en ejecución.
Os adjunto alguna imagen del proyecto tal y como ha quedado y en el vídeo posterior lo veréis funcionando.
Al proyecto original (diseñado con Delphi 6/7) utilizando la VCL le he añadido código para poder utilizar Tethering y comunicarse con una aplicación móvil que hará las veces de «mando a distancia».
Lo primero es incluir los dos componentes nuevos e imprescindibles que nos permitirán trabajar con Tethering; Un TTetheringManager y un TTetheringAppProfile. El primero podríamos decir, que es el encargado de todo lo relacionado con la conexión entre dispositivos y el segundo el que controla todas las acciones y recursos que comparten las aplicaciones una vez que ya están conectadas.
Además de estos dos componentes (que son indispensables), vamos añadir Acciones y recursos a nuestra aplicación. Con ellos podremos completar todas las operaciones/comunicaciones que deseamos realizar entre ambos programas.
ACCIONES
El programa de por si, tiene unas acciones predefinidas propias de un reproductor (incluidas en un TActionList estándar), como son el PLAY, PAUSE, STOP, SIGUIENTE,… como se aprecian el la imagen derecha.
Lo que he hecho es «mapear» estas acciones en el componente TTetheringAppProfile como públicas y con la propiedad Kind a Shared. De esta forma podrán ser llamadas/invocadas desde otra aplicación conectada a esta, utilizando, por ejemplo, el método RunRemoteAction de la clase TTetheringAppProfile.
A la izquierda se puede ver una imagen de cómo está «mapeada» la acción PLAY del reproductor. De forma similar a esta se hace con el resto. Tiene asignado un nombre único “rPlay”, que será con el que se invoque y está asociada a la acción del programa ActionPlay.
Cuando desde el mando a distancia ejecutemos el siguiente código:
ttProfiler.RunRemoteAction(pInfo, 'rPlay'); |
Se ejecutará la acción ActionPlay definida en nuestro programa. Más adelante cuando hablemos del mando a distancia, repasaremos esto.
En cuanto a las acciones no hay que hacer nada más, tan simple como esto. Debemos/podemos “mapear” las acciones que necesitemos ejecutar utilizando el Inspector de objetos.
RECURSOS
Si utilizando las acciones podemos conseguir ejecutar comandos entre diferentes aplicaciones, utilizando recursos lo que vamos a conseguir es poder compartir información entre los programas que se están comunicando. Utilizando ambos, deberíamos poder hacer todo lo necesario.
En el componente TTetheringAppProfile (igual que con las acciones) vamos a definir los recursos que utilizaremos para enviar información al “Mando a distancia”.
En mi caso, he utilizado diferentes recursos para la información que deseo enviar desde el reproductor y que deseo que reciba el mando a distancia; Es decir, todo lo referente a la canción que se está reproduciendo en ese momento. De esta forma, definiré recursos para el título, el artista, género, duración de la canción, volumen,…
Todos ellos se irán actualizando en cada momento con la información actual de la reproducción.
Durante la ejecución de la aplicación (reproductor) lo único que tenemos que hacer es ir actualizando el valor de los recursos a medida que estos van cambiando. Cuando selecciono una canción nueva, modifico los recursos del Título, Artista, Longitud de la canción,… mientras que se está reproduciendo tendré que actualizar el recurso que posee la posición (en tiempo) de la canción o cuando cambio el volumen, el que mantiene este valor.
Para ello bastan unas líneas como estas:
// actualizar los recursos relacionados con la canción actual ttProfiler.Resources.FindByName('rTiempoTotal').Value := lblDuracion.Caption; ttProfiler.Resources.FindByName('rMaxCancion').Value := IntToStr(tbCancion.Max); ttProfiler.Resources.FindByName('rTiempoCancion').Value := lblPosition.Caption; ttProfiler.Resources.FindByName('rPosCancion').Value := IntToStr(tbCancion.Position); ttProfiler.Resources.FindByName('rMaxCancion').Value := IntToStr(tbCancion.Max); ... // Al modificar el volumen actualizamos el recurso ttProfiler.Resources.FindByName('rVolumen').Value := IntToStr(tbVolumen.Position); ... |
Aquí accedo a los recursos a partir de su nombre de forma única, utilizando FindByName, aunque también podría hacerlo utilizando la propiedad Items o FindItemID.
En este caso la estrategia que hemos escogido es definir unos recursos donde almacenaremos valores, disponibles para que otras aplicaciones los consulten.
Otra alternativa es enviar directamente los datos a recursos definidos en otras aplicaciones conectadas. Es lo que vamos a hacer para enviar la carátura (imagen JPG) a la aplicación del mando a distancia. Der esta forma podremos ver la alternativa a intercambiar datos.
Para ello vamos a utilizar el método SendStream de la clase TTetheringAppProfile, con un código como este:
// enviar datos a los perfiles remotos (si tenemos alguno) if (ttManager.RemoteProfiles.Count > 0) then begin // acceder al perfil pInfo := ttManager.RemoteProfiles[0]; // La imagen está en disco JPEGImage := TJPEGImage.Create(); CaractulaStream := TMemoryStream.Create; try JPEGImage.LoadFromFile(InfoTracks[ID].PathImage); JPEGImage.SaveToStream(CaractulaStream); // Una vez almacenada en un Stream la enviamos ttProfiler.SendStream(pInfo, 'rCaratula', CaractulaStream); finally CaractulaStream.Free; JPEGImage.Free; end; end; |
Una vez realizado el envío, en la aplicación que está conectada nos saltará un evento OnResourceReceived que tiene la siguiente cabecera:
procedure TMainForm.ttProfilerResourceReceived (const Sender: TObject; const AResource: TRemoteResource); |
Basta con comprobar que es el recurso deseado y realizar las acciones pertinentes. En mi caso, como es una imagen, directamente se puede cargar sobre un TImage y mostrar así en el mando a distancia la carátula de la canción que se está reproduciendo en ese momento:
procedure TMainForm.ttProfilerResourceReceived(const Sender: TObject; const AResource: TRemoteResource); begin _Log('Resource received; ' + AResource.Name); _Log('Hint= ' + AResource.Hint); _Log('Valor= ' + AResource.Value.AsString); // Es el recurso que esperamos? if (AResource.Hint = 'rCaratula') then begin // Cargarlo sobre un TImage imgCaratula.Bitmap.LoadFromStream(AResource.Value.AsStream); end; |
Con esto ya tenemos descrito el sistema que utilizamos para enviar información desde el reproductor al mando a distancia conectado.
PROYECTO MÓVIL
El proyecto móvil, como ya se ha visto antes, es un mando a distancia para el reproductor de música. No sólo he intentado que tenga las funciones básicas para controlar la aplicación, sino que además reciba información de la canción que se está reproduciendo en cada momento; Una forma de plasmar el estado del reproductor en el dispositivo que hace de “mando a distancia”.
Al entrar en el programa, disponemos de un botón que nos permitirá conectar con nuestro reproductor, si este está presente. Para ello se utiliza el método DiscoverManagers. Si encontramos alguna aplicación a la que poder unirnos, se realiza un PairManager.
Durante este proceso, como ya he comentado antes, “saltan” eventos en ambas aplicaciones, que nos permiten comprobar el estado de cada operación. Algunos de ellos son OnNewManager, OnPairedFromLocal, OnPairedToRemote,…
Una vez completado el “emparejamiento” lo que hago desde la aplicación móvil es subscribirme a los recursos publicados por la aplicación de escritorio. De esta forma, una vez que la suscripción se ha completado, cuando esos recursos se modifiquen, el control remoto recibirá automáticamente una notificación.
// Suscribirse a los recursos remotos b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rArtista'); b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rAlbum'); b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rCancion'); b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rGenero'); b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rAnyo'); b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rVolumen'); b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rTiempoTotal'); b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'rTiempoCancion'); … b := ttProfiler.SubscribeToRemoteItem(RemoteProfiles[0], 'ListaCanciones'); |
Además la aplicación “solicita” mediante una acción remota, que se le envíen los datos iniciales. De esta forma justo después de conectarse recibe toda la información del estado del reproductor. A partir de ese momento, sólo se irán recibiendo aquellos recursos que se van modificando. Esta llamada a una acción remota se realiza con un código como este:
// Perfiles remotos i := RemoteProfiles.Count; // Hay alguno? if (i > 0) then begin // Accedemos al primero pInfo := RemoteProfiles[0]; // Ejecutamos la acción remota ttProfiler.RunRemoteAction(pInfo, 'ActionSendInfoToRemote'); … |
Más o menos con lo explicado hasta ahora ya podemos ver cómo el control remoto se mantiene “actualizado” con el estado que en cada momento tiene el reproductor.
La otra parte del trabajo es la de que el control remoto se comporte realmente como un “control remoto” de nuestra aplicación. Para ello basta con utilizar las acciones publicadas desde la aplicación del reproductor que vimos anteriormente.
El el componente AppProfiler hemos creado acciones que “mapean” las acciones del formulario (las de siempre).
De esta forma, creamos una acción pública (IsPublic=True) compartida (Shared) llamada rPlay (nombre único) y que ejecutará la acción ActionPlay. Igual para el Pause, Stop,…
Desde nuestro mando a distancia sólo nos queda ejecutar la acción remota rPlay, para que en el reproductor se ejecute la acción ActionPlay.
// Alguien conectado? if (ttManager.RemoteProfiles.Count > 0) then begin pInfo := ttManager.RemoteProfiles[0]; // Ejecutamos acciones remotas… ttProfiler.RunRemoteAction(pInfo, 'rPlay'); … |
TIPOS DE CONEXIÓN
Una de las mejoras más importantes en la última versión de Delphi con respecto a Tethering, es la inclusión de un nuevo protocolo de comunicación. A partir de RAD Studio XE7 en el componente TTetheringManager encontramos la propiedad AllowedAdapters, que nos permite seleccionar entre Network (wifi) o Bluetooth. No sólo eso, sino que podemos seleccionar ambos, utilizando “;” o “pipes” (|), de forma que se inicializarán ambos.
Debería bastar con modificar esta propiedad para hacer funcionar nuestro programa con uno u otro protocolo (**).
(**) NOTA: Mi intención, era probar esta nueva característica y poder enseñarla en esta entrada, pero desgraciadamente no he conseguido conectar mi ordenador con la aplicación móvil utilizando bluetooth. Creo que los problemas de conexión me los está generando el ordenador portátil (que ya es algo viejo) y cuyos drivers bluetooth no están correctamente instalados, así que por ahora me he quedado sin poder probar/enseñar esta opción. Sigo intentándolo, pero no quería demorar más la publicación de esta entrada por este tema.
A medida que descubra más sobre el problema lo añadiré a la entrada (prometido).
CONCLUSIÓN
La sensación que deja esta característica una vez que la usas en una aplicación y ves el funcionamiento, es que realmente es algo muy “simple”, pero a la vez muy “útil”. De aquellas cosas que piensas cuando las ves, que ”porqué no se le habrán ocurrido a alguien antes”…
;-D
Salvando las primeras pruebas, cuando ya se dominan un poco los métodos y propiedades de ambos componentes y se entiende el funcionamiento básico de “Acciones” y “Recursos”, la utilización se vuelve bastante simple.
He grabado un vídeo para que se pueda ver funcionando ambas aplicaciones, espero que sea útil junto con el resto de la entrada.
Os adjunto los links para descargar tanto los ejecutables como los fuentes de ambos aplicaciones:
Código fuente del reproduvctor
Código fuente del mando a distancia
Ejecutable del mando a distancia
Apliación APK del mando a distancia (actualizado 25/02/2015)
Código fuente del package PBass.BPL
DLLs y BPLs extras de delphi 6 (PBass.bpl)
NOTA: Hay diferentes versiones de la librería BASS.DLL; en mi caso estoy utilizando una compatible con 64 bits. Si os da problemas en otras versiones/siatemas avisadme por favor.
NOTA2: Gracias a Cocce, que me ha comentado que le daba un error al ejecutar si no está delphi 6 instalado (debido a la compilación del package PBass.bpl -que os dije que había compilado con D6-). He subido el código fuente del package y un par de BPL’s que necesita para ejecutar.
AÑADIDO (25/02/2015): (Gracias iretai).
El usuario Iretai me comenta que la aplicación ha “salido” con demasiados permisos y tiene razón. Por defecto Delphi tiene una serie de permisos “predefinidos” activados, que si no nos acordamos de desactivar quedan activados en su publicación. No es algo sin importancia y menos si la aplicación va a ser una aplicación que posteriormente se distribuya en la tienda de Google. En este caso, como estábamos hablando de un ejemplo no le di más importancia, pero si la tiene.
Además los permisos activados no son “triviales”, pues hablamos de acceso a las llamadas, a la cámara o al calendario. En concreto las siguientes líneas están en el XML:
- <uses-permission android:name=»android.permission.CALL_PHONE» />
- <uses-permission android:name=»android.permission.CAMERA» />
- <uses-permission android:name=»android.permission.INTERNET» />
- <uses-permission android:name=»android.permission.READ_CALENDAR» />
- <uses-permission android:name=»android.permission.READ_EXTERNAL_STORAGE» />
- <uses-permission android:name=»android.permission.READ_PHONE_STATE» />
- <uses-permission android:name=»android.permission.WRITE_CALENDAR» />
- <uses-permission android:name=»android.permission.WRITE_EXTERNAL_STORAGE» />
El código fuente de la aplicación ha estado disponible desde que publiqué la entrada, así que basta con cambiarlos y recompilar, pero ya que también he publicado el APK compilado, los he modificado yo y lo he vuelto a subir actualizado.
También he subido la aplicación a Google Play (donde al descargar nos avisa de los permisos activados) para que también se pueda descargar desde allí.
Os adjunto la captura donde aparecen los cambios de permisos al subir la actualización a Google Play (cosa que está muy bien).
Como siempre los comentarios, sugerencias, críticas,… serán bien recibidas.
Un saludo y hasta la próxima.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Impresionante :)
I tried your project but i have an error executing the line
H := LoadPackage(‘PBass.BPL’);
PBass.BPL requires «rtl60.bpl» and then the program aborts.
Would you please provide the PBass.bpl source project?
Thanks in advance
Cocce
@Cocce
Tranks Cocce.
I have upload the source of the project (originally in D6).
I have uploaded the BPL’s in a separate file.
Thanks for the advice.
Que decir, una entrada excelente amigo Germán, si ésto no convence a los que aún tienen dudas que Delphi está haciendo cosas geniales, entonces nada los convencerá.
Impresionante la forma como abordaste el ejercicio amigo, muchas felicidades.
Saludos
@Eliseo GN
Gracias Eliseo.
La verdad es que he intentado que al menos fuera algo atractivo y se saliera de lo que es un ejemplo convencional. Espero que al menos eso aumente el interés.
Un saludo.
Muy interesante el artículo así como la simplicidad y potencia que el invento proporciona. ¿Qué hay debajo de los componentes que se mencionan? ¿Cómo funcionan «realmente»? Sea como sea muchas gracias por la aportación Germán. :)
@dec
Hola David. Gracias por los comentarios.
Los dos protocolos están definidos en dos unidades creadas expresamente para ello, System.Tether.NetworkAdapter y System.Tether.BluetoothAdapter. A partir de ahí cada uno de ellos se basa en una tecnología diferente que se ha encapsulado para hacerlos más sencillos de utilizar y para que ambas conexiones funcionen, a vista del usuario, de la misma manera (modificando la propiedad AllowedAdapters).
En el caso de conexión wifi (network) se usa TCPIP ; Revisar la unit System.Tether.Comm; para más detalles la clase TTetheringNetworkComm. Veremos que el cliente y el server, tienen definidas estas dos variables:
* FTCPClient: IIPTCPClient;
* FTCPServer: IIPTCPServer;
En el caso de bluetooth, se usa la unit System.Bluetooth que proporciona todas las clases para conexión entre programas utilizando bluetooth (que se puede hacer sin necesidad de utilizar tethering -pero resulta un poco más complejo-) y otras clases relacionadas, como por ejemplo, las que implementan el protocolo BluetoothLE (Low energy).
Un saludo.
Muchas gracias por la información Germán.
Hola.-
Gran artículo y muy bien explicado.
Solo tengo una cuestión, si quisiera enviar desde el reproductor al mando además de los datos propios de la canción (titulo, autor, etc.) la canción misma (supongo que mediante un TStream), tienes idea de como deberia enfocar este tema?
Saludos y muchas gracias por tus articulos.
@Javier
Hola Javier.
Lo deberías hacer enviando streams. De la misma forma como envío la carátula (que se hace así -con streams-) puedes enviar la canción.
No deberías tener problemas en hacerlo.
Un saludo.
@Germán Estévez
Hola. Gracias por tu respuesta. Actualmente utilizo esto como metodo de envío:
procedure TForm1.PlayerRemoto(Sender: TObject);
var
newDish: TStream;
begin
newDish.Create;
newDish := StringToStream(LoadFile(‘/sdcard2/musica/EMANUELLE.mp3’));
AppProfile.SendStream(Manager.RemoteProfiles[0], ‘Musica’, newDish); <——Error
end;
function TForm1.LoadFile(const FileName: TFileName): string;
begin
with TFileStream.Create(FileName,
fmOpenRead or fmShareDenyWrite) do begin
try
SetLength(Result, Size);
Read(Pointer(Result)^, Size);
except
Result := ''; // Deallocates memory
Free;
raise;
end;
Free;
end;
end;
Desgraciadamente, me devuelve un error cuando envío el stream en la línea indicada más arriba. Se que con imagenes es facil ya que en la propiedad bitmap tenemos la funcion SaveToStream, sin embargo, en audio, no existe esto.
Saludos.
Por cierto, el error que me devuelve es error en parámetros (en newDish). Mi problema es que newDish posiblemente aunque es del tipo correcto, no contenga el audio correctamente.
Saludos.
@Javier
Hola Javier.
Yo probaría a generar utiliando un TMemoryStream un Stream en memoria a partir del MP3 de la canción. Enviarlo, y una vez recibido volver a volcarlo a disco (o a la tarjeta).
A partir de ahí ya deberías poder reproducirlo.
Un saludo.
Gracias. Probaré eso que me comentas. Quería hacerlo de la misma forma como se reproducen los wav, pero según parece, los mp3 no se pueden reproducir directamente desde memoria, sino como tu bien dices, grabandolo primero a disco (o a la tarjeta).
Saludos.
Hola Javier.
Pensé que querías hacer justo lo contrario. Grabar el MP3 a disco para luego reproducirlo.
Hay poca información para realizar streaming, pero algo hay.
En la propia página de la librería BASS hay algo. Es posible que utilizando lo librería que he utilizado en el reproductor puedas conseguirlo (http://www.un4seen.com/forum/?topic=15197.0).
Y en esta página (http://codes-sources.commentcamarche.net/source/100709-android-stream-mp3-implementation-listener-java-depuis-delphi) también explican algo. A ver si te sirve.
Un saludo.
Gracias. He escrito el siguiente código:
procedure TForm1.PlayerRemoto(Sender: TObject);
var
newDish: TMemoryStream;
//sound: TSoundItem;
begin
newDish:=TMemoryStream.Create;
try
newDish.LoadFromFile(‘/sdcard2/musica/EMANUELLE.mp3’);
newDish.Position:=0;
AppProfile.SendStream(Manager.RemoteProfiles.Items[0], ‘Musica’, newDish);
finally
newDish.Free
end;
end;
Pero desafortunadamente me da error de «Parameter out of range» en el paso de parámetros en el appProfile. Me temo que no carga correctamente el archivo mp3 en el memorystream o bien al enviar newDish no es la forma correcta de enviarlo.
gran artículo. No pienso lo mismo de tu gusto musical :D
@mike
Gracias.
Ya sabes, como se suele decir, «sobre gustos, no hay nada escrito…»
;-DD
Muy interesante, gracias por comparti.
el apk bajado, solicita permisos com hacer llamadas telefonicas, localizarme a traves del GPS, Leer informacion como ID e IMEI, Acceder a mi camara y finalmente permisos para manipular mi disco. Creo que ninguna de estas solicitudes es necesaria, claro que son interesantes de utilizar si uno quiere usmear al que bajo la apk.
@iretai
Hola iretai.
Seguramente tienes razón. Deben ser los permisos que Delphi tiene activos por defecto al generar una aplicación que en este caso debí dejarlos activados.
Si tienes algún reparo en descargarla, no hay problema (tiene lógica), para eso está subido el código fuente.
Basta con que lo compiles y elimines los permisos innecesarios. El APK puedes copiarlo al teléfono e instalarlo desde allí (sin pasar por la tienda).
Si puedo cuando tenga un hueco yo mismo lo haré y volveré a subir la aplicación.
CORRIJO: Esta no la había subido a la tienda de google. Recompilo y lo vuelvo a poner. Cuando lo tenga actualizado os aviso con un añadido en la entrada.
Gracias.
@iretai
Corregido.
He subido el APK con los nuevos permisos y también lo he subido a Google pLay.
Arriba (al final del artículo) está el link.
Un saludo.
Saludos a Todos.
He estado indagando sobre como hacer un APP buscador de musica (vía Streaming/Internet), utilizando Firemonkey/Delphi(preferiblemente FireMonkey por lo de los iOS/Android); es decir, poder escribir el nombre de una canción o artista, y acto seguido me muestre el/las canciones encontrada(s); Poder reproducirla o hacer el download de la canción. Tengo la idea, de que esto amerita esta inscrito en algun servicio de musica (Spotify, etc) y usar algun API; pero la verdad que encuentro muy poca documentación o ejemplos claros de como hacerlo.
Gracias de Antemano por cualquier orientación.
@MiguelC-II
Hola Miguel.
Tal y como comentas, hay varios temas a los que debes atender.
Lo primero es tener algún servicio donde buscar canciones. En este mismo ejemplo o en este otro de la web (http://neftali.clubdelphi.com/?p=3572) puedes ver cómo acceder. Las API’s que te puedas encontrar seguramente son similares (REST) y el acceso concreto dependerá del servicio.
Lo segundo es el tema del Streaming una vez seleccionada la canción. Para esto deberás buscar algún componente que te permita la descarga y reproducción. La descarga es fácil que puedas hacerla con las Indy (por ejemplo) la reproducción vía streaming, tendrás que ser creo con un componente específico.
Un saludo.
Hola Neftalí, por que será que siempre que estoy por empezar un proyecto termino en tu blog??
Tengo en mente realizar un programa que se comunique vía bluetooth con un arduino, con fines didácticos, se trata de controlar dirección y velocidad de un auto de juguete, el líneas generales.
No se realizar la comunicación bluetooth desde delphi -este será mi primer intento- y este trabajo tuyo es lo primero que leo, pero desde ya intuyo que lo mio es mucho más modesto que lo que aquí encuentro. Alguna recomendación que puedas darme??? todo comentario se agradece y ayuda.
@victor
Hola Víctor.
Al contrario, este sistema usando Tethering es muy sencillo.
Tethering es una capa que simplifica mucho las cosas y utiliza como vía de comunicación bluetooth o wifi de forma transparente para el programador. Es este caso ideal para programar comunicación entre varias aplicaciones que utilicen delphi.
En tu caso tendrás que utilizar directamente bluetooth (que se puede hacer sin utilizar tethering).
Para ello puedes revisar la documentación de la docwiki de embarcadero referente a bluetooth.
Tendrás que utilizar las units destinadas a ello. Te dejo un par de enlaces:
http://docwiki.embarcadero.com/RADStudio/XE8/en/Using_Bluetooth_Low_Energy
http://docwiki.embarcadero.com/RADStudio/XE8/en/Using_Bluetooth
Un saludo.
Muchas gracias por tu respuesta, ya me pongo a estudiarlo.
Saludos!!
Hola Neftalí,
En primer lugar gracias por compartir sus conocimientos, fue muy útil a sus enseñanzas sobre » Tethering Delphi XE7″ desarrollaron un sistema muy similar, pero tengo un problema que no he encontrado una solución, tal vez usted me puede ayudar, tengo un servidor con un programa principal y una aplicación de Android, todo funciona muy bien, conectado a través de wifi, pero la conexión en adroid se perdió al quedarse fuera del alcance de wifi tiene un error: SOCKET ERROR…CONNECTION RESET BY PEER, y volver al trabajo tienen que cerrar la aplicación en Android y cerca también en el servidor, ya sabes alguna manera de evitar que el programa se bloquea el servidor y que no es necesario cerrar y abrir de nuevo?
muchas gracias.
@Vinicius
Hola Vinicius.
Tendríais que revisar los métodos que vienen con los componenntes de tethering para controlar la conexión.
Tal vez podaís cerrar la conexión y volver a abrirla cuando los dispositivos vuelvan a estar dentro de la red wifi.
Un saludo.
Interesante artículo!, lamentablemente los fuentes no están disponibles, ¿es posibles resubirlos?.
@Arturo Serrallés
Los reviso.
Por un cambio en el blog, hay muchos enlaces que han quedado incorrectos.
@Arturo Serrallés
Ya están modificados los links.
Debería poder bajar los ficheros sin problemas.
Un saludo.
Muchas gracias Neftalí, ya pude descargarlos.