BluetoothAdapter — ما هو، طرقه وإدارة Bluetooth في Android

المؤلف: IT Sectr نُشر: 2026-07-16 وقت القراءة: 10 دق

BluetoothAdapter هو كلاس نظام Android يمثل محول Bluetooth المحلي للجهاز. BluetoothAdapter هو نقطة الدخول لجميع عمليات Bluetooth على Android: تشغيل الراديو (enable)، مسح الأجهزة، إدارة الرؤية (setScanMode)، والحصول على معلومات المحول (getName, getAddress, getState). يتوفر الكلاس عبر BluetoothManager.getAdapter() (API 18+) أو BluetoothAdapter.getDefaultAdapter(). على الأجهزة بدون وحدة Bluetooth، يُرجع getDefaultAdapter() قيمة null. وفقًا لـ Android Developers، 2026، BluetoothAdapter هو مكون إلزامي لأي تطبيق BLE على Android، بدءًا من API 5.

الرئيسية

  • BluetoothAdapter هو كلاس نظام Android لإدارة محول Bluetooth المحلي للجهاز
  • getDefaultAdapter() هو طريقة ثابتة للحصول على نسخة؛ يُرجع null على الأجهزة بدون Bluetooth
  • getBluetoothLeScanner() هو طريقة الوصول إلى ماسح BLE الحديث (API 21+)
  • enable/disable هما طريقتان لتشغيل وإيقاف راديو Bluetooth (تتطلبان إذن BLUETOOTH_ADMIN)
  • startDiscovery/startLeScan هما طريقتا المسح الكلاسيكي و BLE (LE Scan مهمل، استخدم BluetoothLeScanner)

ما هو BluetoothAdapter: الجوهر والحصول على النسخة

BluetoothAdapter يمثل محول Bluetooth الفعلي لجهاز Android. كل جهاز لديه محول واحد بالضبط (باستثناء Android Automotive مع شرائح Bluetooth متعددة، التي تستخدم BluetoothManager.getAdapterList()). يغلف BluetoothAdapter حالة الراديو: STATE_OFF (0)، STATE_TURNING_ON (1)، STATE_ON (2)، STATE_TURNING_OFF (3). يتم تتبع الحالة عبر BroadcastReceiver على ACTION_STATE_CHANGED.

الحصول على نسخة BluetoothAdapter هو الخطوة الأولى لأي تطبيق BLE على Android. الطريقة الموصى بها هي عبر BluetoothManager.getAdapter() من API 18+. البديل هو الطريقة الثابتة BluetoothAdapter.getDefaultAdapter()، التي تعمل من API 5 ولكنها أقل مرونة. كلتا الطريقتين تُرجعان null إذا كان الجهاز لا يحتوي على وحدة Bluetooth (أجهزة لوحية Wi-Fi only، المحاكي). فحص null إلزامي: يجب أن ينهي التطبيق عمله بشكل صحيح أو يعطل وظائف BLE.

kotlin
// الحصول على BluetoothAdapter (موصى به)
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothManager
import android.content.Context

class BluetoothHelper(context: Context) {

    private val bluetoothAdapter: BluetoothAdapter?

    init {
        // الطريقة 1: عبر BluetoothManager (API 18+)
        val manager = context.getSystemService(Context.BLUETOOTH_SERVICE)
                as BluetoothManager?
        bluetoothAdapter = manager?.adapter

        // الطريقة 2: عبر طريقة ثابتة (API 5+)
        // val adapter = BluetoothAdapter.getDefaultAdapter()

        // فحص null
        if (bluetoothAdapter == null) {
            // الجهاز لا يدعم Bluetooth
        }
    }

    // فحص حالة Bluetooth
    fun isBluetoothEnabled(): Boolean {
        return bluetoothAdapter?.isEnabled == true
    }

    // الحصول على معلومات المحول
    fun getAdapterInfo(): Map<String, String> {
        return mapOf(
            "name" to (bluetoothAdapter?.name ?: "N/A"),
            "address" to (bluetoothAdapter?.address ?: "N/A"),
            "state" to (bluetoothAdapter?.state?.toString() ?: "N/A"),
            "scanMode" to (bluetoothAdapter?.scanMode?.toString() ?: "N/A")
        )
    }
}

يوضح كلاس BluetoothHelper الحصول على BluetoothAdapter عبر BluetoothManager مع فحص null لاحق. يتحقق isBluetoothEnabled من isEnabled — شرط إلزامي قبل أي عمليات BLE. يُرجع getAdapterInfo اسم الجهاز وعنوان MAC والحالة ووضع الرؤية. مهم: على Android 10+ (API 29+)، تُرجع خدمة النظام عنوان MAC وهمي (02:00:00:00:00:00) إذا لم يكن للتطبيق أذونات BLUETOOTH_ADMIN و ACCESS_FINE_LOCATION.

الطرق الرئيسية لـ BluetoothAdapter: enable, disable, getState, getAddress

BluetoothAdapter يوفر طرقًا للتحكم في راديو Bluetooth. enable() و disable() يقومان بتشغيل وإيقاف Bluetooth. تتطلب كلتا الطريقتين إذن BLUETOOTH_ADMIN ويتم تنفيذهما بشكل غير متزامن: بعد استدعاء enable()، يبدأ النظام عملية تشغيل الراديو، ويتم تتبع الحالة عبر BroadcastReceiver مع إجراء BluetoothAdapter.ACTION_STATE_CHANGED. على Android 10+، تتطلب enable() و disable() امتياز نظام إضافي — لا يمكن للتطبيقات العادية التحكم في Bluetooth برمجيًا بدون حوار مستخدم.

getState() يُرجع الحالة الحالية للمحول: STATE_OFF (10)، STATE_TURNING_ON (11)، STATE_ON (12)، STATE_TURNING_OFF (13). getAddress() يُرجع عنوان MAC لمحول Bluetooth. على Android 6+، مطلوب ACCESS_FINE_LOCATION (أو ACCESS_COARSE_LOCATION لـ API 31+) لطلب عنوان MAC. على Android 10+، يُرجع getAddress() العنوان الثابت 02:00:00:00:00:00 — العنوان الحقيقي غير متاح عبر واجهة برمجة التطبيقات العامة.

getScanMode() يحدد وضع رؤية المحول: SCAN_MODE_NONE (غير مرئي)، SCAN_MODE_CONNECTABLE (مرئي للأجهزة المتصلة)، SCAN_MODE_CONNECTABLE_DISCOVERABLE (مرئي للجميع). وضع الرؤية محدود زمنيًا (عادة 60–300 ثانية) للأمان. يتطلب تعيين الوضع عبر setScanMode() إذن BLUETOOTH_ADMIN وإذن النظام على Android 10+.

الطريقةالوصفالإذن المطلوب
enable()تشغيل راديو BluetoothBLUETOOTH_ADMIN
disable()إيقاف راديو BluetoothBLUETOOTH_ADMIN
getState()حالة المحول الحاليةBLUETOOTH
getAddress()عنوان MAC للمحولBLUETOOTH + ACCESS_FINE_LOCATION (API 23+)
getScanMode()وضع رؤية الجهازBLUETOOTH
setScanMode()تعيين وضع الرؤيةBLUETOOTH_ADMIN

مسح الأجهزة: startDiscovery و BluetoothLeScanner

BluetoothAdapter يدعم نوعين من المسح. يتم تشغيل المسح الكلاسيكي Bluetooth (BR/EDR) عبر startDiscovery() — يكتشف أجهزة Bluetooth من جميع الأنواع، بما في ذلك الهواتف وسماعات الرأس. يتم إرجاع النتائج عبر BroadcastReceiver مع إجراء BluetoothDevice.ACTION_FOUND. يعمل startDiscovery() لمدة 12 ثانية ويمكن إلغاؤه عن طريق استدعاء cancelDiscovery(). هذه الطريقة مهملة لـ BLE — استخدم BluetoothLeScanner.

يتم مسح BLE عبر BluetoothAdapter باستخدام الطريقة المهملة startLeScan(LeScanCallback). بدءًا من API 21، توصي Google باستخدام BluetoothLeScanner، الذي يتم الحصول عليه عبر BluetoothAdapter.getBluetoothLeScanner(). يوفر BluetoothLeScanner واجهة برمجة تطبيقات أكثر مرونة: تكوين المسح عبر ScanSettings (الوضع، نوع رد الاتصال، وضع المطابقة)، التصفية عبر ScanFilter (حسب UUID الخدمة، اسم الجهاز، عنوان MAC)، ودعم PendingIntent للمسح في الخلفية.

kotlin
// واجهة برمجة تطبيقات مسح BLE القديمة (مهملة) مقابل الجديدة
import android.bluetooth.BluetoothAdapter
import android.bluetooth.le.*

class BLEScanner(private val bluetoothAdapter: BluetoothAdapter?) {

    // مهمل: startLeScan (API 18+، API 21)
    @Suppress("DEPRECATION")
    fun legacyScan() {
        bluetoothAdapter?.startLeScan { device, rssi, scanRecord ->
            print("Found (LE Scan): $device.name, RSSI: $rssi")
        }
    }

    // جديد: BluetoothLeScanner (API 21+)
    fun modernScan() {
        val scanner = bluetoothAdapter?.bluetoothLeScanner
            ?: return

        // إعدادات المسح
        val settings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
            .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
            .build()

        // تصفية حسب الخدمة (UUID معدل ضربات القلب)
        val filters = listOf(
            ScanFilter.Builder()
                .setServiceUuid(ParcelUuid.fromString("0000180D-0000-1000-8000-00805F9B34FB"))
                .build()
        )

        // بدء المسح
        scanner.startScan(filters, settings, object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                val device = result.device
                val rssi = result.rssi
                print("Found (BLE Scanner): ${device.name}, RSSI: $rssi, address: ${device.address}")
            }

            override fun onScanFailed(errorCode: Int) {
                print("Scan error: $errorCode")
            }
        })
    }
}

يقارن كلاس BLEScanner بين startLeScan المهمل و BluetoothLeScanner الحديث. في legacyScan، يتلقى LeScanCallback BluetoothDevice و RSSI و scanRecord الخام. في modernScan، يتم استخدام ScanSettings مع وضع LOW_LATENCY (أقصى سرعة اكتشاف) و ScanFilter للتصفية حسب UUID خدمة معدل ضربات القلب (0x180D). يوفر ScanCallback onScanResult مع كائن ScanResult يحتوي على معلومات موسعة: الاسم و RSSI وبيانات الإعلان ونوع الاتصال.

BluetoothManager: واجهة برمجة تطبيقات حديثة للوصول إلى BluetoothAdapter

BluetoothManager هو خدمة نظام Android، تم تقديمها في API 18 (Android 4.3)، لإدارة عمليات Bluetooth. قبل API 18، كانت الطريقة الوحيدة للحصول على BluetoothAdapter هي الطريقة الثابتة getDefaultAdapter(). يوفر BluetoothManager: adapter — نسخة BluetoothAdapter، getConnectedDevices() — قائمة بالأجهزة المتصلة، getDevicesMatchingConnectionStates() — التصفية حسب الحالة. يُستخدم BluetoothManager أيضًا للحصول على BluetoothLeScanner في واجهات برمجة التطبيقات القديمة.

مزايا BluetoothManager على استدعاء BluetoothAdapter.getDefaultAdapter() مباشرة: لا يعتمد التطبيق على singleton ثابت، يحترم المدير السياق (Activity/Application)، وهو أمر مهم لسيناريوهات الحسابات المتعددة في Android Enterprise. على Android Automotive مع شرائح Bluetooth متعددة، يُرجع BluetoothManager.getAdapterList() جميع المحولات المتاحة — يُرجع BluetoothAdapter.getDefaultAdapter() المحول الأول فقط.

kotlin
// استخدام BluetoothManager لـ BLE
class BLEConnection(context: Context) {

    private val bluetoothManager: BluetoothManager =
        context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager

    private val adapter: BluetoothAdapter? = bluetoothManager.adapter

    // الحصول على قائمة أجهزة BLE المتصلة
    fun getConnectedDevices(): List<BluetoothDevice> {
        return bluetoothManager.getConnectedDevices(
            BluetoothProfile.GATT
        )
    }

    // تصفية الأجهزة حسب الحالة
    fun getDevicesByState(states: IntArray): List<BluetoothDevice> {
        return bluetoothManager.getDevicesMatchingConnectionStates(
            BluetoothProfile.GATT, states
        )
    }

    // فحص دعم BLE على الجهاز
    fun isBLESupported(): Boolean {
        return adapter != null && context.packageManager
            .hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
    }

    // طلب تشغيل Bluetooth عبر حوار النظام
    fun requestEnableBluetooth(activity: MainActivity) {
        if (adapter?.isEnabled == false) {
            val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            activity.startActivityForResult(intent, REQUEST_ENABLE_BT)
        }
    }

    companion object {
        const val REQUEST_ENABLE_BT = 1001
    }
}

يستخدم كلاس BLEConnection BluetoothManager للوصول إلى BluetoothAdapter والحصول على قائمة أجهزة GATT المتصلة. يتحقق isBLESupported من وجود راديو BLE عبر PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) — فحص مهم للأجهزة التي تحتوي على Bluetooth Classic بدون BLE. يُظهر requestEnableBluetooth حوار النظام لتشغيل Bluetooth (ACTION_REQUEST_ENABLE)، دون الحاجة إلى إذن BLUETOOTH_ADMIN — هذه هي الطريقة القانونية الوحيدة لتشغيل Bluetooth على Android 10+ بدون تطبيق نظام.

أذونات Android للعمل مع BluetoothAdapter

الأذونات لـ BluetoothAdapter تطورت مع كل إصدار من Android. على Android 6–11 (API 23–30)، BLUETOOTH و BLUETOOTH_ADMIN و ACCESS_FINE_LOCATION إلزامية لمسح BLE. على Android 12+ (API 31+)، قسم Google الأذونات: تم استبدال ACCESS_FINE_LOCATION بـ BLUETOOTH_SCAN (المسح)، BLUETOOTH_CONNECT (الاتصال)، BLUETOOTH_ADVERTISE (الإعلان). لاكتشاف أجهزة BLE، BLUETOOTH_SCAN كافٍ، الموقع غير مطلوب.

جدول الأذونات حسب إصدار Android:

العمليةAPI 23–30API 31+
مسح BLEACCESS_FINE_LOCATIONBLUETOOTH_SCAN (بدون موقع)
اتصال BLEACCESS_FINE_LOCATIONBLUETOOTH_CONNECT
إعلان BLEACCESS_FINE_LOCATIONBLUETOOTH_ADVERTISE
تشغيل/إيقافBLUETOOTH_ADMINBLUETOOTH_ADMIN (النظام)
الحصول على عنوان MACACCESS_FINE_LOCATIONBLUETOOTH_CONNECT (عنوان وهمي)

على Android 12+، جميع أذونات Bluetooth هي أذونات وقت التشغيل — يجب طلبها في وقت التشغيل عبر ActivityResultContracts.RequestMultiplePermissions. تنتمي BLUETOOTH_SCAN و BLUETOOTH_ADVERTISE إلى مجموعة NEARBY_DEVICES، وتنتمي BLUETOOTH_CONNECT إلى نفس المجموعة. تبقى أذونات BLUETOOTH و BLUETOOTH_ADMIN في البيان للتوافق مع API < 31، ولكن بالنسبة لـ API 31+ يتم تجاهلها — تتطلب Google تحديد الأذونات الجديدة صراحة.

kotlin
// طلب أذونات Bluetooth على Android 12+
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat

class PermissionHelper(context: Context) {

    fun getRequiredPermissions(): Array<String> {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // Android 12+: BLE-
            arrayOf(
                Manifest.permission.BLUETOOTH_SCAN,
                Manifest.permission.BLUETOOTH_CONNECT,
                Manifest.permission.BLUETOOTH_ADVERTISE
            )
        } else {
            // Android 6-11: BLE
            arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN
            )
        }
    }

    // فحص جميع الأذونات
    fun hasPermissions(context: Context): Boolean {
        return getRequiredPermissions().all { permission ->
            ContextCompat.checkSelfPermission(context, permission)
                    == PackageManager.PERMISSION_GRANTED
        }
    }
}

يُرجع كلاس PermissionHelper المجموعة الصحيحة من الأذونات حسب مستوى API. على Android 12+، يتم استخدام BLUETOOTH_SCAN و BLUETOOTH_CONNECT و BLUETOOTH_ADVERTISE بدون موقع. على Android 6–11، لا يزال ACCESS_FINE_LOCATION مطلوبًا لمسح BLE. يجب على المطور مراعاة كلا السيناريوهين عند طلب الأذونات عبر ActivityResultContracts أو RxPermissions.

مثال كامل لـ BluetoothAdapter في Kotlin

مثال كامل لتطبيق BLE في Kotlin يستخدم BluetoothAdapter لمسح الأجهزة BLE والاتصال بها وقراءة بياناتها. يغطي المثال فحص الأذونات والحصول على المحول والمسح عبر BluetoothLeScanner والاتصال عبر BluetoothDevice.connectGatt.

kotlin
// مدير BLE كامل في Kotlin
class BLEManager(private val context: Context) {

    private val bluetoothManager: BluetoothManager =
        context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    private val adapter: BluetoothAdapter? = bluetoothManager.adapter
    private var scanner: BluetoothLeScanner? = adapter?.bluetoothLeScanner
    private var gatt: BluetoothGatt? = null

    // 1. اكتشاف الخدمات
    fun canScan(): Boolean {
        return adapter?.isEnabled == true
                && scanner != null
                && PermissionHelper(context).hasPermissions(context)
    }

    // 2. مع مرشح
    fun startScanning(callback: (BluetoothDevice, Int) -> Unit) {
        if (!canScan()) return

        val settings = ScanSettings.Builder()
            .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
            .setReportDelay(0)
            .build()

        scanner?.startScan(null, settings, object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                callback(result.device, result.rssi)
            }
        })
    }

    // 3. إيقاف المسح
    fun stopScanning() {
        scanner?.stopScan(object : ScanCallback() {})
    }

    // 4. الاتصال بجهاز BLE
    fun connectToDevice(device: BluetoothDevice) {
        if (adapter?.isEnabled != true) return

        gatt = device.connectGatt(
            context,
            false,
            object : BluetoothGattCallback() {
                override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
                    if (newState == BluetoothProfile.STATE_CONNECTED) {
                        gatt.discoverServices()
                    }
                }

                override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
                    // تم العثور على الخدمات، يمكن قراءة الخصائص
                }
            },
            BluetoothDevice.TRANSPORT_LE
        )
    }

    // 5. تحرير الموارد
    fun disconnect() {
        gatt?.disconnect()
        gatt?.close()
        gatt = null
    }
}

يوحد كلاس BLEManager دورة BLE الكاملة على Android: فحص المحول والأذونات (canScan)، المسح عبر BluetoothLeScanner مع ScanSettings (startScanning)، الاتصال عبر BluetoothDevice.connectGatt مع TRANSPORT_LE (connectToDevice)، وتحرير الموارد (disconnect). يتم تنفيذ جميع عمليات BLE على خيط واجهة المستخدم — يستدعي Android استدعاءات BluetoothGattCallback على الخيط الرئيسي. لمهام BLE المكثفة، يُوصى بنقل عمليات GATT إلى HandlerThread في الخلفية.

الأسئلة الشائعة

ما هو BluetoothAdapter في Android؟

BluetoothAdapter هو كلاس يمثل محول Bluetooth المحلي لجهاز Android. يتم الحصول عليه عبر BluetoothManager.getAdapter() (API 18+) أو BluetoothAdapter.getDefaultAdapter(). يوفر طرقًا لتشغيل/إيقاف Bluetooth ومسح الأجهزة وإدارة الرؤية والحصول على معلومات المحول. يُرجع null على الأجهزة بدون وحدة Bluetooth.

لماذا يُرجع BluetoothAdapter.getDefaultAdapter() قيمة null؟

السبب هو عدم وجود راديو Bluetooth على الجهاز. نموذجي للأجهزة اللوحية Wi-Fi only ومحاكي Android و Android TV بدون Bluetooth. تحقق من getDefaultAdapter() على null عند بدء التشغيل وقم بتعطيل وظائف BLE إذا كان المحول غائبًا. بديل هو الفحص عبر PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE) لتحديد أكثر دقة.

كيف يختلف BluetoothLeScanner عن startLeScan؟

BluetoothLeScanner (API 21+) هو واجهة برمجة تطبيقات حديثة لمسح BLE مع دعم ScanFilter و ScanSettings و PendingIntent. startLeScan (API 18+) هو طريقة مهملة لـ BluetoothAdapter تقبل LeScanCallback بمجموعة بيانات محدودة. توصي Google باستخدام BluetoothLeScanner لجميع المشاريع الجديدة، يسمح بالتصفية حسب UUID وتكوين وضع استهلاك الطاقة والعمل في الخلفية عبر PendingIntent.

ما هي الأذونات المطلوبة لـ BLE على Android 12+؟

على Android 12+ (API 31)، يتطلب مسح BLE BLUETOOTH_SCAN، والاتصال يتطلب BLUETOOTH_CONNECT، والإعلان يتطلب BLUETOOTH_ADVERTISE. لم يعد إذن الموقع ACCESS_FINE_LOCATION مطلوبًا لـ BLE. على Android 6–11، ACCESS_FINE_LOCATION مطلوب. يتم طلب جميع الأذونات في وقت التشغيل عبر ActivityResultContracts.

هل يمكن تشغيل Bluetooth برمجيًا بدون حوار؟

على Android 10+، تشغيل Bluetooth برمجيًا بدون حوار نظام متاح فقط لتطبيقات النظام بإذن BLUETOOTH_PRIVILEGED. يجب على التطبيقات العادية استخدام Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) و startActivityForResult — يؤكد المستخدم التشغيل في حوار النظام. BLUETOOTH_ADMIN في البيان لا يمنح حقوق enable() على Android 10+.

الخلاصة

  • BluetoothAdapter هو نقطة الدخول لجميع عمليات Bluetooth على Android، يتم الحصول عليه عبر BluetoothManager أو getDefaultAdapter()
  • getState() و isEnabled هما فحصان أساسيان لحالة راديو Bluetooth قبل أي عمليات BLE
  • BluetoothLeScanner (API 21+) يحل محل startLeScan المهمل مع دعم ScanFilter و ScanSettings و PendingIntent
  • BluetoothManager هو الطريقة الحديثة للحصول على BluetoothAdapter مع دعم سيناريوهات الحسابات المتعددة و Automotive
  • الأذونات تطورت: ACCESS_FINE_LOCATION (API 23-30) → BLUETOOTH_SCAN/CONNECT/ADVERTISE (API 31+)
  • enable()/disable() — على Android 10+ فقط عبر حوار النظام ACTION_REQUEST_ENABLE للتطبيقات العادية
  • connectGatt هو طريقة BluetoothDevice لإنشاء اتصال GATT مع أجهزة BLE الطرفية عبر BluetoothGattCallback

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا