且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Android RemoteExceptions 和服务

更新时间:2023-02-13 15:14:05

这些异常确实会被抛出,你应该编写适当的 try/catch 逻辑来处理你在服务上调用的远程方法没有的情况完成.

就您的调查而言,您在浏览本地资源方面走在正确的轨道上.您可能忽略的是 android.os.RemoteException 实际上只是其他 Binder 相关异常的基类,它是一个子类,android.os.DeadObjectException,在 Binder 的原生代码.

As far as your investigation, you were on the right track looking through the native sources. What you may have overlooked is that android.os.RemoteException is a actually just a base class for other Binder related exceptions and that it is a subclass, android.os.DeadObjectException, which is thrown within the native code of Binder.

如果活动使用在另一个进程中运行的服务,该服务在执行请求的过程中终止,则该活动将看到此异常.我能够通过对 Marko Gargenta 的 AIDLDemo 示例进行以下细微更改来向自己证明这一点一>.

An activity will see this exception if it makes use of a service running in another process that dies in the middle of performing a request. I was able to prove this to myself by making the following minor changes to Marko Gargenta's AIDLDemo example.

首先,通过更新 AndroidManifest.xml 确保服务在其自己的进程中运行:

First, make sure the service runs in its own process by updating the 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方法提前退出:

Then modify the add method to exit prematurely:

@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,最终系统重新生成服务进程.

In logcat you see the service process die, the activity receive a DeadObjectException, and ultimately the system respawn the service process.

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 烦恼.

I would imagine if your service was running in the same process as your activity you might never see this exception but then again if that were the case you probably wouldn't be bothering with AIDL.

此外,正如您所发现的,Android 不会在进程之间建立异常隧道.如果您需要将错误传达回调用活动,则需要使用其他方式.

Additionally, as you discovered, Android does not tunnel exceptions between processes. If you need to communicate an error back to a calling activity then you need to use other means.