// service端实现 public class AidlService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return new ITestExceptionAidl.Stub() {
@Override public boolean testThrowException() throws RemoteException { if (true) { throw new RuntimeException("TestException"); } return true; } }; } }
// client端实现 bindService(intent, new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { ITestExceptionAidl aidl = ITestExceptionAidl.Stub.asInterface(service);
@Override public void onServiceDisconnected(ComponentName name) {
} }, Context.BIND_AUTO_CREATE);
但是这个程序实际上运行起来是这样的:
1 2 3 4 5
01-01 05:31:55.475 4868 4880 E JavaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.) 01-01 05:31:55.475 4868 4880 E JavaBinder: java.lang.RuntimeException: TestException 01-01 05:31:55.475 4868 4880 E JavaBinder: at me.linjw.demo.ipcdemo.AidlService$1.testThrowException(AidlService.java:22) 01-01 05:31:55.475 4868 4880 E JavaBinder: at me.linjw.demo.ipcdemo.ITestExceptionAidl$Stub.onTransact(ITestExceptionAidl.java:48) 01-01 05:31:55.475 4868 4880 E JavaBinder: at android.os.Binder.execTransact(Binder.java:565)
看日志里面的ITestExceptionAidl$Stub.onTransact,也就是说在service端就已经被异常打断了,并没有传给client端,而且第一个大大的”Exceptions are not yet supported across processes.”是说异常不允许跨进程吗?但是我明明记得AIDL生成的代码里面就有向Parcel写入异常啊:
public final void writeException(Exception e) { int code = 0; if (e instanceof Parcelable && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) { // We only send Parcelable exceptions that are in the // BootClassLoader to ensure that the receiver can unpack them code = EX_PARCELABLE; } else if (e instanceof SecurityException) { code = EX_SECURITY; } else if (e instanceof BadParcelableException) { code = EX_BAD_PARCELABLE; } else if (e instanceof IllegalArgumentException) { code = EX_ILLEGAL_ARGUMENT; } else if (e instanceof NullPointerException) { code = EX_NULL_POINTER; } else if (e instanceof IllegalStateException) { code = EX_ILLEGAL_STATE; } else if (e instanceof NetworkOnMainThreadException) { code = EX_NETWORK_MAIN_THREAD; } else if (e instanceof UnsupportedOperationException) { code = EX_UNSUPPORTED_OPERATION; } else if (e instanceof ServiceSpecificException) { code = EX_SERVICE_SPECIFIC; } writeInt(code); StrictMode.clearGatheredViolations(); if (code == 0) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new RuntimeException(e); } writeString(e.getMessage()); ... }
// service端改成抛出UnsupportedOperationException ppublic class AidlService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return new ITestExceptionAidl.Stub() {
@Override public boolean testThrowException() throws RemoteException { if (true) { throw new UnsupportedOperationException("TestException"); } return true; } }; } }
// client端实现还是一样,不变 bindService(intent, new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { ITestExceptionAidl aidl = ITestExceptionAidl.Stub.asInterface(service);
@Override public void onServiceDisconnected(ComponentName name) {
} }, Context.BIND_AUTO_CREATE);
这样运行的话客户端就能捕获到异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
01-01 05:49:46.770 19937 19937 E testtest: RemoteException 01-01 05:49:46.770 19937 19937 E testtest: java.lang.UnsupportedOperationException: TestException 01-01 05:49:46.770 19937 19937 E testtest: at android.os.Parcel.readException(Parcel.java:1728) 01-01 05:49:46.770 19937 19937 E testtest: at android.os.Parcel.readException(Parcel.java:1669) 01-01 05:49:46.770 19937 19937 E testtest: at me.linjw.demo.ipcdemo.ITestExceptionAidl$Stub$Proxy.testThrowException(ITestExceptionAidl.java:77) 01-01 05:49:46.770 19937 19937 E testtest: at me.linjw.demo.ipcdemo.MainActivity$3.onServiceConnected(MainActivity.java:132) 01-01 05:49:46.770 19937 19937 E testtest: at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1465) 01-01 05:49:46.770 19937 19937 E testtest: at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1482) 01-01 05:49:46.770 19937 19937 E testtest: at android.os.Handler.handleCallback(Handler.java:751) 01-01 05:49:46.770 19937 19937 E testtest: at android.os.Handler.dispatchMessage(Handler.java:95) 01-01 05:49:46.770 19937 19937 E testtest: at android.os.Looper.loop(Looper.java:154) 01-01 05:49:46.770 19937 19937 E testtest: at android.app.ActivityThread.main(ActivityThread.java:6097) 01-01 05:49:46.770 19937 19937 E testtest: at java.lang.reflect.Method.invoke(Native Method) 01-01 05:49:46.770 19937 19937 E testtest: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1052) 01-01 05:49:46.770 19937 19937 E testtest: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:942)
// 有异常的情况 public final void writeException(Exception e) { int code = 0; if (e instanceof Parcelable && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) { // We only send Parcelable exceptions that are in the // BootClassLoader to ensure that the receiver can unpack them code = EX_PARCELABLE; } else if (e instanceof SecurityException) { code = EX_SECURITY; } else if (e instanceof BadParcelableException) { code = EX_BAD_PARCELABLE; } else if (e instanceof IllegalArgumentException) { code = EX_ILLEGAL_ARGUMENT; } else if (e instanceof NullPointerException) { code = EX_NULL_POINTER; } else if (e instanceof IllegalStateException) { code = EX_ILLEGAL_STATE; } else if (e instanceof NetworkOnMainThreadException) { code = EX_NETWORK_MAIN_THREAD; } else if (e instanceof UnsupportedOperationException) { code = EX_UNSUPPORTED_OPERATION; } else if (e instanceof ServiceSpecificException) { code = EX_SERVICE_SPECIFIC; } writeInt(code); StrictMode.clearGatheredViolations(); if (code == 0) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new RuntimeException(e); } writeString(e.getMessage()); // 之后还有一些写入堆栈的操作,比较多,这里可以不看 }
public final void writeNoException() { if (StrictMode.hasGatheredViolations()) { // 如果StrictMode收集到了写违规行为会走这里,我们可以不关注它 writeInt(EX_HAS_REPLY_HEADER); ... } else { // 一般情况下会走这里 writeInt(0); } }
01-01 05:31:55.475 4868 4880 E JavaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.) 01-01 05:31:55.475 4868 4880 E JavaBinder: java.lang.RuntimeException: TestException 01-01 05:31:55.475 4868 4880 E JavaBinder: at me.linjw.demo.ipcdemo.AidlService$1.testThrowException(AidlService.java:22) 01-01 05:31:55.475 4868 4880 E JavaBinder: at me.linjw.demo.ipcdemo.ITestExceptionAidl$Stub.onTransact(ITestExceptionAidl.java:48) 01-01 05:31:55.475 4868 4880 E JavaBinder: at android.os.Binder.execTransact(Binder.java:565)
public final void writeException(Exception e) { int code = 0; if (e instanceof Parcelable && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) { // We only send Parcelable exceptions that are in the // BootClassLoader to ensure that the receiver can unpack them code = EX_PARCELABLE; } else if (e instanceof SecurityException) { code = EX_SECURITY; } else if (e instanceof BadParcelableException) { code = EX_BAD_PARCELABLE; } else if (e instanceof IllegalArgumentException) { code = EX_ILLEGAL_ARGUMENT; } else if (e instanceof NullPointerException) { code = EX_NULL_POINTER; } else if (e instanceof IllegalStateException) { code = EX_ILLEGAL_STATE; } else if (e instanceof NetworkOnMainThreadException) { code = EX_NETWORK_MAIN_THREAD; } else if (e instanceof UnsupportedOperationException) { code = EX_UNSUPPORTED_OPERATION; } else if (e instanceof ServiceSpecificException) { code = EX_SERVICE_SPECIFIC; } writeInt(code); StrictMode.clearGatheredViolations(); // code为0,代表不支持这种异常,继续把异常抛出或者创建RuntimeException抛出 if (code == 0) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new RuntimeException(e); } ... }