¿Cómo transferir archivos entre aplicaciones de Android que se ejecutan en el mismo dispositivo?
Estoy escribiendo una aplicación de Android que interactúa con un servicio RESTful. Este servicio web esencialmente enfrenta un sistema de archivos, y proporciona metadatos, así CRUD acceso a los archivos. Mi aplicación recupera los metadatos y lo expone a aplicaciones de terceros a través de un ContentProvider
.
Tengo que añadir la capacidad de las aplicaciones de terceros, que se ejecutan en el mismo dispositivo que mi aplicación, a CRUD los archivos reales haciendo solicitudes a / desde mi aplicación (no directamente con el servidor). Esto significa que necesitan enviar o recibir el contenido de los archivos (que normalmente son XML o imágenes) a través de mi aplicación.
- BindService () devuelve false pero unbindService () necesita ser llamado?
- Usar SharedPreferences en modo multiproceso
- Android aidl no puede enlazar al servicio, cuando el host se instala después de que el cliente
- La vinculación al servicio que ya fue iniciada por BroadcastReceiver crea una nueva instancia de servicio
- Android: startActivityForResult no llamando aActivityResult
He pensado en dos enfoques para implementar esto:
Opción 1 – Uso de ContentProvider.openFile
Esto parece una opción obvia para dar a las aplicaciones de terceros la capacidad de leer archivos de mi ContentProvider
. Creo que empieza a ser complicado cuando esas aplicaciones necesitan crear o actualizar archivos a través de mi 'ContentProvider'. Necesitaré una devolución de llamada cuando hayan terminado para saber cuándo enviar el archivo nuevo / modificado de nuevo al servidor. Creo que podría utilizar un FileObserver para ese propósito sin embargo.
Opción 2 – Uso de un Messenger a través de un servicio
Con este enfoque, puedo enviar los archivos entre mi aplicación y las aplicaciones cliente a través del Messenger
. Los archivos tendrían que pasar a través de un Bundle
, por lo que no estoy seguro de cuál es el mejor formato para transmitirlos ( File
, FileDescriptor
, matriz de bytes, algo más ??). No tengo una buena manija en si o no esto causaría problemas si los archivos consiguen ser grandes.
Opción 3: un enfoque híbrido
- Utilice la (s) carpeta (s) en el almacenamiento externo como un buzón
- Comunique las peticiones de CRUD, y el contenido de la caja de la gota, a través de un
Messenger
/Service
- Utilice
ContentProvider
para almacenar el estado de las solicitudes - La aplicación de terceros recibe actualizaciones de estado a través de un
ContentObserver
Resumen
Creo que usar ContentProvider
sería la solución ideal, pero parece que la API no es totalmente compatible con mi caso de uso. Me preocupa que intentar seguir ese camino podría resultar en una implementación kludgy. Si voy con un servicio de Messenger
y Service
, no estoy seguro de la forma más sólida de transferir los archivos a través de un Bundle
.
El enfoque híbrido parece bastante robusto, pero el más complejo de implementar. Los archivos en realidad no se están pasando, por lo que el rendimiento debe ser bueno. Sin embargo, me temo que esto es over-architecting la solución.
¿Cuál es el mejor enfoque para transferir archivos entre aplicaciones que se ejecutan en el mismo dispositivo Android? Por supuesto, estoy abierto a otras opciones que no he esbozado en mi pregunta.
- Handler en Android
- Android ResultReceiver a través de paquetes
- ¿Cómo puedo notificar una actividad en ejecución de un receptor de difusión?
- ¿Cómo llamar a un servicio remoto Android (IPC) desde un servicio Widget / local?
- ¿Por qué AIDL / Messenger está enlazado a un Servicio?
- ¿Por qué utilizar parcelable cuando se puede realizar la misma tarea utilizando variables estáticas?
- La mejor manera de realizar la comunicación entre actividades en una aplicación Android TabHost
- GREF que aumenta / que disminuye en servicio multi-hilo (aidl) - qué significa?
Proveedor de contenido es definitivamente el camino a seguir. Si usted considera que Google utiliza este enfoque para casi todo, entonces se convierte en appaentr que este es el método de diseño previsto.
No estoy exaltando las virtudes de ellos, pero en la tierra de los ciegos, el proveedor de contenido de un solo ojo es el rey.
Actualizar
Hay un ejemplo de cómo hacerlo en el libro de CommonsWare, consulte el enlace proporcionado.
Fuente del proveedor de contenido / archivos
Utilice el marco de sincronización para los proveedores de contenido. Simplemente mantenga una lista de peticiones y programe la sincronización para descargar el archivo. También puede hacer esto en cosquillas de red, etc. Puede utilizar intents de difusión o contentobserver para notificar a los clientes que el archivo se descarga.
En esencia esto es probablemente similar a su tercera opción, pero lo más importante es que utiliza las herramientas suministradas por Android en lugar de rodar su propio.
Ad Endum
El mejor lugar para comenzar es la muestra de Android SDK en: android-sdk \ samples \ android-8 \ SampleSyncAdapter, pero se advierte que hay una carga de cosas relacionadas con los contactos que enmascara los bits jugosos. Me tomó un tiempo para averiguar que podía eliminar casi todo excepto el syncadapter
http://developer.android.com/reference/android/os/ParcelFileDescriptor.html puede enviarse entre procesos. Creo que hay una sutilidad en la que estos están explícitamente en la lista negra de ser permitido a ser puesto en intenciones. Pueden ser enviados a través de AIDL sin embargo. Además, NO utilice la tarjeta sd para esto. Esto es sólo pedir problemas. Una tarjeta SD es legible en el mundo, por lo que cualquiera puede verlo. Además, no siempre tiene acceso a escribir en la tarjeta SD (se quita o se pone en UMS).
Usar la tarjeta SD es definitivamente la forma recomendada de compartir archivos en Android.
Sin embargo, me gustaría ir con una solución híbrida modificada que hace uso de startActivityForResult()
y onActivityResult()
(docs aquí ) en el lado del cliente para comunicar solicitudes CRUD (y obtener el Uri a los archivos de la tarjeta SD si es necesario ) Si no le importa crear una actividad simulada como un front-end a su servicio. Los clientes, una vez terminados con los archivos, pueden llamar a startActivityForResult()
nuevo para alertar a la aplicación de los cambios.
Por supuesto esto se puede hacer con startService()
/ bindService()
sin embargo no proporciona una manera fácil para que los clientes obtengan un resultado del estado especialmente si usted necesita IPC.
Aunque los proveedores de contenido / resolvers se sienten como la forma correcta de ir sobre las cosas, creo que es más para las solicitudes de dirección única específica para proporcionar / consumir contenido.