Question

I'm currently working on an XMPP app' on Android and I'm pondering about the best way to throw a different type of Exception than a RemoteException to my activity from my service.

As it seems impossible to throw another thing than a RemoteException using IPC (you can't declare to throw anything in your .aidl), I just see two solutions:

  • Create a listener for my activity to listen on my custom XMPP exception, which in fact will not be thrown but just sent as a usual object implementing the Parcelable protocol.

  • Catch my XMPPException and throw a RemoteException (with a content updated with my XMPPException) - But in that case, how could I know on my activity if it's an XMPP or a real RemoteException ? By tagging the name of the exception and parsing it on my activity ? It would be really gore.

Do you have any idea ? Did I miss something from the SDK documentation ?

Thanks.

Was it helpful?

Solution

If #1 means what I think it does, I'd use that -- have the service catch the exception and call a method on an AIDL-defined callback object created and supplied by the activity.

You can see an example of that technique in this client and service project, from one of my books.

OTHER TIPS

It looks like we can throw custom exceptions derived from RemoteException. So you can have XMPPRemoteException, or just a generic MyRemoteException that will hold the original exception. Below is a demo for the second case:

Server:

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

Client:

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

Helper method:

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

Exception:

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

    public MyRemoteException() {}

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

I think it is impossible to achieve "Throw a custom exception from a service to an activity". See the resource of 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);
}

so we can know that we just can throw these five exceptions above.

for example: If your service throw a 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!");
    }
...
}

your client will can catch it:

            try {
                printer.addImage(0, null);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top