سؤال

حتى لقد كتب الخدمة و نشاط على نظام التشغيل أندرويد.

بلدي تشغيل الخدمة في العمليات الخاصة ، لذلك جميع الاتصالات بين الأنشطة والخدمات يحدث عن طريق التصنيف.يمكنني استخدام الروبوت القياسية .aidl آلية هذا.

حتى الآن كل شيء يعمل بشكل جيد.ومع ذلك ، فإن AIDL يولد كل طريقة بذرة باستخدام "يلقي RemoteException" لذلك يجب التعامل معها.

لم سريعة البقرى على كامل الروبوت المصدر-رمز فقط وجدت ثلاث حالات هذا الاستثناء هو القيت من أي وقت مضى.هذه هي في خدمة مختلفة لا اتصال مع.

راجعت ج-مصادر لأنه من الناحية النظرية RemoteExceptions يمكن إنشاؤها باستخدام JNI واجهة..لم يظهر شيء.

لدي انطباع أن الجميع يتعامل مع مثل هذه:

  try {

    mService.someMethodCall (someArguments);

  } catch (RemoteException e) {

    e.printStackTrace();

  }

هذه ليست صلبة رمز, و أنا لا أريد شيئا من هذا القبيل في بلدي رمز قاعدة.

وبالاضافة الى ذلك:حاولت رمي RemoteException عبر IPC نفسي و كل ما حصلت عليه هو كومة و تتبع نظام تسجيل رسالة يقول لي أن الاستثناءات غير معتمدة حتى الآن.طلبي لم ير الاستثناء والخدمات التي رمى الاستثناء انتهى في حالة غريبة جدا (نصف عامل) :-(

الأسئلة هي:

  • هل هذه الاستثناءات من أي وقت مضى الحصول على القيت ؟

  • وقد أي شخص من أي وقت مضى رأيت مثل هذه المحاولة-catch اصطياد RemoteException?

  • يمكن أن يكون لا وجود لهم و أننا فقط اضطر للتعامل معهم لأن "يلقي RemoteException" هو رمز ميت أو اليسار أكثر داخل AIDL ومترجم ؟

Disclamer:أنا لم أقرأ كامل شفرة المصدر.اعتدت البقرى للعثور على التكرارات RemoteException لذا قد غاب عن بعض بسبب اختلاف بيضاء الاستخدام.

هل كانت مفيدة؟

المحلول

هذه الاستثناءات لا بل على طرح و يجب أن تكتب المناسبة حاول/catch المنطق في التعامل مع الوضع فيها عن بعد طريقة الاحتجاج على خدمة لم يكمل.

بقدر التحقيق الخاص بك, كنت على الطريق الصحيح يبحث من خلال المصادر الأصلية.ما كنت قد تجاهله هو أن android.os.RemoteException هو في الواقع مجرد قاعدة الطبقة الأخرى الموثق ذات الصلة استثناءات وأنه هو فئة فرعية ، android.os.DeadObjectException, الذي طرح في الأم رمز من الموثق.

النشاط سوف نرى هذا الاستثناء إذا كان يجعل من استخدام خدمة قيد التشغيل في عملية أخرى أن يموت في منتصف إجراء الطلب.كنت قادرا على إثبات هذا بنفسي من خلال جعل التالية تغييرات طفيفة على ماركو 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.

بالإضافة إلى ذلك, كما يمكنك اكتشاف الروبوت لا النفق استثناءات بين العمليات.إذا كنت بحاجة إلى التواصل خطأ مرة أخرى إلى الدعوة النشاط ثم تحتاج إلى استخدام وسائل أخرى.

نصائح أخرى

RemoteException يتم طرح إذا كان عملية استضافة كائن بعيد لم تعد متوفرة ، وهو ما يعني عادة عملية تحطمت.

ومع ذلك ، فإن التعليق السابق و أيضا الروبوت الرسمية الوثائق عن DeadObjectException يجري الاستثناء الوحيد القيت من أي وقت مضى مرة أخرى إلى العميل.بعض أنواع RuntimeExceptions القيت في AIDL تنفيذ الخدمة سيتم تمريرها إلى العميل rethrown هناك.إذا كنت نلقي نظرة على الموثق.execTransact (طريقة) ، سترى أنه يمسك RuntimeException ويمر قلة مختارة مرة أخرى إلى العميل.

على RuntimeExceptions التي تتلقى هذه معاملة خاصة مدرجة أدناه.يمكنك أيضا التحقق من الطرود.writeException للتحقق.هذا الأسلوب يستخدم من قبل الموثق فئة المشير الاستثناء في الطرود ونقلها مرة أخرى إلى العميل ، حيث سيكون rethrown كجزء لا يتجزأ من.readException.

  • SecurityException
  • BadParcelableException
  • IllegalArgumentException
  • NullPointerException
  • IllegalStateException
  • NetworkOnMainThreadException
  • UnsupportedOperationException

أنا تعثرت على هذا السلوك عن طريق الصدفة كنت ترى غير متوقعة الاستثناءات على جانب العميل ، الخدمة لا تحطمها عندما يجب على IllegalStateException.كامل writeup:https://blog.classycode.com/dealing-with-exceptions-in-aidl-9ba904c6d63

"الاستثناءات غير معتمدة حتى الآن عبر عمليات" هو المفتاح هنا.RemoteException هي في الواقع القيت ، ولكن ليس بشكل مباشر. كل استثناء القيت في جهاز التحكم عن بعد خدمة في حين aidl الدعوة التي يجري التعامل معها سيؤدي في RemoteException يتم استلامها من قبل التطبيق الخاص بك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top