من الميزات الفريدة لتطبيقات الأجهزة الجوّالة هي التعرّف على الموقع الجغرافي. يصطحب مستخدمو الأجهزة الجوّالة أجهزتهم معهم في كل مكان، وتوفّر إضافة ميزة التعرّف على الموقع الجغرافي إلى تطبيقك تجربة أكثر ملاءمةً للسياق.
عيّنات تعليمات برمجية
يتضمّن مستودع ApiDemos على GitHub نماذج توضّح كيفية استخدام الموقع الجغرافي على الخريطة:
Kotlin
- MyLocationDemoActivity: استخدام طبقة "موقعي الجغرافي"، بما في ذلك أذونات وقت التشغيل
- LocationSourceDemoActivity: استخدام
LocationSource - CurrentPlaceDetailsOnMap: العثور على الموقع الجغرافي الحالي لجهاز Android وعرض تفاصيل المكان (نشاط تجاري أو نقطة اهتمام أخرى) في هذا الموقع الجغرافي يمكنك الاطّلاع على البرنامج التعليمي حول عرض تفاصيل المكان الحالي على الخريطة.
Java
- MyLocationDemoActivity: استخدام طبقة "موقعي الجغرافي"، بما في ذلك أذونات التشغيل
- LocationSourceDemoActivity: استخدام
LocationSource - CurrentPlaceDetailsOnMap: للعثور على الموقع الجغرافي الحالي لجهاز Android وعرض تفاصيل المكان (نشاط تجاري أو أي نقطة اهتمام أخرى) في ذلك الموقع الجغرافي يمكنك الاطّلاع على البرنامج التعليمي حول عرض تفاصيل المكان الحالي على الخريطة.
العمل باستخدام بيانات الموقع الجغرافي
تتضمّن بيانات الموقع الجغرافي المتاحة لجهاز Android الموقع الجغرافي الحالي للجهاز، والذي يتم تحديده بدقة باستخدام مجموعة من التقنيات، واتجاه الحركة وطريقتها، وما إذا كان الجهاز قد تحرّك عبر حدود جغرافية محدّدة مسبقًا أو حدود جغرافية. بناءً على احتياجات تطبيقك، يمكنك الاختيار من بين عدة طرق للتعامل مع بيانات الموقع الجغرافي:
- توفّر طبقة موقعي الجغرافي طريقة بسيطة لعرض الموقع الجغرافي للجهاز على الخريطة. ولا يوفّر بيانات.
- ننصح باستخدام واجهة برمجة التطبيقات للموقع الجغرافي في "خدمات Google Play" لجميع الطلبات الآلية للحصول على بيانات الموقع الجغرافي.
- تتيح لك واجهة
LocationSourceتوفير موفّر موقع جغرافي مخصّص.
أذونات تحديد الموقع الجغرافي
إذا كان تطبيقك يحتاج إلى الوصول إلى الموقع الجغرافي للمستخدم، عليك طلب الإذن من خلال إضافة أذونات تحديد الموقع الجغرافي ذات الصلة في Android إلى تطبيقك.
يوفّر Android إذنَين لتحديد الموقع الجغرافي: ACCESS_COARSE_LOCATION وACCESS_FINE_LOCATION. يحدّد الإذن الذي تختاره دقة الموقع الجغرافي الذي تعرضه واجهة برمجة التطبيقات.
android.permission.ACCESS_COARSE_LOCATION– يسمح لواجهة برمجة التطبيقات بعرض الموقع الجغرافي التقريبي للجهاز. يوفّر الإذن تقديرًا لموقع الجهاز الجغرافي من خدمات الموقع الجغرافي، كما هو موضّح في المستندات حول دقة الموقع الجغرافي التقريبي.android.permission.ACCESS_FINE_LOCATION– يسمح لواجهة برمجة التطبيقات بتحديد الموقع الجغرافي بأكبر قدر ممكن من الدقة من مقدّمي خدمات الموقع الجغرافي المتاحين، بما في ذلك نظام تحديد المواقع العالمي (GPS) بالإضافة إلى بيانات شبكة Wi-Fi وشبكة الجوّال.
إضافة الأذونات إلى بيان التطبيق
إذا كان تطبيقك يحتاج فقط إلى الموقع الجغرافي التقريبي ليعمل، أضِف إذن
ACCESS_COARSE_LOCATION إلى ملف بيان تطبيقك:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" > ... <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> ... </manifest>
ومع ذلك، إذا كان الموقع الجغرافي الدقيق مطلوبًا، أضِف الإذنَين ACCESS_COARSE_LOCATION وACCESS_FINE_LOCATION إلى ملف بيان تطبيقك:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp" > ... <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> ... </manifest>
طلب أذونات التشغيل
يقدّم الإصدار 6.0 من نظام التشغيل Android (Marshmallow) نموذجًا جديدًا للتعامل مع الأذونات، ما يسهّل على المستخدمين عملية تثبيت التطبيقات وتحديثها. إذا كان تطبيقك يستهدف المستوى 23 من واجهة برمجة التطبيقات أو المستويات الأحدث، يمكنك استخدام نموذج الأذونات الجديد.
إذا كان تطبيقك متوافقًا مع نموذج الأذونات الجديد وكان الجهاز يعمل بنظام التشغيل Android 6.0 (Marshmallow) أو إصدار أحدث، لن يحتاج المستخدم إلى منح أي أذونات عند تثبيت التطبيق أو ترقيته. يجب أن يتحقّق التطبيق من حصوله على الإذن اللازم في وقت التشغيل، وأن يطلب الإذن إذا لم يكن لديه. يعرض النظام مربّع حوار للمستخدم يطلب منه منح الإذن.
للحصول على أفضل تجربة للمستخدم، من المهم طلب الإذن في السياق المناسب. إذا كان الموقع الجغرافي ضروريًا لتشغيل تطبيقك، عليك طلب إذن تحديد الموقع الجغرافي عند بدء تشغيل التطبيق. ويمكن تحقيق ذلك من خلال شاشة ترحيب أو معالج يوضّح للمستخدمين سبب الحاجة إلى الإذن.
إذا كان التطبيق يتطلّب الإذن لجزء من وظائفه فقط، فعليك طلب إذن تحديد الموقع الجغرافي في الوقت الذي ينفّذ فيه التطبيق الإجراء الذي يتطلّب الإذن.
يجب أن يتعامل التطبيق بشكل سليم مع الحالات التي لا يمنح فيها المستخدم الإذن. على سبيل المثال، إذا كان الإذن مطلوبًا لميزة معيّنة، يمكن للتطبيق إيقاف هذه الميزة. إذا كان الإذن ضروريًا لكي يعمل التطبيق، يمكن للتطبيق إيقاف جميع وظائفه وإبلاغ المستخدم بأنّه بحاجة إلى منح الإذن.
تتحقّق عينة التعليمات البرمجية التالية من الإذن باستخدام مكتبة AndroidX قبل تفعيل طبقة "موقعي الجغرافي". ثم يتم التعامل مع نتيجة طلب الحصول على إذن من خلال تنفيذ ActivityCompat.OnRequestPermissionsResultCallback من "مكتبة الدعم"، وذلك على النحو التالي:
Kotlin
// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.example.kotlindemos import com.example.common_ui.catalog.Sample import com.example.common_ui.catalog.Complexity import com.example.common_ui.catalog.Framework import android.Manifest import android.annotation.SuppressLint import android.content.pm.PackageManager import android.location.Location import android.os.Bundle import android.view.View import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback import androidx.core.content.ContextCompat import com.example.common_ui.R import com.example.kotlindemos.PermissionUtils.PermissionDeniedDialog.Companion.newInstance import com.example.kotlindemos.PermissionUtils.isPermissionGranted import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment /** * This demo shows how GMS Location can be used to check for changes to the users location. The * "My Location" button uses GMS Location to set the blue dot representing the users location. * Permission for [Manifest.permission.ACCESS_FINE_LOCATION] and [Manifest.permission.ACCESS_COARSE_LOCATION] * are requested at run time. If either permission is not granted, the Activity is finished with an error message. */ @Sample( id = "com.example.kotlindemos.MyLocationDemoActivity", title = "My Location Layer", description = "Enabling blue dot location indicator and My Location button with runtime permissions.", category = "Location & Sensors", complexity = Complexity.SIMPLE, tags = ["#location", "#mylocation", "#permissions", "#bluedot"], purpose = "Demonstrates requesting ACCESS_FINE_LOCATION permissions and enabling the blue dot location layer.", successCriteria = "Tapping My Location button centers camera on user's current GPS position.", failureIndicators = "Permission denial causes unhandled crash or location button missing.", framework = Framework.KOTLIN_VIEWS ) class MyLocationDemoActivity : SamplesBaseActivity(), OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback, OnRequestPermissionsResultCallback { /** * Flag indicating whether a requested permission has been denied after returning in * [.onRequestPermissionsResult]. */ private var permissionDenied = false private lateinit var map: GoogleMap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.my_location_demo) val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment? mapFragment?.getMapAsync(this) applyInsets(findViewById(R.id.map_container)) } override fun onMapReady(googleMap: GoogleMap) { map = googleMap googleMap.setOnMyLocationButtonClickListener(this) googleMap.setOnMyLocationClickListener(this) enableMyLocation() } /** * Enables the My Location layer if the fine location permission has been granted. */ @SuppressLint("MissingPermission") private fun enableMyLocation() { // 1. Check if permissions are granted, if so, enable the my location layer if (ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) { map.isMyLocationEnabled = true return } // 2. If if a permission rationale dialog should be shown if (ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_FINE_LOCATION ) || ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_COARSE_LOCATION ) ) { PermissionUtils.RationaleDialog.newInstance( LOCATION_PERMISSION_REQUEST_CODE, true ).show(supportFragmentManager, "dialog") return } // 3. Otherwise, request permission ActivityCompat.requestPermissions( this, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ), LOCATION_PERMISSION_REQUEST_CODE ) } override fun onMyLocationButtonClick(): Boolean { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT) .show() // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false } override fun onMyLocationClick(location: Location) { Toast.makeText(this, "Current location:\n$location", Toast.LENGTH_LONG) .show() } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) { super.onRequestPermissionsResult( requestCode, permissions, grantResults ) return } if (isPermissionGranted( permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION ) || isPermissionGranted( permissions, grantResults, Manifest.permission.ACCESS_COARSE_LOCATION ) ) { // Enable the my location layer if the permission has been granted. enableMyLocation() } else { // Permission was denied. Display an error message // Display the missing permission error dialog when the fragments resume. permissionDenied = true } } override fun onResumeFragments() { super.onResumeFragments() if (permissionDenied) { // Permission was not granted, display error dialog. showMissingPermissionError() permissionDenied = false } } /** * Displays a dialog with error message explaining that the location permission is missing. */ private fun showMissingPermissionError() { newInstance(true).show(supportFragmentManager, "dialog") } companion object { /** * Request code for location permission request. * * @see .onRequestPermissionsResult */ private const val LOCATION_PERMISSION_REQUEST_CODE = 1 } }
جافا
// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.example.mapdemo; import com.example.common_ui.catalog.Sample; import com.example.common_ui.catalog.Complexity; import com.example.common_ui.catalog.Framework; import android.Manifest.permission; import android.annotation.SuppressLint; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMyLocationButtonClickListener; import com.google.android.gms.maps.GoogleMap.OnMyLocationClickListener; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import android.Manifest; import android.content.pm.PackageManager; import android.location.Location; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.widget.Toast; /** * This demo shows how GMS Location can be used to check for changes to the users location. The "My * Location" button uses GMS Location to set the blue dot representing the users location. * Permission for {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and {@link * android.Manifest.permission#ACCESS_COARSE_LOCATION} are requested at run time. If either * permission is not granted, the Activity is finished with an error message. */ @Sample( id = "my_location", title = "My Location Layer", description = "Enabling blue dot location indicator and My Location button with runtime permissions.", category = "Location & Sensors", complexity = Complexity.SIMPLE, tags = {"#location", "#mylocation", "#permissions", "#bluedot"}, purpose = "Demonstrates requesting ACCESS_FINE_LOCATION permissions and enabling the blue dot location layer.", successCriteria = "Tapping My Location button centers camera on user's current GPS position.", failureIndicators = "Permission denial causes unhandled crash or location button missing.", framework = Framework.JAVA_VIEWS ) public class MyLocationDemoActivity extends SamplesBaseActivity implements OnMyLocationButtonClickListener, OnMyLocationClickListener, OnMapReadyCallback, ActivityCompat.OnRequestPermissionsResultCallback { /** * Request code for location permission request. * * @see #onRequestPermissionsResult(int, String[], int[]) */ private static final int LOCATION_PERMISSION_REQUEST_CODE = 1; /** * Flag indicating whether a requested permission has been denied after returning in {@link * #onRequestPermissionsResult(int, String[], int[])}. */ private boolean permissionDenied = false; private GoogleMap map; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(com.example.common_ui.R.layout.my_location_demo); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(com.example.common_ui.R.id.map); mapFragment.getMapAsync(this); applyInsets(findViewById(com.example.common_ui.R.id.map_container)); } @Override public void onMapReady(@NonNull GoogleMap googleMap) { map = googleMap; map.setOnMyLocationButtonClickListener(this); map.setOnMyLocationClickListener(this); enableMyLocation(); } /** * Enables the My Location layer if the fine location permission has been granted. */ @SuppressLint("MissingPermission") private void enableMyLocation() { // 1. Check if permissions are granted, if so, enable the my location layer if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { map.setMyLocationEnabled(true); return; } // 2. Otherwise, request location permissions from the user. PermissionUtils.requestLocationPermissions(this, LOCATION_PERMISSION_REQUEST_CODE, true); } @Override public boolean onMyLocationButtonClick() { Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT).show(); // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false; } @Override public void onMyLocationClick(@NonNull Location location) { Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG).show(); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); return; } if (PermissionUtils.isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_FINE_LOCATION) || PermissionUtils .isPermissionGranted(permissions, grantResults, Manifest.permission.ACCESS_COARSE_LOCATION)) { // Enable the my location layer if the permission has been granted. enableMyLocation(); } else { // Permission was denied. Display an error message // Display the missing permission error dialog when the fragments resume. permissionDenied = true; } } @Override protected void onResumeFragments() { super.onResumeFragments(); if (permissionDenied) { // Permission was not granted, display error dialog. showMissingPermissionError(); permissionDenied = false; } } /** * Displays a dialog with error message explaining that the location permission is missing. */ private void showMissingPermissionError() { PermissionUtils.PermissionDeniedDialog .newInstance(true).show(getSupportFragmentManager(), "dialog"); } }
طبقة "موقعي الجغرافي"
يمكنك استخدام طبقة "موقعي الجغرافي" وزر "موقعي الجغرافي" لعرض الموضع الحالي للمستخدم على الخريطة. استخدِم mMap.setMyLocationEnabled()
لتفعيل طبقة "موقعي الجغرافي" على الخريطة.
يوضّح المثال التالي استخدامًا بسيطًا لطبقة "موقعي الجغرافي":
Kotlin
// TODO: Before enabling the My Location layer, you must request // location permission from the user. This sample does not include // a request for location permission. map.setMyLocationEnabled(true) map.setOnMyLocationButtonClickListener { Toast.makeText(context, "MyLocation button clicked", Toast.LENGTH_SHORT).show() // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). false } map.setOnMyLocationClickListener { location -> Toast.makeText(context, "Current location:\n$location", Toast.LENGTH_LONG).show() }
جافا
// TODO: Before enabling the My Location layer, you must request // location permission from the user. This sample does not include // a request for location permission. map.setMyLocationEnabled(true); map.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() { @Override public boolean onMyLocationButtonClick() { Toast.makeText(context, "MyLocation button clicked", Toast.LENGTH_SHORT).show(); // Return false so that we don't consume the event and the default behavior still occurs // (the camera animates to the user's current position). return false; } }); map.setOnMyLocationClickListener(new GoogleMap.OnMyLocationClickListener() { @Override public void onMyLocationClick(@NonNull Location location) { Toast.makeText(context, "Current location:\n" + location, Toast.LENGTH_LONG).show(); } });
عند تفعيل طبقة "موقعي الجغرافي"، يظهر زر "موقعي الجغرافي" في أعلى يسار الخريطة. عندما ينقر المستخدم على الزر، توسّط الكاميرا الخريطة على الموقع الجغرافي الحالي للجهاز، إذا كان معروفًا. يُشار إلى الموقع الجغرافي على الخريطة بنقطة زرقاء صغيرة إذا كان الجهاز ثابتًا، أو برمز شارة رتبة عسكرية إذا كان الجهاز يتحرّك.
تعرض لقطة الشاشة التالية زر مشاركة الموقع الجغرافي في أعلى يسار الصفحة والنقطة الزرقاء "موقعي الجغرافي" في وسط الخريطة:

يمكنك منع ظهور زر مشاركة الموقع الجغرافي من خلال استدعاء UiSettings.setMyLocationButtonEnabled(false).
يمكن لتطبيقك الاستجابة للأحداث التالية:
- إذا نقر المستخدم على زر مشاركة الموقع الجغرافي، يتلقّى تطبيقك طلب استدعاء
onMyLocationButtonClick()منGoogleMap.OnMyLocationButtonClickListener. - إذا نقر المستخدم على النقطة الزرقاء "موقعي الجغرافي"، سيتلقّى تطبيقك عملية ردّ
onMyLocationClick()منGoogleMap.OnMyLocationClickListener.
واجهة برمجة التطبيقات للموقع الجغرافي في "خدمات Google Play"
تُعدّ واجهة برمجة التطبيقات للموقع الجغرافي في "خدمات Google Play" الطريقة المفضّلة لإضافة ميزة "التعرّف على الموقع الجغرافي" إلى تطبيق Android. وتتضمّن وظائف تتيح لك:
- تحديد الموقع الجغرافي للجهاز
- الاستماع إلى تغييرات الموقع الجغرافي
- تحديد وسيلة النقل، في حال كان الجهاز يتحرّك
- يمكنك إنشاء مناطق جغرافية محدّدة مسبقًا ومراقبتها، تُعرف باسم الحدود الجغرافية.
تسهّل عليك واجهات برمجة التطبيقات الخاصة بالموقع الجغرافي إنشاء تطبيقات فعّالة من حيث استهلاك الطاقة وتستند إلى الموقع الجغرافي. وكما هو الحال مع حزمة تطوير البرامج بالاستناد إلى بيانات خرائط Google للتطبيقات المتوافقة مع Android، يتم توزيع واجهة برمجة التطبيقات للموقع الجغرافي كجزء من حزمة تطوير البرامج (SDK) الخاصة بـ خدمات Google Play. لمزيد من المعلومات حول واجهة برمجة التطبيقات للموقع الجغرافي، يُرجى الرجوع إلى فئة التدريب على Android جعل تطبيقك يتيح استخدام الموقع الجغرافي أو مرجع واجهة برمجة التطبيقات للموقع الجغرافي. يتم تضمين أمثلة الرموز كجزء من حزمة تطوير البرامج (SDK) لخدمات Google Play.