Генерирует пользовательское исключение из службы в действие
Вопрос
В настоящее время я работаю над приложением XMPP на Android, и я размышляю о лучшем способе создать исключение другого типа, чем RemoteException, для моей активности из моего сервиса.
Поскольку кажется невозможным создать что-то другое, кроме RemoteException, используя IPC (вы не можете объявить, что в вашем .aidl что-либо выбрасывается), я просто вижу два решения:
Создайте прослушиватель для моей активности для прослушивания моего пользовательского исключения XMPP, которое на самом деле не будет выдано, а просто отправлено как обычный объект, реализующий Parcelable протокол.
Перехватите мое XMPPException и выдайте RemoteException (с содержимым, обновленным с помощью моего XMPPException) - Но в таком случае, как я могу узнать по моей активности, является ли это XMPP или реальным RemoteException ?Пометив имя исключения и проанализировав его в моей активности ?Это было бы действительно ужасно.
У тебя есть какие - нибудь идеи ?Я что - то пропустил из документации SDK ?
Спасибо.
Решение
Если # 1 означает то, что я думаю, я бы использовал это - попросил службу перехватить исключение и вызвать метод для объекта обратного вызова, определенного AIDL, созданного и предоставленного activity.
Вы можете увидеть пример этой техники в этом клиент и Обслуживание проект из одной из моих книг.
Другие советы
Похоже, что мы можем создавать пользовательские исключения, производные от 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;
}
}
Я думаю, что невозможно добиться "Выбросить пользовательское исключение из сервиса в действие".Смотрите ресурс Посылки:
/**
* 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:
@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();
}