أنواع الـ BroadcastReceiver الجزء الثالث
بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله
تكلمت في مقالتين سابقتين عن الـ Broadcast
في هذي المقالة سأتكلم عن أنواع الـ Broadcast و الفرق بين كل نوع و أخر .
كما تعلم عزيز القارئ ان الـ Broadcast ينقسم الى أربع أنواع- تكلمت عنها في المقالة السابقة- وهي مقسمة كما في الصورة التالية :
النوع الأول وهــو الـ Normal :
- يستخدم دالة الــ sendBroadcast
- غير متزامن عند عملية التنفيذ .
في المقالة السابقة ، شرحت هذا النوع بالتفصيل .
النوع الثاني وهــو الـ Ordered :
- يستخدم دالة الــ sendOrderedBroadcast
- متزامن عند علمية التنفيذ ، اي يقوم بتنفيذ العملية على حسب الأولوية .
كيف يعني ؟؟
نفرض ان لديك - Action - واحد فقط يتم إستدعائه من ثلاث كلاسات مختلفة و ليكن اسم الكلاسات هي Class A & Class B & Class C ..
الأن تريد تنفيذ الحدث الموجود في كلاس C قبل كلاس A أو كلاس B ، أو ربما تريد تنفيذ الحدث B ثم C ثم A .. كما في الصور التالي :
تم تعريف - Action - واحد في ملف - Mainfest - كما في الصورة :
لاحظ عزيز المبرمج انها تم تعريف اكشن واحد بنفس الاسم ، وكذلك تم تحديد الأولوية في عملية التنفيذ من خلال - 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
- Battery_Status_Charging
- Battery_Status_Discharging
- Battery_Status_Full
- Battery_Status_Plugged_USB
Action_Device_Storage_Low
Action_Dock_Event
هذا جزء من الــ Documentation :
هذي الــ 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);
}
}
تغير وضع حالة البطارية من خلال :
الأن عند تغير كل قيمة يظهر لي نص بحالة البطارية :
النوع الرابع وهــــو الــ LocalBroadcast :
هـــو عبارة عن ارسال و استقبال بيانات محلية - local - من داخل التطبيق أو من تطبيق الى تطبيق أخر .
أي بمعنى - لا يستقبل بيانات من النظام و لا يرسل بيانات الى النظام .
من مميزات الـــ LocalBroadcast هي التواصل :
- بين الــ Activities
- بين الــ Activity و Service
- بين الــ Activity و الــ Broadcast
- بين الــ Service و الــ Broadcast ، وكذلك العكس
- بين التطبيقات مثلا تطبيق A يرسل بيانات الى التطبيق B - إذا تم تمهيد وقبول التصاريح .
يعتبر هذا النوع من الـ Broadcast الأكثر حماية لأنه :
- يعمل داخل التطبيق فقط .
- الـ Broadcast لا يخرج من التطبيق .
- وكذلك التطبيقات الأخر لا يمكنها الوصول الى الــ receiver لأن نوع الـ Action يكون خاص بالتطبيق فقط .
- أكثر فعالية لعدم تسريب البيانات خارج التطبيق.
صورة لتوضيح طريقة عمل هذا النوع :
أخيراً ، مثال عملي لهذا النوع من الــ 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>
ما تم عمله :
- إنشاء حلقين من نوع EditText لكتابة الارقام .
- عمل دالة لانشاء حدث عند الضغط على زر الارسال .
- في داخل هذا الاكشن تم إنشاء اوبجكت من كلاس Intent ويشير الى كلاس الــ MyReceiver .
- بعد ذلك يتم ارسال البيانات من خلال استخدام دالة الــ sendBroadcast
- كلاس الــ MyReceiver يرث من كلاس الــ BroadcastReceiver ويستقبل عددين مرسل له من كلاس الــ MainActivity .
- إنشاء متغير جديد يقوم بعملية جمع المتغيرين ، ثم يرسلها الى MainActivity من خلال LocalBroadcastManager .
- في كلاس ال MyReceiver تم إنشاء اوبجكت من كلاس الــ Intent و وضع اسم للاكشن ، بحيث يتم استقبال هذا الاكشن في كلاس الــ MainActivity عن طريق عمل dynamic receiver .
- في كلاس الــ MainActivity تم إنشاء اوبجكت من كلاس الــ LocalBroadcastManager ، بحيث يكون هذا الاوبجكت هو المسؤول عن تسجيل receiver عند تشغيل التطبيق
- في الأخير تم إنشاء حقل من نوع TextView لعرض النتيجة المرسلة من كلاس MyReceiver في الــ MainActivity .
"في الأخير لاحظ ان هذا النوع من الــ Broadcast يستخدم الــ طريقة الــ statically broadcast مع طريقة الــ dynamic broadcast "
أتمنى أني وفقت في تبسيط إيصال المفاهيم ، وأعتذر على الاطالة .
هذا وإن كان من صواب فمن الله ،، وإن كان من خطأ فمن نفسي و الشيطان .
سبحانك اللهم وبحمدك أشهد أن لا إله إلا أنت أستغفرك وأتوب اليك .
التعليقات (0)
لايوجد لديك حساب في عالم البرمجة؟
تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !