因此,我为Android OS写了一项服务和活动。

我的服务在其自己的过程中运行,因此我的活动与服务之间的所有通信都是通过IPC进行的。我为此使用标准的Android .AIDL机制。

到目前为止,一切都很好。但是,AIDL使用“ Remoteexception”生成所有方法存根,因此我必须处理它们。

我在整个Android源代码上进行了快速的GREP,只发现了三种例外情况。这些是我不连接的不同服务。

我也检查了C源,因为从理论上讲,可以使用JNI界面生成Remoteexceptions ..什么都没出现。

我的印象是每个人都这样处理:

  try {

    mService.someMethodCall (someArguments);

  } catch (RemoteException e) {

    e.printStackTrace();

  }

这不是可靠的代码,我不希望在我的代码库中这样的东西。

除此之外:我试图通过IPC自己进行remoteexception,而我所得到的只是堆栈跟踪和系统日志消息,告诉我尚未支持例外。我的应用程序从未看到过例外,而抛出例外的服务最终处于一个非常奇怪的状态(中途工作):-(

问题是:

  • 这些例外是否被抛弃了?

  • 有没有人见过这样的尝试捕捉障碍,抓住了remoteexception?

  • 难道他们不存在,而我们只是被迫与他们打交道,因为“ thr thr thr thr thr the the dead Code”或AIDL编译器内部的剩下的代码?

Disclamer:我还没有阅读整个源代码。我使用GREP找到了Remoteexception的出现,因此由于使用不同的使用情况,我可能会错过一些。

有帮助吗?

解决方案

这些例外确实确实被抛弃了,您应该编写适当的尝试/捕获逻辑来处理您在服务上调用的远程方法未完成的情况。

就您的调查而言,您正在正确的轨道上浏览本地资源。您可能忽略了 android.os.RemoteException 实际上只是用于其他粘合剂相关例外的基类,它是一个子类, android.os.DeadObjectException, ,被扔在 粘合剂的本地代码.

如果它利用在执行请求中间死亡的另一个过程中运行的服务,则活动将看到此异常。我能够通过对以下较小的更改来证明自己 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> 

然后修改 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;
        }

    };
}

在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

我可以想象,如果您的服务在与您的活动相同的过程中运行,您可能永远不会看到此例外,但是如果是这种情况,您可能不会对AIDL感到困扰。

此外,正如您发现的那样,Android不会在过程之间隧道异常。如果您需要将错误传达回通话活动,则需要使用其他方式。

其他提示

如果是 过程 托管远程对象不再可用,这通常意味着该过程崩溃了。

但是,以前的评论以及官方的Android文档对DeadoBjectException是唯一被送回客户的例外是错误的。在您的AIDL服务实施中抛出的某些类型的Runtime Exceptions将转回客户端并在此转移。如果您查看binder.exectransact()方法,您会发现它会捕获RuntimeException并将选择的几个回到客户端。

下面列出了接受此特殊待遇的Runtime Exceptions。您也可以检查Parcel.WriteException以验证。活页夹类使用该方法将异常填充到包裹中,然后将其转移回客户,在该客户将其作为Parcel.ReadException的一部分重新启用。

  • SecurityException
  • BadParcelableException
  • 非法征收exception
  • 空指针异常
  • 非法施加感受
  • NetworkOnMainThreadException
  • 无支撑的exception

我偶然地偶然发现了这种行为,我在客户端看到了出乎意料的例外,而当它应该在illegalstateexception上时,我的服务并没有崩溃。完整写入:https://blog.classycode.com/dealing-with-exceptions-in-aidl-9ba904c6d63

“尚未跨流程支持”是这里的关键。 remoteexception的确被抛出,但不是直接的。 每一个 在处理AIDL呼叫时,在远程服务中抛出的例外将导致您的申请收到Remoteexception。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top