2010-03-21 14 views
25

tengo una situación particular: un servicio iniciado por un receptor de radiodifusión comienza una actividad. Quiero hacer posible que esta actividad se comunique nuevamente con el servicio. He elegido usar AIDL para hacerlo posible. Todo parece funcionar bien excepto por el método bindService() llamado en onCreate() de la actividad. bindService(), de hecho, una excepción de puntero nulo porque onServiceConnected() Nunca se llama mientras onBind() método del servicio es. De todos modos, bindService() devuelve verdadero. El servicio está obviamente activo porque inicia la actividad. Sé que llamar a una actividad de un servicio puede sonar extraño, pero desafortunadamente esta es la única forma de tener reconocimiento de voz en un servicio.onServiceConnected llamada después método bindService

Gracias de antemano

Respuesta

13

no puedo compensar el problema exacto de su descripción, así que voy a adivinar aquí!

¿Cómo puede bindService() lanzar una NullPointerException? La única forma en que esto podría (/ debería) suceder es cuando no se proporciona un Service o un ServiceConnection oyente.

bindService() no puede lanzar una NullPointerExceptionporqueonServiceConnected() no se llama. La llamada a onServiceConnected() es un producto de bindService().

Así que supongo que está llamando a un método AIDL, antes de que el Service se haya enlazado realmente?

+1

sí, lo siento, entiendo que el problema podría explicarse mejor. Se lanza NullPointerException porque la interfaz remota nunca se llena como remote = IRemoteService.Stub.asInterface (service); en onServiceConnected() nunca se llama. ¿Debería bindService desencadenar el onServiceConnected inmediatamente? – Matroska

+2

'onServiceConnected()' no se debe llamar __inmediatamente__, probablemente habrá un pequeño retraso. – MrSnowflake

+0

¡Tienes razón! El método no se llama inmediatamente. Ese fue mi problema – Matroska

36

Después de horas y horas de tratar de resolver esto, el problema es que los ejemplos que muestran la creación del servicio, no incluyen el método onBind o tienen el siguiente código de ejemplo o lo genera para usted:

public IBinder onBind(Intent intent) { 
    // TODO Auto-generated method stub 
    return null; 
} 

Esto hace que el método onServiceConnected falle o que nunca se ejecute realmente. La solución es muy simple, que es la siguiente:

public IBinder onBind(Intent intent) { 
    return mBinder; 
} 

¿Dónde se puede crear una carpeta sencilla como la siguiente para volver:

private final IBinder mBinder = new LocalBinder(); 
public class LocalBinder extends Binder { 
    public ConferenceService getService() { 
    return ConferenceService.this; 
    } 
} 
+3

¡Gracias, Brad, me salvaste un poco de tiempo aquí! Tuve dos problemas, el que señala aquí y el que no tiene el servicio definido en el archivo de manifiesto. Descubrí que el estado de comprobación de bindService() también es importante. – DustinB

+0

gracias Brad, también me ahorra mucho tiempo – Houcheng

+0

Esto se documenta aquí: http://developer.android.com/guide/components/bound-services.html#Binder – Rolf

37

que acabamos de experimentar otra versión de este problema, con el mismo síntoma de onServiceConnected(...) sin llamar. La causa fue diferente en mi caso.

Debe asegurarse de tener una declaración de servicio en su AndroidManifest.xml dentro de la etiqueta de la aplicación: esta fue la raíz del problema para mí.

<application android:name=".YourAppTitle" android:icon="@drawable/icon" android:label="@string/app_name"> 
    <activity android:name=".Main" android:label="@string/app_name"> 
    </activity> 
    <service android:name="YourService" /> 
</application> 

Hay una complicación adicional si está utilizando una biblioteca de Android separada dentro de Eclipse - añadiendo esta etiqueta de servicio sólo parece solucionar el problema si el servicio se hace referencia está en el mismo paquete que el manifiesto; es decir, si su aplicación está en el paquete a.b.c y aquí reside AndroidManifest.xml, entonces 'YourService' también debe estar en el paquete a.b.c. (Copiado manualmente de otra biblioteca, si es necesario) o bien la etiqueta puede <service..>/será ignorado y onServiceConnected(...) todavía no se llamará.

Este fue el caso de mi proyecto a pesar de que he usado una sentencia de importación adecuado para el servicio en mi código.Eclipse no mostró ningún error, por lo que la importación identificó correctamente la clase de otra biblioteca en el espacio de trabajo de Eclipse.

HTH

+0

Mi servicio está en una biblioteca y tengo este problema: ¿tiene que crear un nuevo servicio que herede el anterior? –

+0

Tengo un proyecto de biblioteca que contiene un servicio de facturación que quiero mantener en gran medida idéntico en un grupo de proyectos secundarios; He modificado esto para que sea abstracto y realicé un servicio que lo hereda en el proyecto secundario, pero obtengo el mismo error que anteriormente. Para que quede claro, ¿la llamada 'bindService (...)' debe provenir del 'Servicio' heredado o puede estar en el padre abstracto? ¿Y sabes la causa raíz de este problema? –

+0

Lo que he escrito es toda la información que tengo, me temo; He dejado de desarrollar Android a través de la frustración con la API y errores de firmware desde la publicación el año pasado. – KomodoDave

8

Una cosa más es que si llama bindservice método dentro del método oncreate entonces el onserviceconnected se llama después de que se terminó el método oncreate.

Por lo tanto, cualquier referencia a las funciones de interfaz antes de que finalice el oncreate (o antes de que se llame al onserviceconnected) muestra una excepción de puntero nulo.

+0

Este era exactamente el problema con el que me estaba encontrando, estaba llamando bind (... dentro de Create y no tenía idea de por qué el servicio SIEMPRE devolvía nulo, ¡gracias! – Sauron

+0

Esto lo arregló para mí, gracias ; He visto días en esto. –

22

Nunca se ha llamado al evento onServiceConnected en mi aplicación.

El problema era que tenía el nombre del servicio definido en mi solicitud se manifiestan como:

<service android:name="MyService" android:enabled="true"></service> 

Una vez que lo cambié el nombre completo de la clase funcionó:

<service android:name="com.example.MyService" android:enabled="true"></service> 

Actualización: También puede utilizar un nombre de clase relativo:

<service android:name=".MyService" android:enabled="true"></service> 

Especifique el nombre de clase con su completo com.example.MyServiceClass en lugar de solo MyServiceClass.

+0

Gracias. En mi caso, utilizar "MyService" es suficiente, pero con la locura de la programación en Java, creo que esta podría ser una opción más segura (o más segura) cada vez que implemente un servicio. –

+3

en realidad tiene que poner ".MyService" no el completo a menos que esté fuera del paquete. –

+1

No entiendo exactamente por qué, pero esto es absolutamente cierto. Esta respuesta simplemente solucionó mi problema. – codepushr

4

Otra causa más de la pregunta original podría ser que el servicio aún no se está ejecutando y está pasando 0 como indicador para bindService. De este modo:

bindService(intent, serviceConnection, 0); 

Cuando lo que busca sería:

bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 
1

No puede haber otra explicación, no es una situación muy frecuente, pero me las arreglé para entrar en ella y perder 2 horas a resuélvelo.

Entonces, lo que hice fue que quería reutilizar el paquete del intento recibido por el método onBind. Pero fui por la versión perezosa y cambié la clase del intento. Aparentemente, esto provoca que onServiceConnected no se llame. Probablemente porque el sistema guarda una referencia al intento y lo usa cuando llama aServiceConnected.

En conclusión, no cambie la intención que recibe en onBind.

0

Estaba llamando bind con un Intent vacío - getContext().bindService(new Intent(), mConnection, Context.BIND_AUTO_CREATE). Tengo que hacer que la intención sea más específica para indicar a qué servicio me quiero vincular. Obviamente, esto es un error de código, pero desafortunadamente la salida de Logcat no fue lo suficientemente clara.

Cuestiones relacionadas