Вопрос

Итак, я написал услугу и деятельность для Android OS.

Мой сервис работает в своем собственном процессе, поэтому вся связь между моей деятельностью и услугой происходит через IPC. Я использую стандартный механизм Android .aidl для этого.

Пока все все работает нормально. Тем не менее, AIDL генерирует все расстройки метода, используя «бросающие remoteException», поэтому я должен справиться с ними.

Я сделал быстрый GREP на весь исходный код Android и нашел только три случая, когда это исключение когда-либо брошено. Это в другом сервисе, с которой я не связываюсь.

Я проверил C-источники, так как в теории ременныеЭксементы могут быть сгенерированы с использованием интерфейса JNI. Ничто не получилось.

У меня впечатление, что все просто обрабатывают их так:

  try {

    mService.someMethodCall (someArguments);

  } catch (RemoteException e) {

    e.printStackTrace();

  }

Это не сплошной код, и я не хочу что-то вроде этого в моей кодовой основе.

Кроме того: я пытался выбросить рементуэкспертизацию через IPC, и все, что я получил, был трассировкой стека и сообщение о системном журнале, который говорит мне, что исключения еще не поддерживаются. Мое приложение никогда не видели исключения и услуги, которые бросили исключение, заканчивалось в очень странном состоянии (на полпути, работая) :-(

Вопросы:

  • Эти исключения когда-либо бросаются?

  • Кто-нибудь когда-либо видел такой блок Try-Catch, ловящий рементуэкспертизацию?

  • Может ли быть то, что они не существуют, и что мы просто вынуждены иметь дело с ними, потому что «бросает Remoteexception» - это мертвый кодом или левый внутри компилятора AIDL?

Раскрытие: я не прочитал весь исходный код. Я использовал GREP, чтобы найти вхождения ременныхxception, поэтому я мог пропустить некоторые из-за различного использования пробелов.

Это было полезно?

Решение

Эти исключения действительно получают бросок, и вы должны написать соответствующую логику TRY / CALL для обработки ситуации, когда удаленный метод, который вы вызываете на сервисе, не завершен.

Что касается вашего расследования, вы были на правильном пути, глядя через родные источники. То, что вы могли упустить из виду, это то, что android.os.RemoteException на самом деле просто базовый класс для других исключений, связанных с связующим связующим, и что это подкласс, android.os.DeadObjectException, который брошен в Нативный код связующего.

Деятельность увидит этот искрок, если он использует службу, работающую в другом процессе, который умирает в середине выполнения запроса. Я смог доказать это себе, сделав следующие незначительные изменения в Пример Аидадемо Марко Гаргенти.

Во-первых, убедитесь, что сервис работает в собственном процессе, обновляя 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 не делает туннельные исключения между процессами. Если вам нужно сообщить об ошибке обратно к вызывающей активности, вам нужно использовать другие средства.

Другие советы

RemoteException брошен, если обработать Хостинг удаленный объект больше не доступен, который обычно означает, что процесс разбивается.

Тем не менее, предыдущий комментарий, а также официальная документация Android неверна о DEADOBJECTEXCECTION, являющейся единственным исключением, когда-либо брошенным обратно к клиенту. Некоторые типы Runtimeexceptions, брошенные в вашу реализацию службы AIDL, будут переданы обратно клиенту и там Rethrown. Если вы посмотрите на метод Binder.exectransact (), вы увидите, что он ловит runtimeexception и передает несколько немногих на клиенту.

Runtimeexceptions, которые получают это специальное лечение, перечислены ниже. Вы также можете проверить parcel.writeexception для проверки. Этот метод используется классом связующего в маршал исключение в посылку и перенести его обратно к клиенту, где он будет Rethrown в составе Parcel.Readexception.

  • SecurityException.
  • BadparcelableException.
  • ReganalArgumentException.
  • Исключение нулевого указателя
  • RegalAlStateException.
  • NetworkOnmaintHradexception.
  • UnsupportedOperationException.

Я наткнулся на такое поведение случайно, я видел неожиданные исключения на стороне клиента, и мой сервис не врезался, когда он должен на нелегальственную реакцию. Полная запись:https://blog.classycode.com/dealing-with-exceptions-in-aidl-9ba904c6d63.

«Исключения еще не поддерживаются в процессах», - это ключ здесь. Remoteexception действительно брошены, но не напрямую. КАЖДЫЙ Исключение, брошенное в вашем удаленном сервисе, когда обрабатывается вызов AIDL, приведет к получению RemoteException вашего приложения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top