أذونات الموقع بالطريقة الصحيحة
الموقع في المقدمة والموقع الدقيق
أذونات الموقع بالطريقة الصحيحة درس مجاني في Android Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Android Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Android Academy 4 دروس في المجموع.
الأذونات ليست اختيارية
يُعد الموقع من أكثر أذونات Android حساسية. ولا يكفي التصريح به في manifest — ففي إصدارات Android الحديثة يجب أن تطلبه من المستخدم أثناء التشغيل وأن تتعامل بسلاسة مع كل إجابة.
يتناول هذا الدرس مستويات الأذونات، وطلبها في Compose، والتعامل مع الرفض، وقواعد الدقيق مقابل التقريبي والوصول في الخلفية الجديدة.
أذونات الموقع الثلاثة
يقسّم Android الموقع إلى مستويات:
ACCESS_COARSE_LOCATION— موقع تقريبي (في حدود حيّ).ACCESS_FINE_LOCATION— موقع دقيق (بمستوى دقة GPS).ACCESS_BACKGROUND_LOCATION— الوصول إلى الموقع أثناء عدم وجود تطبيقك في الواجهة.
لا تطلب إلا ما تحتاج إليه فعليًا. ويخضع الوصول في الخلفية لتدقيق إضافي في Play Store.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- only if truly needed: -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />طلب الأذونات في Compose
توفّر Activity Result APIs مشغّلًا لمربعات حوار الأذونات. وفي Compose، استخدم rememberLauncherForActivityResult مع العقد RequestMultiplePermissions.
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { result ->
val fine = result[Manifest.permission.ACCESS_FINE_LOCATION] == true
val coarse = result[Manifest.permission.ACCESS_COARSE_LOCATION] == true
// react to the user's choice
}بدء طلب الإذن
شغّل مربع الحوار باستدعاء launch() مع مصفوفة الأذونات — وعادةً استجابةً لنقر المستخدم على زر، لا تلقائيًا عند تحميل الشاشة.
Button(onClick = {
launcher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
}) {
Text("Enable location")
}التحقق مما إذا كان الإذن ممنوحًا مسبقًا
لا تطلب الإذن مجددًا إذا كان ممنوحًا بالفعل. تحقّق باستخدام ContextCompat.checkSelfPermission قبل بدء الطلب.
import androidx.core.content.ContextCompat
import android.content.pm.PackageManager
fun hasFineLocation(context: Context): Boolean {
return ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
}الموقع الدقيق مقابل التقريبي
منذ Android 12 (API 31)، يمكن للمستخدمين منح إذن الموقع التقريبي حتى عند طلب الموقع الدقيق. لذلك يجب أن تطلب كلا الإذنين، الدقيق والتقريبي، معًا، وأن تتقبّل احتمال خفض المستخدم للإذن إلى الموقع التقريبي.
صمّم ميزتك بحيث تعمل بصورة مقبولة مع الموقع التقريبي حيثما أمكن.
// Request both — the system shows a Precise/Approximate toggle
launcher.launch(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
// If only COARSE comes back granted, you got approximate location.عرض سبب طلب الإذن
إذا رفض المستخدم الإذن مرةً، يتيح لك Android التحقق من shouldShowRequestPermissionRationale. وعندما تكون قيمتها true، اعرض شرحًا وديًا يوضّح سبب حاجتك إلى الموقع قبل الطلب مجددًا.
import androidx.core.app.ActivityCompat
val shouldExplain = ActivityCompat.shouldShowRequestPermissionRationale(
activity,
Manifest.permission.ACCESS_FINE_LOCATION
)
if (shouldExplain) {
// show a dialog: "We use your location to find nearby stores"
}التعامل مع الرفض الدائم
إذا اختار المستخدم عدم السؤال مرة أخرى (أو رفض الإذن مرتين)، فلن يعرض النظام مربع الحوار بعد ذلك. والخيار الوحيد المتاح لك هو إرساله إلى إعدادات التطبيق لتمكين الإذن يدويًا.
import android.content.Intent
import android.provider.Settings
import android.net.Uri
fun openAppSettings(context: Context) {
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", context.packageName, null)
)
context.startActivity(intent)
}استخدام Accompanist Permissions
تغلّف مكتبة accompanist-permissions كل ذلك في حالة ملائمة لـ Compose. وتتتبّع rememberMultiplePermissionsState حالة منح الأذونات، وتوفّر استدعاء launchMultiplePermissionRequest().
import com.google.accompanist.permissions.rememberMultiplePermissionsState
val permissions = rememberMultiplePermissionsState(
listOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
)
if (permissions.allPermissionsGranted) {
// show the map / read location
} else {
Button(onClick = { permissions.launchMultiplePermissionRequest() }) {
Text("Grant location")
}
}قواعد الموقع في الخلفية
يتطلب الموقع في الخلفية سير عمل من خطوتين: منح إذن الموقع في الواجهة أولًا (الدقيق/التقريبي)، ثم طلب ACCESS_BACKGROUND_LOCATION بشكل منفصل، ما يفتح إعدادات النظام على Android 11 والإصدارات الأحدث. يطلب متجر Play تبريرًا واضحًا وسياسة خصوصية.
اطلب هذا الإذن فقط إذا كان تطبيقك يحتاج فعلًا إلى الموقع أثناء إغلاقه — مثل تحديد المناطق الجغرافية أو تتبع اللياقة وغير ذلك.
// Step 1: request foreground first and confirm it's granted.
// Step 2: only then request background:
launcher.launch(
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
)
// On Android 11+ this sends the user to settings to pick "Allow all the time".خريطة مقيّدة بالإذن
اربط المكونات معًا: اجعل عرض الخريطة مشروطًا بحالة الإذن. اعرض الخريطة بعد منح الإذن فقط، وإلا فاعرض مطالبة بطلبه. هذا هو النمط القياسي الذي يحترم المستخدم.
@Composable
fun LocationGate(permissions: MultiplePermissionsState) {
when {
permissions.allPermissionsGranted -> MapScreen()
else -> Column {
Text("We need location to show nearby places.")
Button(onClick = { permissions.launchMultiplePermissionRequest() }) {
Text("Allow location")
}
}
}
}تحقق سريع
منذ Android 12، يمكن للمستخدم اختيار الموقع التقريبي بدلًا من الموقع الدقيق. ماذا يعني ذلك لطلبك؟
مراجعة
أصبحت تعرف الآن كيفية طلب الموقع بمسؤولية:
- صرّح بإذني الموقع التقريبي/الدقيق (وإذن الموقع في الخلفية فقط إذا كان ضروريًا) في البيان.
- اطلب الأذونات أثناء التشغيل باستخدام Activity Result APIs أو
accompanist-permissions. - اطلب الإذن الدقيق والتقريبي معًا لدعم التبديل بين الموقع الدقيق والتقريبي.
- اعرض توضيحًا لسبب الطلب، ووجّه المستخدمين الذين رُفض إذنهم نهائيًا إلى إعدادات التطبيق.
- تعامل مع موقع الخلفية كسير عمل منفصل من خطوتين وله مبرر واضح.
بهذا تكتمل وحدة Maps & Location Services — يمكنك عرض خريطة وتحديد موقع المستخدم ووضع علامات وطلب الإذن بالطريقة الصحيحة.
الأسئلة الشائعة
هل درس «أذونات الموقع بالطريقة الصحيحة» مجاني؟
نعم — نص درس «أذونات الموقع بالطريقة الصحيحة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Android Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Android Academy 4 دروس في المجموع.
ماذا ستتعلم في «أذونات الموقع بالطريقة الصحيحة»؟
الموقع في المقدمة والموقع الدقيق تتمرن على Android Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Android Academy؟
لا تُشترط خبرة سابقة. Android Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «أذونات الموقع بالطريقة الصحيحة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Android Academy هذا؟
نعم. كل درس في Android Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- عرض خريطة
- الحصول على موقع المستخدم
- العلامات والكاميرا
- أذونات الموقع بالطريقة الصحيحة