گوگل مپ برای اندروید بخش دوم: مکان کاربر

ترجمه و تالیف : پوریا شریفی
تاریخ انتشار : 20 دی 99
خواندن در 3 دقیقه
دسته بندی ها : اندروید

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

تنظیم مکان کاربر

در حالی که سیدنی (مکان پیش فرض دوربین فعلی ما) احتمالا یک شهر دوست داشتنی است، اولین کاری که خواهیم کرد این است که بفهمیم کاربر کجاست و دوربین را روی آنجا متمرکز کنیم. برای دریافت مکان کاربر، باید مجوز آن را در فایل AndroidManifest.xml و داخل برچسب manifest اضافه کنیم. ما در اینجا دو گزینه داریم: ما می‌توانیم  اطلاعات coarse location را درخواست کنیم، که مبتنی بر wifi و داده تلفن همراه است، یا می‌توانیم fine location را بگیریم که اطلاعات را از GPS گوشی دریافت می‌کند. برای این مثال ما از fine location استفاده می‌کنیم.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

پس از تعیین مجوز مورد نیاز در فایل manifest، باید صریحاً آن را برای دستگاه‌هایی که از اندروید Marshmallow و بالاتر استفاده می‌کنند، درخواست کنیم. به MapsActivity.kt برگردید و به تابع onMapReady بروید. ما قصد داریم این تابع را براساس اینکه کاربر مجوز را از قبل تایید کرده یا نه بروزرسانی کنیم. در صورتی که مجوز قبلا تایید شده باشد موقعیت مکانی آن‌ها را فعال می‌کنیم و در غیر این صورت از کاربر دوباره مجوز را درخواست می‌کنیم.

override fun onMapReady(googleMap: GoogleMap) {
    mMap = googleMap

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
        == PackageManager.PERMISSION_GRANTED) {
        initMap()
    } else {
        ActivityCompat.requestPermissions(this,
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
            LOCATION_PERMISSION)
    }
}

حتما متوجه شده‌اید که پارامتری به نام LOCATION_PERMISSION داریم که به requestPermission() پاس داده شده است. این مقداری است که شما برای پیگیری مجوز درخواستی در برنامه خود تنظیم می‌کنید.

private val LOCATION_PERMISSION = 42

اگر کاربر از قبل مجوز location را تایید کرده باشد، می‌توانید متد جدیدی به نام initMap() را فراخوانی کنید که شامل تمام منطق اولیه نقشه شما خواهد بود.

private fun initMap() {
    mMap.isMyLocationEnabled = true

    val sydney = LatLng(-34.0, 151.0)

    mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney"))
    mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney))
}

اگر کاربر هنوز مجوز location را نداده است، بنابراین به متد onRequestPermissionResult() منتقل می‌شوند، جایی که می‌توانید بررسی کنید آیا آن‌ها مجوز را تایید کرده‌اند یا نه و براساس آن واکنش نشان دهید.

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, 
        permissions, 
        grantResults)
    if (requestCode == LOCATION_PERMISSION) {
        if (permissions.size == 1 &&
            permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION &&
            grantResults[0] == PackageManager.PERMISSION_GRANTED
        ) {
            initMap()
        }
    }
}

در این مرحله اگر برنامه را اجرا کنید و بر روی دکمه My Location کلیک کنید:

باید ببینید که دوربین از سیدنی، استرالیا به سمت هر کجا که قرار دارید حرکت می‌کند و یک نقطه آبی کوچک نشان دهنده موقعیت شما است.

علاوه بر این می‌توانید چند listener پیاده سازی کنید که وقتی کاربر بر روی دکمه my location یا موقعیت مکانی خود (نقطه آبی رنگ) کلیک می‌کند، به شما اطلاع دهند.

class MapsActivity : AppCompatActivity(), OnMapReadyCallback,
    GoogleMap.OnMyLocationButtonClickListener,
    GoogleMap.OnMyLocationClickListener {

در حال حاضر بیایید فقط متدهای لازم برای این listenerها را داشته باشیم تا پیام Toast را نشان دهند.

override fun onMyLocationButtonClick(): Boolean {
    Toast.makeText(this, "my location button click", Toast.LENGTH_LONG).show()
    return false
}

override fun onMyLocationClick(location: Location) {
    Toast.makeText(this, "my location click", Toast.LENGTH_LONG).show()
}

برای اینکه این موارد فعال شوند، باید به رویدادها گوش دهید، که نیاز است دو خط زیر را به متد initMap() اضافه کنید.

mMap.setOnMyLocationButtonClickListener(this)
mMap.setOnMyLocationClickListener(this)

پاسخ خودکار به تغییرات

تاکنون در نمایش مکان کاربر روی نقشه پیشرفت خوبی داشته‌ایم، اما با این وجود کاربر باید دکمه‌ای را فشار دهد تا مرکز دوربین در موقعیت کاربر قرار گیرد. ما می‌توانیم با افزودن پکیج Location از خدمات Google Play در این مورد، در برنامه خود استفاده کنیم. با رفتن به فایل build.gradle ماژول app و اضافه کردن خط زیر به آن شروع می‌کنیم.

implementation 'com.google.android.gms:play-services-location:16.0.0'

با بازگشت به MainActivity.kt یک متغیر برای FusedLocationProviderClient ایجاد کنید، که با استفاده از آن به سیستم موقعیت مکانی اندروید متصل می‌شویم.

private lateinit var fusedLocationClient: FusedLocationProviderClient

می‌توانیم در onCreate() قبل از صدا زدن getMapAsync() نمونه‌ای از آن بگیریم.

fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)

حالا می‌توانید کدهای داخل initMap() را حذف کنید، که شامل دوربین و نشانگر در سیدنی است و آن را با کد زیر جایگزین کنید که به FusedLocationPrviderClient گوش می‌دهد و دوربین را در مکان فعلی کاربر قرار می‌دهد.

fusedLocationClient.lastLocation
    .addOnSuccessListener { location : Location? ->
        for (location in locationResult.locations){
            updateMapLocation(location)
        }
    }

که در کد بالا updateMapLocation به صورت زیر تعریف شده است.

private fun updateMapLocation(location: Location?) {
    mMap.moveCamera(CameraUpdateFactory.newLatLng(LatLng(
        location?.latitude ?: 0.0,
        location?.longitude ?: 0.0)))

    mMap.moveCamera(CameraUpdateFactory.zoomTo(15.0f))
}

پس از اجرای برنامه خود، باید ببینید که دوربین به طور خودکار روی مکان فعلی شما با بزرگنمایی از پیش تعیین شده تنظیم شده است. این زمان خوبی است تا با سطح بزرگنمایی بازی کنید و سطح مورد نظر خود را پیدا کنید. به عنوان مثال سطح 15.0f مکان نسبتاً نزدیکی به کاربر دارد.

3.0f آنقدر بزرگنمایی می‌کند که بخش عضیمی از زمین را پوشش می‌دهد.

همچنین اطلاعات دقیق‌تر در مورد مناطق اطراف کاربر در بزرگنمایی نزدیکتر وجود دارد. در آموزش بعدی، جزئیات بیشتری در باره دوربین نقشه خواهیم داشت.

بروزرسانی مکان کاربر به طور مداوم

نکته‌ای که در این تنظیمات وجود دارد این است که هنگام حرکت کاربر مکان بروز نمی‌شود. برای دستیابی به این مورد، می‌توانیم به LocationCallback گوش دهیم تا موقعیت کاربر را به طور مداوم بروز کنیم. در بالای MainActivity.kt یک متغیر جدید برای callback ایجاد کنید.

private lateinit var locationCallback: LocationCallback

این مقدار هر وقت که بخواهیم به موقعیت کاربر گوش دهیم همانند زیر مقداردهی می‌شود.

private fun initLocationTracking() {
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            for (location in locationResult.locations){
                updateMapLocation(location)
            }
        }
    }

    fusedLocationClient.requestLocationUpdates(
        LocationRequest(),
        locationCallback,
        null)
}

در اینجا متوجه خواهید شد که ما فقط یک callback ایجاد نمی‌کنیم و در پایان تابع فوق یک درخواست با FusedLocationProviderCLient برای بروزرسانی مکان کاربر انجام می‌دهیم.

برای شروع گوش دادن به این بروزرسانی موقعیت مکانی، باید متد جدید initLocationTracking() را هم در initMap() و هم در onResume() فراخوانی کنید. دلیل این که ما در onResume() هم درخواست موقعیت مکانی می‎دهیم این است که گوش دادن را وقتی برنامه در background است را متوقف می‌کنیم، اما می‌خواهیم به محض بازگشت کاربر آن را دوباره راه اندازی کنیم.

override fun onResume() {
    super.onResume()
    if( ::mMap.isInitialized ) {
        initLocationTracking()
    }
}

override fun onPause() {
    super.onPause()
    fusedLocationClient.removeLocationUpdates(locationCallback)
}

در این مرحله منطقی است که این کد را از قسمت قبلی در مورد آخرین مکان کاربر حذف کنیم:

fusedLocationClient.lastLocation
    .addOnSuccessListener { location : Location? ->
        for (location in locationResult.locations){
            updateMapLocation(location)
        }
    }

با نوشتن این کدها، دوربین در هنگام ازسرگیری برنامه یا دریافت موقعیت مکانی، همیشه روی کاربر تمرکز می‌کند. این ممکن است چیزی که شما بخواهید نباشد، بنابراین لازم است که شما به هر طریقی که برای پروژه‌های خود منطقی باشد به تغییرات مکان کاربر پاسخ دهید.

نتیجه

در این مقاله یادگرفته‌اید که چگونه برنامه‌های گوگل مپ خود را در اندروید بروز کنید تا داده‌ها موقعیت مکانی کاربر را در آن بگنجانید. با این امکان که به کاربر نشان دهید در کجای دنیا است و چه چیزهایی در اطراف او هستند، می‌توانید از برنامه خود به آن‌ها ارزش بیشتری بدهید و به آن‌ها کمک کنید تا به اهداف خود برسند. می‌توانید کد منبع این پروژه را در Github پیدا کنید.

منبع

گردآوری و تالیف پوریا شریفی
آفلاین
user-avatar

ابتدا که با برنامه‌نویسی آشنا شدم به سمت php و طراحی وب رفتم، بعد از اون به توسعه‌ی اندروید علاقه‌مند شدم و تقریبا ۲ سال است که مشغول به برنامه‌نویسی اندروید هستم، همچنین عاشق یادگیری چیزهای جدید هستم.

دیدگاه‌ها و پرسش‌ها

برای ارسال نظر لازم است ابتدا وارد سایت شوید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید