Nil*_*nck 26 service android aidl remoteexception
所以我为Android操作系统编写了一个服务和一个活动.
我的服务在它自己的进程中运行,因此我的活动和服务之间的所有通信都是通过IPC进行的.我使用标准的Android .aidl机制.
到目前为止一切正常.但是,AIDL使用"throws RemoteException"生成所有方法存根,因此我必须处理它们.
我对整个Android源代码做了快速的grep,并且只发现了三个抛出此异常的情况.这些是我不联系的不同服务.
我也检查了C源代码,因为理论上可以使用JNI接口生成RemoteExceptions.没有出现任何问题.
我的印象是每个人都像这样处理它们:
try {
mService.someMethodCall (someArguments);
} catch (RemoteException e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
这不是可靠的代码,我不想在我的代码库中使用这样的东西.
除此之外:我试图通过IPC自己抛出一个RemoteException,我得到的只是一个堆栈跟踪和系统日志消息,它告诉我还不支持异常.我的应用程序从未看到异常,抛出异常的服务最终处于一个非常奇怪的状态(半途工作):-(
问题是:
是否会抛出这些异常?
有没有人见过这样的try-catch块捕获RemoteException?
难道它们不存在而且我们只是被迫处理它们,因为"抛出RemoteException"是死代码还是AIDL编译器内部的遗留问题?
免责声明:我还没有阅读完整的源代码.我使用Grep来查找RemoteException的出现,所以我可能因为不同的空格使用而错过了一些.
Tim*_*ger 54
确实会抛出这些异常,您应该编写适当的try/catch逻辑来处理您在服务上调用的远程方法未完成的情况.
就您的调查而言,您在正确的轨道上查看本地资源.您可能忽略的是,android.os.RemoteException
它实际上只是其他Binder相关异常的基类,并且它是一个子类android.os.DeadObjectException
,它被抛出在Binder的本机代码中.
如果活动使用在执行请求过程中死亡的另一个进程中运行的服务,则活动将看到此异常.通过对Marko Gargenta的AIDLDemo示例进行以下微小更改,我能够向自己证明这一点.
首先,通过更新AndroidManifest.xml确保服务在其自己的进程中运行:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.marakana" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:theme="@android:style/Theme.Light">
<activity android:name=".AIDLDemo" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--ADD THE android:process TAG TO THE SERVICE-->
<service android:name=".AdditionService" android:process=":process2"/>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>
Run Code Online (Sandbox Code Playgroud)
然后修改add
方法以提前退出:
@Override
public IBinder onBind(Intent intent) {
return new IAdditionService.Stub() {
/**
* Implementation of the add() method
*/
public int add(int value1, int value2) throws RemoteException {
Log.d(TAG, String.format("AdditionService.add(%d, %d)", value1,
value2));
System.exit(-1); // KILL THE PROCESS BEFORE IT CAN RESPOND
return value1 + value2;
}
};
}
Run Code Online (Sandbox Code Playgroud)
在logcat中,您会看到服务进程死亡,活动接收到DeadObjectException
,最终系统重新生成服务进程.
D/AdditionService( 1379): AdditionService.add(1, 1)
I/AndroidRuntime( 1379): AndroidRuntime onExit calling exit(-1)
D/Zygote ( 32): Process 1379 exited cleanly (255)
I/ActivityManager( 58): Process com.marakana:process2 (pid 1379) has died.
W/ActivityManager( 58): Scheduling restart of crashed service com.marakana/.AdditionService in 5000ms
D/AIDLDemo( 1372): onClick failed with: android.os.DeadObjectException
W/System.err( 1372): android.os.DeadObjectException
W/System.err( 1372): at android.os.BinderProxy.transact(Native Method)
W/System.err( 1372): at com.marakana.IAdditionService$Stub$Proxy.add(IAdditionService.java:95)
W/System.err( 1372): at com.marakana.AIDLDemo$1.onClick(AIDLDemo.java:81)
W/System.err( 1372): at android.view.View.performClick(View.java:2408)
W/System.err( 1372): at android.view.View$PerformClick.run(View.java:8816)
W/System.err( 1372): at android.os.Handler.handleCallback(Handler.java:587)
W/System.err( 1372): at android.os.Handler.dispatchMessage(Handler.java:92)
W/System.err( 1372): at android.os.Looper.loop(Looper.java:123)
W/System.err( 1372): at android.app.ActivityThread.main(ActivityThread.java:4627)
W/System.err( 1372): at java.lang.reflect.Method.invokeNative(Native Method)
W/System.err( 1372): at java.lang.reflect.Method.invoke(Method.java:521)
W/System.err( 1372): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
W/System.err( 1372): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
W/System.err( 1372): at dalvik.system.NativeStart.main(Native Method)
D/AIDLDemo( 1372): onServiceDisconnected() disconnected
I/ActivityManager( 58): Start proc com.marakana:process2 for service com.marakana/.AdditionService: pid=1399 uid=10037 gids={1015}
D/AdditionService( 1399): onCreate()
D/AIDLDemo( 1372): onServiceConnected() connected
Run Code Online (Sandbox Code Playgroud)
我想如果你的服务在与你的活动相同的过程中运行,你可能永远不会看到这个异常,但如果是这样的话,你可能不会对AIDL感到烦恼.
此外,正如您所发现的,Android不会在进程之间传递异常.如果您需要将错误传回给调用活动,那么您需要使用其他方法.
如果托管远程对象的进程不再可用,则抛出RemoteException ,这通常意味着进程崩溃.
但是,之前的评论以及官方的Android文档都是错误的,因为DeadObjectException是唯一被抛回客户端的例外.在您的AIDL服务实现中抛出的某些类型的RuntimeExceptions将被传递回客户端并在那里重新抛出.如果您查看Binder.execTransact()方法,您将看到它捕获RuntimeException并将选择的几个传递回客户端.
下面列出了接受此特殊处理的RuntimeExceptions.您还可以检查Parcel.writeException以进行验证.Binder类使用该方法将异常编组到Parcel中并将其传回客户端,在那里它将作为Parcel.readException的一部分重新抛出.
我意外地偶然发现了这种行为,我在客户端看到了意外的异常,并且当它应该在IllegalStateException上时我的服务没有崩溃.完整的文章:https://blog.classycode.com/dealing-with-exceptions-in-aidl-9ba904c6d63
归档时间: |
|
查看次数: |
24622 次 |
最近记录: |