Эти исключения действительно бросаются, и вы должны написать соответствующую логику try/catch, чтобы справиться с ситуацией, когда удаленный метод, который вы вызывали в службе, не был завершен.
Что касается вашего расследования, вы были на правильном пути, просматривая родные источники. Что вы, возможно, упустили, так это то, что android.os.RemoteException
на самом деле просто базовый класс для других связанных с Binder исключений и что это подкласс, android.os.DeadObjectException
, который брошен в пределах native code of Binder.
Активность увидит это исключение, если оно использует сервис, запущенный в другом процессе, который умирает в середине выполнения запроса. Я смог доказать это себе, сделав следующие незначительные изменения в Marko Gargenta's AIDLDemo example.
Прежде всего, убедитесь, что служба запускается в собственном процессе, обновив 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 не туннелирует исключения между процессами. Если вам нужно сообщить об ошибке в вызывающую деятельность, вам необходимо использовать другие средства.
Hi Tim. Какой хороший ответ! Моя служба работала в другом процессе, и я видел DeadObjectExceptions здесь и там во время стресс-тестирования. Alway, когда я использовал оболочку и убил сервисный процесс, пока работало связанное приложение. Ошибка DeadObjectException всегда была в моем списке дел.Теперь, когда я знаю, что они всего лишь подкласс RemoteException, я знаю, что делать. Большое вам спасибо. Я оставляю вопрос открытым еще на один день, если кто-то еще более проницателен! Cheers, Nils –
@Nils Pipenbrinck Glad Я мог бы помочь. Кроме того, теперь, когда вы приняли мой ответ, могу ли я помешать вам присудить награду? –
Я не знал, что вы должны его наградить. Я думал, что это связано с ответом .. :-) –