Pregunta

Actualmente estoy trabajando en una aplicación XMPP 'en Android y estoy reflexionando sobre la mejor manera de lanzar un tipo diferente de excepción que RemoteException a mi actividad desde mi servicio.

Como parece imposible lanzar algo más que una RemoteException usando IPC (no puedes declarar que arrojas nada en tu .aidl), solo veo dos soluciones:

  • Crear un escucha para que mi actividad escuche en mi excepción XMPP personalizada, que de hecho no se lanzará sino que se enviará como un objeto habitual que implementa el protocolo Parcelable.

  • Captura mi XMPPException y lanza una RemoteException (con un contenido actualizado con mi XMPPException) - Pero en ese caso, ¿cómo podría saber sobre mi actividad si es una XMPP o una RemoteException real? ¿Al etiquetar el nombre de la excepción y analizarlo en mi actividad? Sería realmente sangriento.

¿Tienes alguna idea? ¿Me perdí algo de la documentación del SDK?

Gracias.

¿Fue útil?

Solución

Si # 1 significa lo que creo que significa, lo usaría: hacer que el servicio detecte la excepción y llame a un método en un objeto de devolución de llamada definido por AIDL creado y suministrado por la actividad.

Puede ver un ejemplo de esa técnica en este cliente y proyecto , de uno de mis libros.

Otros consejos

Parece que podemos lanzar excepciones personalizadas derivadas de RemoteException. Entonces puede tener XMPPRemoteException, o simplemente una MyRemoteException genérica que contendrá la excepción original. A continuación se muestra una demostración para el segundo caso:

Servidor:

try {
    ...
}
catch(XMPPException e) {
    throw new MyRemoteException(e);
}

Cliente:

try {
    service.someCall();
}
catch(MyRemoteException e) {
    rethrow(e);
}

Método auxiliar:

private void rethrow(MyRemoteException e) throws Exception {
    if(e.innerException instanceof XMPPException)
        throw (XMPPException)e.innerException;
    else
        throw e.innerException;
}

Excepción:

public class MyRemoteException extends RemoteException {
    private static final long serialVersionUID = 1L;
    public Exception innerException;

    public MyRemoteException() {}

    public MyRemoteException(Exception innerException) {
        this.innerException = innerException;
    }
}

Creo que es imposible lograr " Lanzar una excepción personalizada de un servicio a una actividad " ;. Vea el recurso de Parcel:

    /**
 * Use this function for customized exception handling.
 * customized method call this method for all unknown case
 * @param code exception code
 * @param msg exception message
 */
public final void readException(int code, String msg) {
    switch (code) {
        case EX_SECURITY:
            throw new SecurityException(msg);
        case EX_BAD_PARCELABLE:
            throw new BadParcelableException(msg);
        case EX_ILLEGAL_ARGUMENT:
            throw new IllegalArgumentException(msg);
        case EX_NULL_POINTER:
            throw new NullPointerException(msg);
        case EX_ILLEGAL_STATE:
            throw new IllegalStateException(msg);
    }
    throw new RuntimeException("Unknown exception code: " + code
            + " msg " + msg);
}

para que podamos saber que podemos lanzar estas cinco excepciones anteriores.

por ejemplo: Si su servicio lanza una IllegalArgumentException:

    @Override
public void addImage(final int align, final byte[] imageData) throws RemoteException {
    log("/// addImage ///");
    if (imageData == null) {
        throw new IllegalArgumentException("The second argument(image data) can not be empty!");
    }
...
}

su cliente podrá atraparlo:

            try {
                printer.addImage(0, null);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top