أنواع الـ BroadcastReceiver الجزء الثالث

abdulrahman-abdullahمنذ 6 سنوات

بسم الله الرحمن الرحيم 

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

تكلمت في مقالتين سابقتين عن الـ Broadcast 

في هذي المقالة سأتكلم عن أنواع الـ Broadcast و الفرق بين كل نوع و أخر . 

كما تعلم عزيز القارئ ان الـ Broadcast ينقسم الى أربع أنواع- تكلمت عنها في المقالة السابقة-  وهي مقسمة كما في الصورة التالية : 

types-broadcast.thumb.PNG.9d980eec2ec08a61f4b8d7616836dc6d.PNG

 

النوع الأول وهــو الـ Normal : 

  • يستخدم دالة الــ sendBroadcast 
  • غير متزامن عند عملية التنفيذ .

  في المقالة السابقة ، شرحت هذا النوع بالتفصيل . 

 

النوع الثاني وهــو الـ Ordered : 

  • يستخدم دالة الــ sendOrderedBroadcast 
  • متزامن عند علمية التنفيذ ، اي يقوم بتنفيذ العملية على حسب الأولوية . 

      كيف يعني ؟؟ 

نفرض ان لديك - Action - واحد فقط  يتم إستدعائه من ثلاث كلاسات مختلفة و ليكن اسم الكلاسات هي Class A & Class B & Class C .. 

الأن تريد تنفيذ الحدث الموجود في كلاس C قبل كلاس A أو كلاس B ، أو ربما تريد تنفيذ الحدث B ثم C ثم A .. كما في الصور التالي : 

actionA.thumb.PNG.96aaacb11d0374c62f07b65d2809c406.PNGactionB.thumb.PNG.2f5d8f9a14f001b5dde2f7782ed3f0c5.PNGactionC.thumb.PNG.a59f235bf5a10368ae9dab48c4d6d8f6.PNG

 

تم تعريف - Action - واحد في ملف - Mainfest - كما في الصورة : 

Inkedpriority-receiver_LI.jpg.9fd3ca3e0183f7e52d9c2c8bd51fb503.jpg

لاحظ عزيز المبرمج انها تم تعريف اكشن واحد بنفس الاسم ، وكذلك تم تحديد الأولوية في عملية التنفيذ من خلال - android:priority - 

أعلى قيمة يتم تنفيذها أولاً ،ثم القيم الأقل منها ..  وعند تنفيذ الطلب يتم تمرير اسم الاكشن وهو يتولى المهمة عنك 

MainActivity.java


public class MainActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent("uniq.action");
        sendOrderedBroadcast(intent,null);
    }
}

لاحظ انه تم تمرير اسم الــ Action عند إنشاء أوبجكت من كلاس الــ Intent .

 

اقتباس

قبل  شرح النوع الثالث ما رأيك بإن تأخذ رشفة من قهوتك المفضلة ثم تعود لتستمع بجمال الأندرويد ?

 

النوع الثالث  الــ Sticky Broadcast  : 

يعمل هذا النوع من الـ Broadcast بنفس آلية عمل الـ Normal Broadcast  و لكن الفرق 

الــ Normal ينفذ الحدث و ينتهي عمل الــ Broadcast أي يعمل بمبدأ الــ 

Dies Quickly Broadcast 

أما الــ Sticky Broadcast يبقى قريب من التطبيق حتى بعد تنفيذ الحدث - event - ويراقب- أو ينتظر بمعنى-  أخر وقوع الحدث مرة أخرى 

أي انه ينفذ ثم ينتظر .. ينفذ ينتظر .. وهكذا .

في الأصدارات ما قبل 21 كأن يستخدم دالة sendStickyBroadcast و لكن من إصدار 21 و ما فوق تم التجاهل و التخلي عن هذي الدالة 

لأسباب تتعلق بضعف الحماية . 

ربما تقول بما أنه تم تجاهل هذا النوع لماذا نتطرق له ؟ 

      مازال توجد بعض الــ Actions تستخدم هذا النوع وهي : 

Action_Battery_Changing 

  1.    Battery_Status_Charging 
  2. Battery_Status_Discharging
  3. Battery_Status_Full
  4. Battery_Status_Plugged_USB

Action_Device_Storage_Low 

Action_Dock_Event 

هذا جزء من الــ Documentation  : 

recap_where_sticky_use.PNG.e6fb7a8375d1ef6fc69a82a9cda256d0.PNG

هذي الــ Actions تبقى قريبة من النظام وكذلك من التطبيقات فعند حدوث أي منها يتم إرسال تنبيه الى التطبيقات 

فالنفرض ان لدي تطبيق يظهر حالة التغير في البطارية وعند كل تغير يقوم بتنفيذ حاجة معينة 

مثال عملي : تطبيق يظهر نص التغير في حالة البطارية ويظهر لي نص بذلك . 


public class MainActivity extends AppCompatActivity {
    private TextView mText ;
    private int ctr = 0
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mText = findViewById(R.id.txv_show_mes);
    }
    // object of BroadcastReceiver.
      BroadcastReceiver receiver = new BroadcastReceiver() {
       @Override
       public void onReceive(Context context, Intent intent) {
            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,-1);
            displayStatus(status);
        }
    };
    // call registerReceiver method .
    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter mIntent = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(receiver,mIntent);
    }
    // call unregisterReceiver method .
    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

    private void displayStatus(int status){
       switch (status){
           // تستطيع العودة الى الارقام المذكرو من كلاس الــ
           // BatteryManager.java
           case 1 :
               setmText("Battery Status Unknown ");
               break;
           case 2:
               setmText("Battery Status Charging");
               break;
           case 3 :
               setmText("Battery Status Discharging");
               break;
           case 4:
               setmText("Battery Status Not Charging.");
                break;
           case 5:
               setmText("Battery Status Full .");
               break;
           default:
               setmText("");
       }
    }
    private void setmText(String str){
        mText.setText(str);
    }

}

 

 تغير وضع حالة البطارية  من خلال : 

declaer_battery_p1.thumb.PNG.a75adaa33f79ed4babb47da33a9eb517.PNG

الأن عند تغير كل قيمة يظهر لي نص بحالة البطارية : 

full.thumb.png.20211a1ed509259ac9584ed3795dfaac.pngbattery_charging.thumb.png.882fc1a70f43ade967658deafcac8d9d.pngdisCharging.thumb.png.20625dec007922ebc094babd67f4fa68.png

 

 

 النوع الرابع  وهــــو الــ LocalBroadcast : 

هـــو عبارة عن ارسال و استقبال بيانات محلية - local - من داخل التطبيق أو من تطبيق الى تطبيق أخر . 

أي بمعنى -  لا يستقبل بيانات من النظام و لا يرسل بيانات الى النظام . 

           من مميزات الـــ LocalBroadcast هي التواصل : 

  1. بين الــ Activities 
  2. بين الــ Activity  و Service 
  3. بين الــ Activity  و الــ Broadcast 
  4. بين الــ Service و  الــ Broadcast ، وكذلك العكس 
  5. بين التطبيقات مثلا تطبيق A يرسل بيانات الى التطبيق B -  إذا تم تمهيد  وقبول التصاريح

 

 يعتبر  هذا النوع من الـ Broadcast  الأكثر حماية لأنه :

  1.  يعمل داخل التطبيق فقط . 
  2. الـ Broadcast لا يخرج من التطبيق . 
  3. وكذلك التطبيقات الأخر لا يمكنها الوصول الى الــ receiver لأن نوع الـ Action يكون خاص بالتطبيق فقط . 
  4. أكثر فعالية لعدم تسريب البيانات خارج التطبيق. 

 

صورة لتوضيح طريقة عمل هذا النوع : 

LocalBroadcast-p2.thumb.png.44ec3b288fa262e2b066d9e704f094e6.png

 

أخيراً ،  مثال عملي لهذا النوع من الــ Broadcast ، هـــو عمل برنامج ارسال بيانات من الــ Activity الى BroadcastReceiver -   كما هو موضح في الصورة السابقة 

MainActivity.java 


public class MainActivity extends AppCompatActivity {
    LocalBroadcastManager mLocal ;
    EditText num1,num2 ;
    TextView txvResult ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        num1 = findViewById(R.id.edt_num1);
        num2 = findViewById(R.id.edt_num2);
        txvResult = findViewById(R.id.txv_result);
        mLocal = LocalBroadcastManager.getInstance(this);
    }

    public void sendLocalBroadcast(View view) {
        Intent sendIntent = new Intent(this,MyReceiver.class);

        // set two numbers ..
        int a1 = Integer.valueOf(num1.getText().toString());
        int a2 = Integer.valueOf(num2.getText().toString());
        sendIntent.putExtra("a1",a1);
        sendIntent.putExtra("a2",a2);
        // Send Normal Broadcast ..
        sendBroadcast(sendIntent);
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter("my.result.sum");
        mLocal.registerReceiver(receiver,intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mLocal.unregisterReceiver(receiver);
    }

    // Dynamic Receiver ...
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            int sum = intent.getIntExtra("sum",0);
            txvResult.setText(String.valueOf(sum));
        }
    };
}

MyReceiver.java 


public class MyReceiver  extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {

        int a1 = intent.getIntExtra("a1",-1);
        int a2 = intent.getIntExtra("a2",-1);

        int sum = a1 + a2 ;
        LocalBroadcastManager localBroadcast= LocalBroadcastManager.getInstance(context);
        // declare new intent to put in send broadcast .
        Intent sendIntent = new Intent("my.result.sum");
        sendIntent.putExtra("sum",sum);
        // Now this value of sendIntent send to localBroadcast, And in MainActivity, I'll declare new Dynamic receiver
        // To take this value.
        localBroadcast.sendBroadcast(sendIntent);

    }
}

AndroidMainfest.xml 


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".MyReceiver"/>
    </application>

 

 

Screenshot_1510694750.thumb.png.9a584df7c49b60bc1842837b25b9698e.png

 

ما تم عمله : 

  1. إنشاء  حلقين من نوع EditText  لكتابة الارقام .
  2. عمل دالة لانشاء حدث عند الضغط على زر الارسال  .  
  3. في داخل هذا الاكشن تم إنشاء اوبجكت من كلاس Intent ويشير الى كلاس الــ MyReceiver  . 
  4. بعد ذلك يتم ارسال البيانات من خلال استخدام دالة الــ sendBroadcast 
  5.  كلاس الــ MyReceiver  يرث من كلاس الــ BroadcastReceiver ويستقبل عددين مرسل له من كلاس الــ MainActivity . 
  6. إنشاء متغير جديد يقوم بعملية جمع المتغيرين ، ثم يرسلها الى MainActivity من خلال LocalBroadcastManager  . 
  7. في كلاس ال MyReceiver تم إنشاء اوبجكت من كلاس الــ Intent و وضع اسم للاكشن ، بحيث يتم استقبال هذا الاكشن في كلاس الــ MainActivity  عن طريق عمل dynamic receiver . 
  8. في كلاس الــ MainActivity  تم إنشاء اوبجكت من كلاس الــ LocalBroadcastManager  ، بحيث يكون هذا الاوبجكت هو المسؤول عن تسجيل receiver عند تشغيل التطبيق 
  9. في الأخير تم إنشاء حقل من نوع TextView لعرض النتيجة المرسلة من كلاس MyReceiver  في الــ MainActivity . 

 

"في الأخير لاحظ ان هذا النوع من الــ Broadcast يستخدم الــ طريقة الــ statically broadcast مع طريقة الــ dynamic broadcast   " 

 

 

 

أتمنى أني وفقت في تبسيط إيصال المفاهيم ،  وأعتذر على الاطالة .      

هذا وإن كان من صواب فمن الله ،، وإن كان من خطأ فمن نفسي و الشيطان . 

سبحانك اللهم وبحمدك أشهد أن لا إله إلا أنت أستغفرك وأتوب اليك . 

 

 

كلمات دليلية:
1
إعجاب
3598
مشاهدات
0
مشاركة
0
متابع
متميز
محتوى رهيب

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

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

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