انشاء الـ Bound Service

Mohammad Laifمنذ 3 سنوات

بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته

 

في الدرسين السابقين رأينا طريقة انشاء الـ Started Service والـ Intent Service. في هذا الدرس سنرى طريقة تحويلهم او بالاحرى انشاء النوع الـ Bound Service.

 

طريقة عمل هذة الكلاس:
هذا النوع عباره عن Service عاديه كالـ Started Service و IntentService, ولكن الاختلاف هنا هو استخدام الدالة onBind() لإرجاع عنصر لاصق (binder) بعد انشائه بداخلها وهنا تتحول الى هذا النوع. وللمخاطبه بين هذا النوع والمكون الذي قام بتشغيلها(كالـ Activity) نحتاج الى انشاء عنصر من نوع Service Connection في المكون نفسه حتى تستطيع التخاطب معها.

 

نقاط يجب عليك مراعاتها عند العمل مع هذا النوع من الخدمات

  • تعمل في الخيط الرئيسي (Main/UI Thread) لذلك يجب عليك مراعاة عدم استخدامها للمهام الثقيلة.
  • نستطيع تشغيلها من خلال المكونات التالية: Activities  و Content Provider و Service, ولكننا لانستطيع استخدام المكون Broadcast لتشغيلها.
  • تلتصق (Bound) بالمكون الذي قام بتشغيلها. ونستطيع كذلك لصقها باكثر من مكون واحد.
  • تستطيع التخاطب كـ ارسال واستقبال وتبادل البيانات والنتائج مع المكون الملتصقه به. اي اننا لانحتاج للتعامل مع ResultReceiver او Local Broadcast (نحتاج فقط لإنشاء ServiceConnection في المكون).
  • نستطيع تشبيهها بالخادم (Server) والمكون الذي قام بتشغيلها والتصق بها نستطيع تشبيهه بالعميل (Client).
  • تقوم باطفاء نفسها عندما يتم انهاء جميع المكونات الملتصقة بهم.

 

الهدف
انشاء كلاس Service تقوم بأخد معطيان رقمان ثم تقوم بجمعهم وطباعة الناتج في الـ Log.

 

 طريقة انشاء كلاس من نوع الـ Started Service

  • انشاء كلاس جديدة.
  • عمل Extends لكلاس الـ Service.
  • اضافتها الى ملف الـ Manifest.xml.
  • نعمل Override للدوال:
    • onBind() حتى نقوم بإرجاع هذة الكلاس لإلصاقها للمكون المراد.
    • انشاء عنصر من نوع Binder في داخل هذه الكلاس للصقها مع المكون.
    • انشاء عنصر من نوع ServiceConnection لإنشاء التخاطب مع المكون الذي ستلتصق به.

 

الخطوات

انشاء كلاس جديدة وجعلها تعمل extends لكلاس الـ IntentService:

public class MyBoundService extends Service {}

 

اضافتها الى ملف الـ Manifest.xml:

<service android:name=".service.MyBoundService"/>

 

انشاء كلاس داخليه من نوع Binder وبها داله لإرجاع كلاس هذه الـ Service:

    public class MyBinder extends Binder {

        public MyBoundService getService() {
            return MyBoundService.this;
        }

    }

 

عمل حقل للـ Binder:

private MyBinder mMyBinder = new MyBinder();

 

عمل Override للداله onBind ونقوم بإنجاز هذه المهام بداخلها: الشفره المراد تشغيلها, و حفظ الشفره في الحقل عن طريق Setter واخيراً تقوم بارجاع حقل الـ Binder:

   @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: Called.");

        int firstNumber = intent.getIntExtra(Constant.FIRST_NUMBER, -1);
        int secondNumber = intent.getIntExtra(Constant.SECOND_NUMBER, -2);

        int resultNumber = firstNumber + secondNumber;
        mMyBinder.getService().setResult(resultNumber);

        return mMyBinder;
    }

 

الكلاس كامله:

public class MyBoundService extends Service {

    private static final String TAG = "MyBoundService";
    private MyBinder mMyBinder = new MyBinder();
    private int mResult = -1;

    // Our Binder Class
    public class MyBinder extends Binder {

        public MyBoundService getService() {
            return MyBoundService.this;
        }

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: Called.");

        int firstNumber = intent.getIntExtra(Constant.FIRST_NUMBER, -1);
        int secondNumber = intent.getIntExtra(Constant.SECOND_NUMBER, -2);

        int resultNumber = firstNumber + secondNumber;
        mMyBinder.getService().setResult(resultNumber);

        return mMyBinder;
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }


    private void setResult(int resultNumber) {
        mResult = resultNumber;
    }

    // Used to send bound
    public int getResult() {
        return mResult;
    }

}

قمنا باستقبال البيانات من الـ Activity من خلال الـ Intent في الداله onBind. ثم قمنا بحفظ النتيجه باستخدام Setter الى الحقل mResult. لاحظ ايضاً وجود الداله getResult من نوع Getter لهذا الحقل, حيث اننا سنستخدمها في الـ Activity للحصول على النتيجه.

 

طريقة نقل البيانات: تقنية الـ Bound تسمح لنا بالدخول الى دوال الـ Getter الموجوده في الـ Service من المكون الملتصقه به (في مثالنا المكون هو Activity).

 

 

في كلاس الـ Actiivty:

نقوم بإنشاء الحقول:

private TextView mResultTextView;
private boolean isBound = false;
private MyBoundService mMyBoundService;

private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        isBound = true;

        MyBoundService.MyBinder myBinder = (MyBoundService.MyBinder) service;
        mMyBoundService = myBinder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        isBound = false;
        }
};
  • الحقل الاول هو عباره عن الـ View.
  • الحقل الثاني هو عباره عن boolean لنحدد هل السيرفس في حاله Bound ام لا.
  • الحقل الثالث MyBoundService هو حقل للكلاس السيرفس التي انشئناها.
  • اما الـ ServiceConnection فهو وسيلة الربط واستلام المعلومات من كلاس الـ Bound الى هذه الـ Activity.
  • الداله onServiceConnected تعمل عند عمل Bound للسيرفر. لذلك قمنا بجعل عنصر الـ Bound الى true. وايضاً قمنا بعمل init للحقل mMyBoundService بداخلها باستخدام الـ Binder الذي انشئناه سابقاً.

 

عمل Bound للسيرفس:

نقوم بعمل Override للداله onStart وننشئ بداخلها الـ Intent التي ستعمل Bound كالتالي:

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(Main6Activity.this, MyBoundService.class);
        intent.putExtra(Constant.FIRST_NUMBER, 10);
        intent.putExtra(Constant.SECOND_NUMBER, 20);
        bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
    }

لاحظ استخدمنا bindService لعمل Bound لهذه السيرفس (وليس startService) والتي تأخد عنصر ServiceConnection و نوع الـ Bound (هنا اخترنا النوع BIND_AUTO_CREATE).

 

نقوم بعمل Override للداله onDestroy لإزالتها حتى لاتحدث مشاكل في الذاكرة:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);
    }

 

حل تشغيل مهمه طويله على هذا النوع

من الافضل عدم استخدامها للمهام الطويله او قم باستخدام احد انماط الخيوط الحاسوبية كما اتى شرحهم في الدروس السابقه.

 

في هذا الدرس رأينا طريقة انشاء الخدمة من نوع الـ Bound Service وكيفية انشاء ServiceConnection لربطها مع الكون الذي قام بتشغيلها, حتى تستطيع نقل البيانات والنتائج اليه بكل سهوله ويسر. في الدرس القادم سنرى طرق مساعدة لجعل الـ Started Service و الـ Intent Service تستطيع نقل البيانات والنتائج الى المكون الذي قام بتشغيلها.

 

رابط الكلاسات المستخدمه في هذا الدرس

للحصول على رابط المشروع راجع درس المقدمة.
 

المصادر والمراجع

للمزيد راجع درس المقدمة.

 

نهاية الدرس
لاتنسى تتبع الدرس والدورة كذلك لإشعارك عندما يتم التعديل على المتحوى او اضافة المزيد من المعلومات. ايضاً لاتنسى الاعجاب بالدرس ومشاركته مع الاخرين.

المحاضر

Mohammad Laif

محتوى الدورة

تمهيد
1 مقدمة
2 تعرف على التزامن (الـ Concurrency)
3 اخطاء التزامن (الـ Concurrency) الشائعة
العمليات Processes
1 الهيكلة الهندسية لبيئة نظام الاندرويد
2 طبقة الـ Android Runtime و العمليات Processes
3 انواع العمليات (Processes)
الخيوط الحاسوبية Threads
1 الخيوط الحاسوبية (Threads)
2 مكونات الخيوط الحاسوبية (Thread)
3 انشاء الخيط الحاسوبي
أنماط التصميم للخيوط الحاسوبية
1 انشاء نمط الـ Handler و Looper و Thread
2 انشاء نمط الـ HandlerThreads
3 ماهو نمط الـ Thread Pools (الـ Executors)
4 استخدام نمط الـ Thread Pools كـ Singleton
5 استخدام الـ Callable مع نمط الـ Thread Pools
6 انشاء بركة خيوط حاسوبية Thread Pools لتسريع قاعدة البيانات
7 انشاء نمط الـ AsyncTask
8 انشاء نمط الـ Loader
الـ Broadcasts
1 تعرف على الـ Broadcast Receiver
2 انشاء الـ Broadcast Receiver بشكل ثابت
3 انشاء الـ Broadcast Receiver بشكل ديناميكي
4 استخدام الـ Local Broadcast للتخاطب بين المكونات
الـ Services
1 تعرف على الـ Services
2 انشاء الـ Started Service
3 انشاء الـ Intent Service
4 انشاء الـ Bound Service الدرس الحالي
5 استخدام الـ ResultReceiver للتخاطب مع الـ Intent Service
6 استخدام الـ Broadcast للتخاطب مع الـ Started Service
الـ Alarm Manager
1 تعرف على الـ Alarm Manager
2 طرق استخدام الـ Alarm Manager
الـ Jobs
1 استخدام الـ Android JobSchedualer
2 استخدام الـ Firebase JobDispatcher
3 استخدام الـ WorkManager من حزمة JetPack

الكلمات الدليلية

عن الدرس

0 إعجاب
1 متابع
0 مشاركة
1667 مشاهدات
منذ 3 سنوات

التعليقات (0)

لايوجد لديك حساب في عالم البرمجة؟

تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !