Android 从服务向活动抛出自定义异常

Android 从服务向活动抛出自定义异常,android,exception,service,ipc,Android,Exception,Service,Ipc,我目前正在Android上开发一个XMPP应用程序,我正在考虑通过我的服务向我的活动抛出不同类型的异常而不是RemoteException的最佳方法 由于似乎不可能使用IPC抛出除RemoteException之外的其他东西(您不能声明在.aidl中抛出任何东西),我只看到两种解决方案: 为我的活动创建一个侦听器,以侦听我的自定义XMPP异常,该异常实际上不会被抛出,而是作为实现Parcelable协议的常用对象发送 捕获我的XMPPException并抛出一个RemoteException(

我目前正在Android上开发一个XMPP应用程序,我正在考虑通过我的服务向我的活动抛出不同类型的异常而不是RemoteException的最佳方法

由于似乎不可能使用IPC抛出除RemoteException之外的其他东西(您不能声明在.aidl中抛出任何东西),我只看到两种解决方案:

  • 为我的活动创建一个侦听器,以侦听我的自定义XMPP异常,该异常实际上不会被抛出,而是作为实现Parcelable协议的常用对象发送

  • 捕获我的XMPPException并抛出一个RemoteException(其中一个内容用我的XMPPException更新)——但是在这种情况下,我怎么知道我的活动是XMPP还是真正的RemoteException呢?通过标记异常的名称并在我的活动中解析它?那真的是戈尔

你知道吗?我是否错过了SDK文档中的某些内容

谢谢。

如果#1表示我认为它的作用,我会使用它——让服务捕获异常并调用由活动创建和提供的AIDL定义的回调对象上的方法


在我的一本书中,您可以在本和项目中看到该技术的一个示例。

看起来我们可以抛出从RemoteException派生的自定义异常。因此,您可以使用XMPPRemoteException,也可以只使用一个通用的MyRemoteException来保存原始异常。下面是第二个案例的演示:

服务器:

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

try {
    service.someCall();
}
catch(MyRemoteException e) {
    rethrow(e);
}
助手方法:

private void rethrow(MyRemoteException e) throws Exception {
    if(e.innerException instanceof XMPPException)
        throw (XMPPException)e.innerException;
    else
        throw e.innerException;
}
例外情况:

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

    public MyRemoteException() {}

    public MyRemoteException(Exception innerException) {
        this.innerException = innerException;
    }
}
    @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!");
    }
...
}

我认为不可能实现“将自定义异常从服务抛出到活动”。 请参见地块资源:

    /**
 * 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);
}
所以我们可以知道,我们可以把这五个异常抛在上面

例如: 如果您的服务引发IllegalArgumentException:

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

    public MyRemoteException() {}

    public MyRemoteException(Exception innerException) {
        this.innerException = innerException;
    }
}
    @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!");
    }
...
}
您的客户将能够捕捉到它:

            try {
                printer.addImage(0, null);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }

是的,我看了你的代码,我正在谈论这个。我会用的,这一定是正确的方法。但谷歌不允许我们抛出另一种例外,这有点奇怪。也许在SDK的未来版本中。感谢您的建议:)当服务同步处理请求时,自定义异常很好。若请求是异步处理的,则将使用对客户端的回调(请参阅@commonware.com response)。E/JavaBinder(1544):***未捕获的远程异常!(进程之间还不支持异常。)这种方法对我不起作用。它对我也不起作用。MyRemoteException将被框架捕获并记录,并且将在客户端生成一个新的不相关的RemoteException。否决这个答案。如果其中一个答案对你有用,别忘了接受。它可以帮助未来的观众知道哪个答案对你帮助最大。谢谢