Connectivity Manager هو خدمة نظام Android توفر للتطبيقات معلومات حول حالة اتصال الشبكة للجهاز. يسمح بالتحقق من توفر الإنترنت، وتحديد نوع الشبكة (Wi-Fi، بيانات الجوال، Ethernet)، وتتبع التغييرات في الاتصال وإدارة طلبات الشبكة بناءً على جودة الاتصال. وفقًا لـ Android Developers، 2025، ConnectivityManager هو واجهة برمجة التطبيقات الرئيسية لمراقبة الشبكة وهو جزء من Android Framework منذ API Level 1.
النقاط الرئيسية
ConnectivityManager هو خدمة نظام لنظام التشغيل Android، يمكن الوصول إليها عبر Context.getSystemService(Context.CONNECTIVITY_SERVICE). يوفر واجهة برمجة تطبيقات للحصول على معلومات حول اتصال الشبكة للجهاز، ومراقبة تغييرات الشبكة وإدارة طلبات الشبكة للتطبيق. كان Connectivity Manager جزءًا من Android Framework منذ الإصدار الأول للمنصة (API Level 1) وخضع لتغييرات كبيرة على مر العقود: من getActiveNetworkInfo() البسيط إلى النموذج التفاعلي الحديث مع NetworkCallback و NetworkRequest.
تشمل الإمكانيات الرئيسية لـ Connectivity Manager: التحقق من وجود اتصال شبكة نشط، تحديد نوع الشبكة (Wi-Fi، بيانات الجوال، Ethernet، Bluetooth، VPN)، مراقبة تغييرات حالة الشبكة في الوقت الفعلي، الحصول على معلومات حول عرض النطاق الترددي وزمن الوصول، وإدارة طلبات الشبكة للتطبيق. ConnectivityManager يُستخدم مع WorkManager و Repository لتنفيذ بنية Offline-First والتحميل التكيفي للمحتوى وتحسين أداء التطبيق حسب جودة الاتصال.
بدءًا من Android 10 (API 29)، غيرت Google نهج العمل مع ConnectivityManager. طريقة getActiveNetworkInfo() تم إعلانها مهملة، وبدلاً منها يُوصى باستخدام registerDefaultNetworkCallback() أو registerNetworkCallback() مع NetworkRequest. توفر واجهة برمجة التطبيقات الجديدة معلومات شبكة أكثر تفصيلاً، بما في ذلك القدرة على اكتشاف البوابات المقيدة (Wi-Fi مع المصادقة) وتقييم جودة الاتصال. ConnectivityManager أيضًا مدمج مع عائلة Jetpack: تم إصدار مكتبة ConnectivityManager في 2024 كجزء من Jetpack لتبسيط مراقبة الشبكة في تطبيقات Compose.
في بنية Android الحديثة، يُستخدم Connectivity Manager على مستوى المستودع أو UseCase لاتخاذ قرارات حول طلبات الشبكة. طبقة المستودع تتحقق من حالة الشبكة قبل استدعاء API: إذا كانت الشبكة غير متاحة، يتم إرجاع البيانات من التخزين المحلي (Room). إذا كانت الشبكة متاحة، يتم تنفيذ طلب إلى الخادم وحفظ النتيجة في Room. ViewModel يشترك في Flow من Room ولا يعرف تفاصيل التفاعل الشبكي — وهذا يسمح باختبار كل طبقة بشكل مستقل.
يحصل Connectivity Manager على معلومات حالة الشبكة من خدمة النظام connectivity، التي تتفاعل مع واجهات الشبكة لنواة Linux. عندما يتصل الجهاز بشبكة Wi-Fi أو يشغل بيانات الجوال، تخطر النواة خدمة النظام، التي تقوم بتحديث حالتها الداخلية وإخطار جميع الاستدعاءات المسجلة. بنية ConnectivityManager مبنية على نمط Observer: يسجل التطبيق NetworkCallback ويتلقى إخطارات حول أي تغييرات في الشبكة — إنشاء اتصال، فقدان الاتصال، تغيير نوع الشبكة أو تدهور الجودة.
تستخدم واجهة برمجة التطبيقات الحديثة لـ ConnectivityManager NetworkRequest لتصفية أحداث الشبكة. يسمح NetworkRequest بتحديد متطلبات الشبكة: النقل (Transport.WIFI، Transport.CELLULAR، Transport.ETHERNET)، إمكانية الإنترنت (NetworkCapabilities.NET_CAPABILITY_INTERNET) ومعايير أخرى. إذا كان التطبيق يحتاج فقط إلى Wi-Fi لتنزيل ملفات كبيرة، فإنه ينشئ NetworkRequest مع Transport.WIFI ويسجل استدعاءً. سيخطر النظام التطبيق فقط عند تغيير اتصال Wi-Fi، متجاهلاً أحداث شبكة الجوال.
ميزة مهمة لـ Connectivity Manager على Android 12+ هي الشبكات القائمة على الإمكانيات. التطبيق لا يتحقق فقط من “هل هناك إنترنت؟”، بل يمكنه تقييم نوع حركة المرور المتاحة. على سبيل المثال، يشير NET_CAPABILITY_NOT_METERED إلى اتصال غير محدود (Wi-Fi)، و NET_CAPABILITY_NOT_ROAMING يشير إلى أن الجهاز ليس في تجوال. هذا يسمح باتخاذ قرارات: تنزيل الفيديو عبر Wi-Fi فقط، تأجيل المزامنة أثناء التجوال، أو استخدام بيانات الجوال فقط للطلبات الحرجة.
| مستوى API | الطريقة الموصى بها | الحالة |
|---|---|---|
| 1-22 | getActiveNetworkInfo() | مهملة |
| 21+ | NetworkCallback + registerNetworkCallback() | موصى بها |
| 24+ | registerDefaultNetworkCallback() | موصى بها |
| 28+ | getActiveNetwork() + NetworkCapabilities | بديل |
| 31+ | registerBestMatchingNetworkCallback() | API جديد |
لاستخدام Connectivity Manager في تطبيق Android، يلزم أذونات. ACCESS_NETWORK_STATE هو إذن إلزامي لقراءة معلومات الشبكة، يُعلن في AndroidManifest.xml. بدون هذا الإذن، سيعيد ConnectivityManager قيمة null لـ getActiveNetwork() ولن يستدعي الاستدعاءات. لتنفيذ عمليات الشبكة، يلزم أيضًا إذن INTERNET. بدءًا من Android 10 (API 29)، يمكن للتطبيق التحقق من حالة الشبكة بدون أذونات إضافية في وقت التشغيل — ACCESS_NETWORK_STATE هو إذن عادي ويُمنح تلقائيًا أثناء التثبيت.
يوفر Connectivity Manager الحديث عدة طرق رئيسية للعمل مع الشبكة. getActiveNetwork() (API 23+) يُرجع كائن Network للشبكة النشطة الحالية أو null إذا كان الجهاز غير متصل. هذه الطريقة لا تتطلب استدعاءات ومناسبة للفحص لمرة واحدة. يمكن تمرير كائن Network إلى NetworkCapabilities للحصول على معلومات مفصلة: نوع النقل، حالة القياس، التجوال، إمكانية الإنترنت وخصائص أخرى.
registerDefaultNetworkCallback() (API 24+) هي الطريقة المفضلة لمراقبة الشبكة. يسجل التطبيق استدعاءً يتم استدعاؤه عند أي تغييرات في الشبكة الافتراضية (الشبكة التي يرسل التطبيق من خلالها حركة المرور). يتلقى الاستدعاء كائن Network يمكن استخدامه لربط المقابس وعملاء HTTP. تحل هذه الطريقة محل getActiveNetworkInfo() المهملة وتوفر مراقبة تفاعلية للشبكة بدون استقصاء.
registerNetworkCallback() (API 21+) يسمح بالاشتراك في تغييرات نوع شبكة محدد عبر NetworkRequest. على سبيل المثال، يمكن للتطبيق تتبع شبكات Wi-Fi فقط باستخدام new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(). سيخطر النظام التطبيق حول اتصال/فصل Wi-Fi دون التأثير على أحداث شبكة الجوال. NetworkCapabilities.getLinkDownstreamBandwidthKbps() يُرجع تقديرًا لعرض النطاق الترددي الهابط بكيلوبت/ثانية، مما يسمح بتكييف جودة المحتوى مع سرعة الاتصال.
| الطريقة | الحد الأدنى لـ API | الغرض |
|---|---|---|
| getActiveNetwork() | 23 | الحصول على الشبكة النشطة الحالية |
| getNetworkCapabilities() | 21 | الحصول على إمكانيات الشبكة (النوع، القياس، التجوال) |
| registerDefaultNetworkCallback() | 24 | مراقبة الشبكة الافتراضية |
| registerNetworkCallback() | 21 | مراقبة الشبكات حسب فلتر NetworkRequest |
| unregisterNetworkCallback() | 21 | إلغاء تسجيل الاستدعاء |
| getActiveNetworkInfo() | 1 | مهملة، لا تستخدم |
مكتبة Jetpack Connectivity (androidx.core:core-ktx) توفر امتدادات ملائمة للعمل مع ConnectivityManager في Compose. الدالة ConnectivityManager.observeAsState() تُرجع State
ConnectivityManager.NetworkCallback هي فئة مجردة بطرق يستدعيها النظام عند تغيير حالة الشبكة. onAvailable(Network) يُستدعى عندما تصبح الشبكة متاحة. يتلقى التطبيق كائن Network يمكن استخدامه لربط المقابس عبر Network.bindSocket(). onLost(Network) يُستدعى عندما تصبح الشبكة غير متاحة. يجب على التطبيق التبديل إلى البيانات المحلية أو عرض رسالة حول عدم وجود اتصال. onCapabilitiesChanged(Network, NetworkCapabilities) يُستدعى عند تغيير خصائص الشبكة (على سبيل المثال، عند التبديل من Wi-Fi إلى بيانات الجوال).
تتطلب المعالجة الصحيحة لتغييرات الشبكة مراعاة دورة حياة المكون. يجب تسجيل الاستدعاء في onStart()/onResume() وإلغاؤه في onStop()/onPause(). إذا لم يتم إلغاء الاستدعاء، فقد يستمر في العمل بعد تدمير Activity، مما يسبب تسرب الذاكرة واحتمال NullPointerException عندما يحاول الاستدعاء تحديث واجهة المستخدم لمكون مُدمَّر. استخدم lifecycleScope أو repeatOnLifecycle للإدارة التلقائية للتسجيل. في Jetpack Compose، استخدم DisposableEffect لتسجيل وإلغاء الاستدعاء.
معالجة البوابات المقيدة هي ميزة مهمة لـ ConnectivityManager بدءًا من Android 10. CAPTIVE_PORTAL هو سيناريو حيث تكون شبكة Wi-Fi متاحة ولكنها تتطلب مصادقة عبر صفحة ويب (المطارات، الفنادق، المقاهي). يشير NetworkCapabilities.NET_CAPABILITY_VALIDATED إلى أن الشبكة لديها وصول كامل إلى الإنترنت. إذا كان NET_CAPABILITY_VALIDATED غائبًا، يمكن للتطبيق فتح متصفح لمصادقة البوابة المقيدة. الطريقة isCaptivePortal()، المضافة في Android 11 (API 30)، تُستخدم لاكتشاف البوابات المقيدة.
يسمح ConnectivityManager بطلب شبكة لأغراض محددة عبر requestNetwork() و bindProcessToNetwork(). على سبيل المثال، تطبيق لتنزيل ملفات كبيرة يمكنه طلب شبكة Wi-Fi حتى إذا كانت بيانات الجوال نشطة. للقيام بذلك، يتم إنشاء NetworkRequest مع addTransportType(TRANSPORT_WIFI)، وعند توفر Wi-Fi، يستدعي النظام onAvailable(). يربط التطبيق المقابس بهذه الشبكة عبر network.bindSocket() أو OkHttp مع كائن Network مهيأ. هذا يوفر تحكمًا مرنًا في استخدام واجهات الشبكة.
لنلق نظرة على مثال كامل لاستخدام ConnectivityManager مع واجهة برمجة التطبيقات الحديثة (NetworkCallback) في بنية Clean Architecture. NetworkMonitor هي فئة مغلفة حول ConnectivityManager توفر حالة الشبكة بشكل تفاعلي عبر StateFlow. يشترك ViewModel في هذا Flow ويمرر الحالة إلى واجهة المستخدم. يستخدم Repository NetworkMonitor لاتخاذ قرارات حول طلبات الشبكة. هذا النهج يضمن قابلية الاختبار وعزل تبعيات المنصة.
المثال أدناه يوضح كيفية استخدام ConnectivityManager بشكل صحيح مع registerDefaultNetworkCallback. فئة NetworkMonitor تغلف العمل مع خدمة النظام وتوفر Kotlin Flow
class NetworkMonitor(
private val connectivityManager: ConnectivityManager
) {
val isOnline: StateFlow<Boolean> = callbackFlow {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
trySend(true)
}
override fun onLost(network: Network) {
trySend(false)
}
override fun onCapabilitiesChanged(
network: Network,
caps: NetworkCapabilities
) {
val connected = caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET
)
trySend(connected)
}
}
connectivityManager.registerDefaultNetworkCallback(callback)
awaitClose {
connectivityManager.unregisterNetworkCallback(callback)
}
}.stateIn(
CoroutineScope(Dispatchers.Default),
SharingStarted.WhileSubscribed(5000),
initialValue = checkInitialState()
)
private fun checkInitialState(): Boolean {
val network = connectivityManager.getActiveNetwork() ?: return false
val caps = connectivityManager.getNetworkCapabilities(network) ?: return false
return caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET
)
}
}
يشترك ViewModel في NetworkMonitor.isOnline عبر stateIn() ويمرر الحالة إلى Compose. يتحقق Repository من القيمة الحالية isOnline.value قبل استدعاء API: إذا كانت false — يُرجع Flow من Room. إذا كانت true — يستدعي API، يحفظ النتيجة في Room ويُرجع Flow من Room. يستخدم WorkManager NetworkType.CONNECTED لتقييد المهام الخلفية. يتم اختبار NetworkMonitor باستخدام كائن mock لـ ConnectivityManager و NetworkCallback وهمي، مما يسمح بمحاكاة أي سيناريو شبكة في اختبارات الوحدة.
القاعدة الأولى للعمل مع ConnectivityManager هي عدم استخدام واجهة برمجة التطبيقات المهملة. getActiveNetworkInfo() مهملة منذ API 29 وقد تعيد بيانات غير صحيحة على إصدارات Android الجديدة. بدلاً منها، استخدم getActiveNetwork() + getNetworkCapabilities() للفحص لمرة واحدة و registerDefaultNetworkCallback() للمراقبة المستمرة. الطريقة القديمة أيضًا لا تفرق بين الشبكات ذات البوابة المقيدة والإنترنت الكامل، مما يؤدي إلى نتائج إيجابية خاطئة.
القاعدة الثانية هي دائمًا إلغاء تسجيل الاستدعاء. إذا سجلت Activity NetworkCallback في onStart() ولكنها لم تلغه في onStop()، يستمر الاستدعاء في العمل بعد تدمير Activity. هذا يسبب تسرب الذاكرة واحتمال NullPointerException عندما يحاول الاستدعاء تحديث واجهة المستخدم لمكون مُدمَّر. استخدم lifecycleScope أو repeatOnLifecycle للإدارة التلقائية للتسجيل. في Jetpack Compose، استخدم DisposableEffect لتسجيل وإلغاء الاستدعاء.
الخطأ الشائع الثالث هو التحقق فقط من توفر الشبكة دون النظر في جودتها. مجرد “هل هناك إنترنت؟” غير كافٍ لاتخاذ القرارات. يجب على التطبيق التحقق من NET_CAPABILITY_NOT_METERED لتنزيل الملفات الكبيرة، و NET_CAPABILITY_NOT_ROAMING للمزامنة في الخلفية، و NET_CAPABILITY_VALIDATED لتأكيد الوصول إلى الإنترنت. تجاهل هذه العلامات يؤدي إلى محاولة التطبيق تنزيل فيديو أثناء التجوال أو مزامنة البيانات عبر بوابة مقيدة في فندق.
القاعدة الرابعة هي عدم استخدام ConnectivityManager للتحقق من توفر خادم محدد. يبلغ ConnectivityManager عن حالة الشبكة على الجهاز، لكنه لا يضمن أن الخادم متاح. للتحقق من توفر API، استخدم طلب HTTP بوقت مهلة قصير أو Health Check. ConnectivityManager + ping HTTP مزيج موثوق: تحقق أولاً من وجود الشبكة، ثم نفذ طلبًا خفيفًا إلى الخادم لتأكيد التوفر الفعلي.
لاختبارات الوحدة، استخدم Robolectric مع ShadowConnectivityManager، الذي يسمح بمحاكاة حالات الشبكة. لاختبارات التكامل — Android Test Orchestrator مع تبديل وضع الطيران. في الاختبارات، تحقق من السيناريوهات: الانتقال من متصل إلى غير متصل، ظهور Wi-Fi أثناء نشاط بيانات الجوال، فقدان الشبكة أثناء تنفيذ طلب، بوابة مقيدة، تجوال. للـ mocking في اختبارات الوحدة، استخدم واجهة مغلفة (مثل NetworkMonitorInterface) يمكن استبدالها بكائن mock بدون تبعيات المنصة.
الأسئلة الشائعة
الطريقة الحديثة هي استخدام registerDefaultNetworkCallback() مع التحقق من NET_CAPABILITY_INTERNET في onCapabilitiesChanged(). للفحص لمرة واحدة: connectivityManager.getActiveNetwork()?.let { caps -> caps.hasCapability(NET_CAPABILITY_INTERNET) } ?: false. الطريقة المهملة getActiveNetworkInfo() غير موصى بها من API 29+.
لقراءة معلومات الشبكة، يلزم الإذن android.permission.ACCESS_NETWORK_STATE. هذا إذن عادي — يُمنح تلقائيًا عند تثبيت التطبيق ولا يتطلب طلبًا في وقت التشغيل. لتنفيذ عمليات الشبكة (طلبات HTTP)، يلزم أيضًا إذن INTERNET.
registerDefaultNetworkCallback() يراقب الشبكة الافتراضية — تلك التي يرسل التطبيق من خلالها حركة المرور الرئيسية. registerNetworkCallback(NetworkRequest) يراقب الشبكات المطابقة لفلتر معين (مثل Wi-Fi فقط). الاستدعاء الافتراضي أبسط ويغطي 90% من السيناريوهات، بينما الطلب المخصص للمتطلبات المحددة لنوع الشبكة.
استخدم NetworkCapabilities: caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) لـ Wi-Fi، hasTransport(TRANSPORT_CELLULAR) لبيانات الجوال. لا تستخدم ConnectivityManager.getActiveNetworkInfo().getType() — هذه الطريقة مهملة. NetworkCapabilities متاح عبر connectivityManager.getNetworkCapabilities(network).
getActiveNetworkInfo() مهملة بسبب عدم الدقة: لا تفرق بين الشبكات ذات البوابة المقيدة والإنترنت الكامل، ولا توفر معلومات حول عرض النطاق الترددي أو التجوال. بدءًا من Android 10، قد تعيد هذه الطريقة null أو بيانات غير صحيحة للاتصالات متعددة الشبكات. البديل هو getActiveNetwork() + NetworkCapabilities.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا