Frage

Also ich habe einen Dienst und eine Tätigkeit für das Android OS geschrieben.

Mein Service wird in einem eigenen Prozess ausgeführt, so die gesamte Kommunikation zwischen meinen Aktivitäten und der Service erfolgt über IPC. Ich benutze den Standard-Android .aidl Mechanismus hierfür.

Bisher funktioniert alles einwandfrei. Allerdings erzeugt die AIDL alle Methoden-Stubs mit „wirft Remote“ so dass ich sie zu behandeln haben.

Ich habe eine schnelle grep auf dem gesamten Android-Quellcode und finde nur drei Fälle, in denen diese Ausnahme jemals geworfen wird. Diese sind in einem anderen Dienst, dass ich nicht verbinden mit.

ich die C-Quellen überprüft auch, weil in der Theorie RemoteExceptions erzeugt werden kann, die JNI-Schnittstelle .. Nichts auftauchten.

Ich habe den Eindruck, dass jeder behandelt sie wie folgt aus:

  try {

    mService.someMethodCall (someArguments);

  } catch (RemoteException e) {

    e.printStackTrace();

  }

Dies ist kein fester Code, und ich will nicht, so etwas in meiner Code-Basis.

Außerdem: Ich habe versucht, mich eine Remote über IPC zu werfen und alles, was ich bekam, war eine Stapel-Spur und eine System-Log-Nachricht, die mir sagt, dass Ausnahmen werden noch nicht unterstützt. Meine Anwendung sah nie die Ausnahme und die Dienste, die die Ausnahme ausgelöst hat in einem sehr seltsamen Zustand endete (auf halber Strecke in Betrieb): - (

Die Fragen sind:

  • Haben diese Ausnahmen jemals geworfen werden?

  • Hat jemand schon einmal einen solchen Try-Catch-Block gesehen eine Remote fangen?

  • Könnte es sein, dass sie nicht existieren und dass wir nur mit ihnen umgehen gezwungen, weil die „wirft Remote“ ist tot-Code oder ein übrig gebliebener innerhalb des AIDL Compiler?

Disclamer: Ich habe nicht den gesamten Source-Code lesen. Früher habe ich Grep das Auftreten von Remote zu finden, so dass ich einige aufgrund unterschiedlicher Leerzeichen Nutzung verpasst haben.

War es hilfreich?

Lösung

Diese Ausnahmen tatsächlich geworfen und Sie sollten geeignete try / catch-Logik schreiben, die Situation zu handhaben, wo eine Remote-Methode, die Sie auf einen Dienst aufgerufen wurden nicht abgeschlossen.

Was Ihre Untersuchung, sind Sie auf dem richtigen Weg die einheimischen Quellen der Suche durch. Was Sie übersehen haben kann, ist, dass android.os.RemoteException eine eigentlich nur eine Basisklasse für andere Binder bezogene Ausnahmen, und dass es eine Unterklasse, android.os.DeadObjectException , die in der nativen Code von Binder .

Eine Aktivität wird diese Ausnahme sehen, ob es die Nutzung einer Dienstleistung in einem anderen Prozess laufen macht, dass stirbt in der Mitte eine Anfrage durchzuführen. Ich konnte dies, indem sie die folgenden kleineren Änderungen an, mir beweisen Marko Gargenta des AIDLDemo Beispiel .

Stellen Sie zunächst sicher, dass der Dienst läuft in einem eigenen Prozess durch die AndroidManifest.xml Aktualisierung:

<?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> 

Ändern Sie dann die add Methode zur Ausfahrt vorzeitig:

@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;
        }

    };
}

In Logcat Sie den Service-Prozess sterben sehen, wird die Aktivität eines DeadObjectException und schließlich das System Respawn Serviceprozess.

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

Ich könnte mir vorstellen, wenn Ihr Service wurde im selben Prozess wie Ihre Tätigkeit ausgeführt wird, könnten Sie nie diese Ausnahme sehen, aber dann wieder, wenn das der Fall wäre, würden Sie wahrscheinlich nicht mit AIDL stört werden.

Zusätzlich ist, wie Sie entdeckt, Android nicht Tunnel Ausnahmen zwischen Prozessen. Wenn Sie einen Fehler zurück zu einer anrufenden Aktivität kommunizieren müssen, dann müssen Sie auf andere Weise verwenden.

Andere Tipps

Remote geworfen wird, wenn der Prozess , um die Remote-Objekt-Hosting ist nicht mehr verfügbar, was in der Regel bedeutet, dass der Prozess abgestürzt ist.

Doch der vorherige Kommentar, und auch die offizielle Android-Dokumentation ist falsch über DeadObjectException die einzige Ausnahme ist immer an den Client zurückgeworfen. Einige Arten von Runtime geworfen in Ihrer AIDL Service-Implementierung werden zurück an den Client übergeben und erneut ausgelöst dort. Wenn Sie einen Blick auf die Binder.execTransact () -Methode nehmen, werden Sie sehen, dass es fängt Runtime und übergibt ein paar ausgewählte zurück an den Client.

Die Runtime, die diese besondere Behandlung sind unten aufgeführt. Sie können auch Parcel.writeException überprüfen, um zu überprüfen. Das Verfahren der Binder-Klasse verwendet wird, um die Ausnahme in ein Paket zu packen und übertragen zurück an den Client, wo es als Teil Parcel.readException erneut ausgelöst werden.

  • Security
  • BadParcelableException
  • Illegal
  • Nullpointer
  • Illegal
  • NetworkOnMainThreadException
  • UnsupportedOperationException

stolperte ich über dieses Verhalten durch Zufall, ich unerwartete Ausnahmen auf der Client-Seite sah, und mein Service stürzte nicht, wenn es auf einer Illegal sollte. Voll writeup: https://blog.classycode.com/dealing-with-exceptions-in -aidl-9ba904c6d63

Die „Ausnahmen sind noch nicht über Prozesse unterstützt“ ist hier der Schlüssel. Remote die sind in der Tat geworfen, aber nicht direkt. alle Ausnahme geworfen in der Remote-Service, während ein AIDL Anruf behandelt wird in einem Remote führen wird von der Anwendung empfangen werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top