داده‌های مکان

یکی از ویژگی‌های منحصربه‌فرد برنامه‌های تلفن همراه، آگاهی از مکان است. کاربران تلفن همراه دستگاه‌هایشان را همه‌جا با خود می‌برند و افزودن آگاهی از مکان به برنامه‌تان تجربه زمینه‌ای بیشتری به کاربران ارائه می‌دهد.

نمونه‌های کد

مخزن ApiDemos در GitHub شامل نمونه‌هایی است که استفاده از مکان را در نقشه نشان می‌دهد:

Kotlin

جاوا

کار کردن با داده‌های مکان

داده‌های مکان دردسترس دستگاه 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>

درخواست اجازه‌های زمان اجرا

‫Android 6.0 (Marshmallow) مدل جدیدی برای مدیریت اجازه‌ها معرفی می‌کند که فرایند نصب و ارتقای برنامه‌ها را برای کاربران ساده می‌کند. اگر برنامه شما سطح API 23 یا بالاتر را هدف‌یابی می‌کند، می‌توانید از مدل اجازه‌های جدید استفاده کنید.

اگر برنامه شما از مدل اجازه‌های جدید پشتیبانی می‌کند و دستگاه از Android نسخه ۶.۰ (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 services Location API

میانای برنامه‌سازی کاربردی مکان خدمات Google Play روش ترجیحی برای افزودن آگاهی از مکان به برنامه Android شما است. این برنامه شامل عملکردهایی است که به شما امکان می‌دهد:

  • مکان دستگاه را تعیین کند.
  • گوش دادن به تغییرات مکان.
  • اگر دستگاه درحال حرکت باشد، نوع حمل‌ونقل را تعیین می‌کند.
  • مناطق جغرافیایی ازپیش تعریف‌شده را که حصار جغرافیایی نامیده می‌شوند ایجاد و نظارت کنید.

میاناهای برنامه‌سازی کاربردی مکان به شما کمک می‌کنند برنامه‌هایی با مصرف بهینه انرژی و آگاه از مکان بسازید. مانند «کیت توسعه نرم‌افزار Google Maps برای Android»، «میانای برنامه‌سازی کاربردی مکان» به‌عنوان بخشی از «کیت توسعه نرم‌افزار خدمات Google Play» توزیع می‌شود. برای اطلاعات بیشتر درباره Location API، لطفاً به کلاس آموزشی Android آگاه کردن برنامه از مکان یا مرجع Location API مراجعه کنید. نمونه‌های کد به‌عنوان بخشی از کیت توسعه نرم‌افزار «خدمات Google Play» گنجانده شده است.