2011-06-01 26 views
7

Primero de todo, me gustaría decir dos cosas. La primera vez, lo siento si esta pregunta ya se ha hecho, he buscado preguntas similares sobre este tema, pero no he podido encontrar una solución. En segundo lugar, disculpe la larga pregunta y, por favor, avísenme de cualquier error y me aseguraré de hacer los cambios adecuados :).¿Servicio compartido de Android?

Soy relativamente nuevo en el desarrollo de Android (aproximadamente 2 meses), así que por favor perdone mi ignorancia. La pregunta que tengo es sobre el servicio de Android.

Mi problema es el siguiente, he creado las 3 aplicaciones siguientes:

  • Una biblioteca androide que contiene un servicio de prueba pequeña (myService).
  • Una aplicación (TestApplicationOne) que tiene acceso a la biblioteca de Android.
  • Otra aplicación (TestApplicationTwo) que también tiene acceso a la biblioteca de Android.

Mi solución actual funciona de la siguiente manera, TestApplicationOne referencia a la biblioteca personalizada y utiliza esta biblioteca para conectarse al servicio (myService) a través del método bindService(). Tras la conexión exitosa, la aplicación se agrega a una colección de observadores ubicados dentro de myService. Cada objeto de esta colección se notifica cada vez que el servicio necesita transmitir un mensaje.

Cuando se ejecutó, la solución anterior parecía funcionar bien. Sin embargo, ahora tengo otra aplicación (TestApplicationTwo) que también desea utilizar el mismo servicio que el anterior. La implementación de TestApplicationTwo se creó con el mismo funcionamiento/especificación de la primera aplicación (TestApplicationOne).

El problema que tengo es que cuando el servicio se inicia en cualquiera de las aplicaciones, la otra aplicación no recibe ninguna notificación de ningún evento.

He intentado implementar varios enfoques para resolver esto. Como usar el patrón Singleton para retener una sola instancia, pero el problema parece existir. Mi única comprensión de esto es que cada vez que se inicia cualquiera de las aplicaciones, se crea una nueva instancia de la biblioteca. Por lo tanto, la biblioteca a la que se hace referencia en TestApplicationOne no es la misma instancia que la biblioteca a la que se hace referencia en TestApplicationTwo, y como resultado, no se ha notificado.

¿Hay alguien con alguna experiencia en este tema? ¿O puede pensar en alguna posible solución?

Gracias de antemano por cualquier ayuda, es muy apreciada.

John

Respuesta

10

El problema que tengo es que cuando el servicio se inicia en cualquiera de las aplicaciones, la otra aplicación no es notificado de cualquier evento.

Eso es porque tiene dos servicios. El hecho de que el servicio esté empaquetado en un proyecto de biblioteca de Android no provoca de alguna manera mágicamente dos aplicaciones distintas para usar la misma copia.

Como utilizar el patrón de Singleton para conservar una sola instancia, pero el problema parece existir todavía.

Ambas aplicaciones se ejecutan en procesos separados, con su propia copia privada del servicio.

Mi única comprensión de esto es que cada vez que se inicia cualquiera de las aplicaciones, se crea una nueva instancia de la biblioteca.

Las bibliotecas no tienen instancias. Los proyectos de la biblioteca de Android no son DLL, son más parecidos a las bibliotecas estáticas.

Así, la biblioteca de referencia en TestApplicationOne no es la misma instancia que la biblioteca de referencia en TestApplicationTwo, y como resultado, no se notifica.

Más exactamente, el servicio en TestApplicationOne es una copia separada del servicio de la copia en TestApplicationTwo.

¿O se le ocurre alguna solución posible?

No tiene dos aplicaciones separadas.

O bien, rediseñe sus aplicaciones de modo que solo una tenga el servicio y la otra use el servicio desde la primera aplicación.

O bien, tiene el servicio deshabilitado en el manifiesto en ambas aplicaciones, exportado con un estable <intent-filter> (por ejemplo, con una cadena de acción personalizada). La primera aplicación que se instalará/ejecutará usa PackageManager para ver si el servicio existe (por ejemplo, no es realmente la primera aplicación). Al ver que el servicio no existe, habilita su propia copia de ese servicio. Luego, la segunda aplicación pasa por el mismo proceso, ve que el servicio ya está allí y usa la copia remota en lugar de habilitar la suya propia.

Ni el segundo ni el tercero son muy fáciles, simplemente porque los datos solo existen en una aplicación (la que tiene el servicio). Por lo tanto, si esa aplicación se desinstala, la otra aplicación se atornilla, incluso si tiene el código de servicio disponible como un componente deshabilitado. Si las aplicaciones se describen claramente para el usuario como una relación primaria/secundaria (por ejemplo, la aplicación y su complemento), entonces esto puede funcionar: los usuarios esperan que no espere que un complemento funcione si la aplicación no está allí, por ejemplo. Por supuesto, en este caso, el plugin no tendría su propia copia del servicio en primer lugar, pero siempre buscaría la aplicación principal para eso.

+0

Blunt, pero una respuesta de todos modos. Gracias por tu ayuda. El producto terminado solo lo utilizaré personalmente, por lo que la solución exportada con un filtro de intención parece ser un posible enfoque. Examinaré más esta sugerencia y actualizaré esta pregunta con mi enfoque elegido. De nuevo, gracias por tu ayuda. – JohnHodkinson

+0

Me sorprende que no menciones compartir un proceso. Tal vez la respuesta es obsoleta? – dcow

+0

@dcow: en el mejor de los casos, eso funcionaría si el escenario de producción indica que las dos aplicaciones están firmadas por la misma clave de firma, y ​​eso no está claro a partir de la pregunta. En segundo lugar, espero sinceramente que el escenario que describa todavía implique máquinas virtuales separadas (que simplemente estén en un solo proceso), en cuyo caso no sería de ayuda. Dos aplicaciones que compartan la misma máquina virtual en el mismo proceso serían problemáticas, por colisiones de classpath si nada más. – CommonsWare

2

No estoy seguro, pero creo que la etiqueta del atributo de servicio android:singleUser="true" podría ser lo que estás buscando.

If set to true, a single instance of this component will run 
for all users. [boolean] 

Si esto no ayuda, entonces usted podría considerar una solución en la que se envíe emisiones del servicio para cada uno de sus eventos y tienen BroadcastRecievers en sus 2 aplicaciones en lugar de acceder al servicio como un objeto ...

Cuestiones relacionadas