المدونة

صلاحية موقع الخلفية في اندرويد ١١

قبل التغييرات الجديدة على نظام Android مع الإصدار 11 ، كان طلب الإذن لكل من الخلفية(Background) والمقدمة(Foreground) لحالات التطبيق هو نفس الشيئ ، فقط اطلب إذنًا واحدًا وكان كل شيء بسيطًا وسهلاً ، ولكن ليس بعد الآن.

location permission old

بضفه عامة هنالك نوعان من الوصول للموقع:

  • صلاحية الوصول من الخلفية Background location
  • صلاحية الوصول من المقدمة Foreground location

    التغييرات الجديدة

بدءًا من Android 11 لكي يتلقى تطبيقك موقع الخلفية ، يجب عليك طلب إذن جديد ACCESS_BACKGROUND_LOCATION مباشرة بعد أن تطلب الأذونات العادية ACCESS_COARSE_LOCATION أو ACCESS_FINE_LOCATION أو كليهما وسيستمر كل شيء في العمل كما كان من قبل.

تذكر اذا لم تقم بطلب هذه الصلاحيات بالطريقة المذكورة اعلاه فلن يكون هنالك استجابة مثل ان تطلب صلاحية ACCESS_BACKGROUND_LOCATION قبل ACCESS_COARSE_LOCATION أو ACCESS_FINE_LOCATION

متى يجب أن تطلب هذا الإذن؟

بشكل عام عند وجود أي ميزة في التطبيق تتطلب الوصول إلى الموقع أثناء التواجد في الخلفية ، فإليك بعض حالات الاستخدام التي صادفتها أثناء العمل:

  • عندما تريد تشغيل Foreground service من الخلفية كمثال

عندما تريد تشغيل تتبع الموقع في الخليفة عندي يتنهي الهاتف من اعادة تشغيل الجهاز (booting) فعندها يجب عليك طلب هذه الصلاحية

  • الوظائف المجدولة التي تستخدم الموقع (WorkManager ، AlarmManager .. إلخ).

مثال:

سيكون لدينا تطبيق بسيط يحتوي على زر واحد ، وسيطلب إذنًا عاديًا (ACCESS_COARSE_LOCATION ، ACCESS_FINE_LOCATION) و ACCESS_BACKGROUND_LOCATION على التوالي

هيا لنبدأ

ابدأ أولاً بإضافة الأذونات في ملف AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.m7mdra.backgroundlocationpermissiondemo">
    
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    
    <application
    ...

الان لنقم بطلب الصلاحية

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val button = findViewById<MaterialButton>(R.id.permissionButton)
        button.setOnClickListener {
            checkLocationPermission()
        }
    }

وهنا حيث يحدث كل شيئ

    private fun checkLocationPermission() {
        //تحقق اذا لم  يتم منح صلاحية الوصول للموقع
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            //ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION طلب الصلاحية للموقع 
            requestPermissionOrShowRational(13)
        } else {
            //  تحقق من نسخة نظام التشغيل , نسخة تساوي ١١ او اعلى
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                //ACCESS_BACKGROUND_LOCATION تحقق من صلاحية الوصول للموقع في الخلفية
                if (hasBackgroundPermission()) {
                    // تم منح الصلاحية مسبقا
                    Toast.makeText(this," تم منح الصلاحية في الخلفية",Toast.LENGTH_SHORT).show()
                } else {
                    //ACCESS_BACKGROUND_LOCATION طلب الصلاحية
                    showBackgroundLocationDialog(13)
                }
            } else {
                // تم منح الصلاحية مسبقا
                Toast.makeText(this,"تم منح الصلاحية",Toast.LENGTH_SHORT).show()

            }
        }
    }
والان بعد ان يتم تنفيذ هذا الكود بعد الضغط على الزر سوف يظهر للمستخدم صندوق فيها خياران رفض او قبول سوف نقوم بالتحقق من هذا الحدث
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String?>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if(requestCode == 13){
            if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
                Toast.makeText(this,"تم منح الصلاحية",Toast.LENGTH_SHORT).show()

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    //الان لنقم بطلب صلاحية الموقع من الخلفية
                    showBackgroundLocationDialog(14)
                }else {
                    Toast.makeText(this,"تم منح الصلاحية في الخلفية مسبقاً",Toast.LENGTH_SHORT).show()

                }
            }else{
                //اظهار رسالة تبين رفض الصلاحية
                showPermissionDeniedDialog()
            }
        }
        if(requestCode == 14){
            if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
                Toast.makeText(this,"تم منح الصلاحية في الخلفية ",Toast.LENGTH_SHORT).show()
            }else{
                //اظهار رسالة تبين رفض الصلاحية
                showPermissionDeniedDialog()
            }
        }
    }

وهذا كل شيء ، والآن سنقوم بتشغيل تطبيقنا ومعرفة ما إذا كان يعمل

صور

1 2 3 4
1 permission android11 2 permission android11 3 permission android11 4 permission android11

السورس كود متوفر هنا

النهاية