اندروید پیشرفته 09.1: Google Maps

۱. خوش آمدید

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

برای جزئیات کامل در مورد دوره، به نمای کلی توسعه پیشرفته اندروید مراجعه کنید .

مقدمه

ساخت برنامه‌ها با نقشه‌های گوگل به شما این امکان را می‌دهد که ویژگی‌هایی مانند تصاویر ماهواره‌ای، کنترل‌های رابط کاربری قوی، ردیابی موقعیت مکانی و نشانگرهای موقعیت مکانی را به برنامه خود اضافه کنید. می‌توانید با نمایش اطلاعات از مجموعه داده‌های خود، مانند مکان‌های مناطق ماهیگیری یا کوهنوردی شناخته شده، به نقشه‌های استاندارد گوگل ارزش ببخشید. همچنین می‌توانید بازی‌هایی مانند Pokemon Go که به دنیای واقعی مرتبط هستند، ایجاد کنید.

در این آموزش کاربردی، شما یک برنامه نقشه گوگل به نام Wander ایجاد می‌کنید.

آنچه باید از قبل بدانید

شما باید با موارد زیر آشنا باشید:

  • قابلیت‌های اساسی نقشه‌های گوگل
  • مجوزهای زمان اجرا.
  • ایجاد، ساخت و اجرای برنامه‌ها در اندروید استودیو
  • گنجاندن کتابخانه‌های خارجی در فایل build.gradle شما.

آنچه یاد خواهید گرفت

  • نقشه گوگل را در برنامه خود ادغام کنید.
  • نمایش انواع مختلف نقشه
  • به نقشه گوگل استایل بدهید.
  • نشانگرها را به نقشه خود اضافه کنید.
  • کاربر را قادر می‌سازد تا یک نشانگر را روی یک نقطه مورد نظر (POI) قرار دهد.
  • فعال کردن ردیابی موقعیت مکانی
  • نمای خیابان گوگل را فعال کنید.

کاری که انجام خواهید داد

  • یک کلید API از کنسول API گوگل دریافت کنید و کلید را در برنامه خود ثبت کنید.
  • اپلیکیشن Wander را ایجاد کنید که یک نقشه گوگل در آن تعبیه شده باشد.
  • ویژگی‌های سفارشی مانند نشانگرها، استایل‌بندی و ردیابی موقعیت مکانی را به برنامه خود اضافه کنید.
  • ردیابی موقعیت مکانی و نمای خیابان را در برنامه خود فعال کنید.

۲. مرور کلی برنامه

در این آموزش کاربردی، شما برنامه Wander را ایجاد می‌کنید که یک نقشه گوگل با استایل خاص است. برنامه Wander به شما امکان می‌دهد نشانگرها را روی مکان‌ها قرار دهید، مکان خود را به صورت زنده ببینید و به پانوراماهای Street View نگاه کنید.

یک نقشه گوگل با استایل خاص

نمای خیابان گوگل در یک برنامه اندروید

۳. وظیفه ۱. راه‌اندازی پروژه و دریافت کلید API

API نقشه‌های گوگل، مانند API مکان‌ها، به یک کلید API نیاز دارد. برای دریافت کلید API، پروژه خود را در کنسول API گوگل ثبت می‌کنید. کلید API به یک گواهی دیجیتال متصل است که برنامه را به نویسنده آن پیوند می‌دهد. برای اطلاعات بیشتر در مورد استفاده از گواهی‌های دیجیتال و امضای برنامه، به بخش «امضای برنامه» مراجعه کنید.

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

اندروید استودیو شامل یک الگوی فعالیت نقشه‌های گوگل است که کد الگوی مفیدی تولید می‌کند. کد الگو شامل یک فایل google_maps_api.xml است که حاوی لینکی است که دریافت کلید API را ساده می‌کند.

۱.۱ ایجاد پروژه Wander با استفاده از الگوی Maps

  1. یک پروژه جدید اندروید استودیو ایجاد کنید.
  2. نام برنامه جدید را «Wander» بگذارید. تا زمانی که به صفحه «افزودن یک فعالیت» برسید، پیش‌فرض‌ها را بپذیرید.
  3. الگوی فعالیت نقشه‌های گوگل را انتخاب کنید.
  4. نام فعالیت (Activity Name) و نام طرح‌بندی (Layout Name) را به صورت پیش‌فرض باقی بگذارید.
  5. عنوان را به "Wander" تغییر دهید و روی Finish کلیک کنید.

اندروید استودیو چندین فایل اضافی مرتبط با نقشه ایجاد می‌کند:

google_maps_api**.xml**

شما از این فایل پیکربندی برای نگهداری کلید API خود استفاده می‌کنید. این الگو دو فایل google_maps_api.xml تولید می‌کند: یکی برای اشکال‌زدایی (debug) و دیگری برای انتشار (release). فایل مربوط به کلید API برای گواهی اشکال‌زدایی در src/debug/res/values ​​قرار دارد. فایل مربوط به کلید API برای گواهی انتشار در src/release/res/values ​​قرار دارد. در این مورد عملی، ما فقط از گواهی اشکال‌زدایی استفاده می‌کنیم.

activity_maps.xml

این فایل طرح‌بندی شامل یک قطعه کد واحد است که کل صفحه را پر می‌کند. کلاس SupportMapFragment یک زیرکلاس از کلاس Fragment است. می‌توانید SupportMapFragment با استفاده از یک تگ <fragment> در هر ViewGroup و با یک ویژگی اضافی، در یک فایل طرح‌بندی قرار دهید:

android:name="com.google.android.gms.maps.SupportMapFragment"

MapsActivity.java

فایل MapsActivity.java کلاس SupportMapFragment نمونه‌سازی می‌کند و از متد getMapAsync() کلاس برای آماده‌سازی نقشه گوگل استفاده می‌کند. اکتیویتی که شامل SupportMapFragment است باید رابط OnMapReadyCallback و متد onMapReady() آن رابط را پیاده‌سازی کند. متد getMapAsync() یک شیء GoogleMap را برمی‌گرداند که نشان می‌دهد نقشه بارگذاری شده است.

۱.۲ دریافت کلید API

  1. نسخه اشکال‌زدایی فایل google_maps_api.xml را باز کنید.

این فایل شامل یک کامنت با یک URL طولانی است. پارامترهای URL شامل اطلاعات خاصی در مورد برنامه شما هستند.

  1. آدرس اینترنتی (URL) را کپی کرده و در مرورگر جایگذاری کنید.
  2. برای ایجاد یک پروژه در کنسول API گوگل، دستورالعمل‌ها را دنبال کنید. به دلیل پارامترهای موجود در URL ارائه شده، کنسول API می‌داند که به طور خودکار API اندروید نقشه‌های گوگل را فعال کند.
  3. یک کلید API ایجاد کنید و برای محدود کردن استفاده از کلید به برنامه‌های اندروید، روی Restrict Key کلیک کنید. کلید API تولید شده باید با AIza شروع شود.
  4. در فایل google_maps_api.xml ، کلید را در رشته google_maps_key جایی که YOUR_KEY_HERE نوشته شده است، جایگذاری کنید.
  5. برنامه خود را اجرا کنید. شما یک نقشه جاسازی شده در activity خود دارید که نشانگر آن در سیدنی، استرالیا تنظیم شده است. (نشانگر سیدنی بخشی از الگو است و بعداً آن را تغییر می‌دهید.)

۴. وظیفه ۲. اضافه کردن انواع نقشه و نشانگرها

نقشه‌های گوگل شامل چندین نوع نقشه هستند: معمولی، ترکیبی، ماهواره‌ای، زمینی و «هیچکدام». در این کار، یک نوار برنامه با منوی گزینه‌ها اضافه می‌کنید که به کاربر اجازه می‌دهد نوع نقشه را تغییر دهد. شما محل شروع نقشه را به محل خانه خود منتقل می‌کنید. سپس پشتیبانی از نشانگرها را اضافه می‌کنید که مکان‌های منفرد را روی نقشه نشان می‌دهند و می‌توانند شامل یک برچسب باشند.

۲.۱ اضافه کردن انواع نقشه

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

  1. برای ایجاد یک فایل XML منوی جدید، روی دایرکتوری res خود کلیک راست کرده و New > Android Resource File را انتخاب کنید.
  2. در پنجره‌ی باز شده، نام فایل را map_options بگذارید. برای نوع منبع، Menu را انتخاب کنید. روی OK کلیک کنید.
  3. کد موجود در فایل جدید را با کد زیر جایگزین کنید تا گزینه‌های نقشه ایجاد شوند. نوع نقشه "none" حذف شده است، زیرا "none" به معنای عدم وجود هرگونه نقشه است.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item android:id="@+id/normal_map"
       android:title="@string/normal_map"
       app:showAsAction="never"/>
   <item android:id="@+id/hybrid_map"
       android:title="@string/hybrid_map"
       app:showAsAction="never"/>
   <item android:id="@+id/satellite_map"
       android:title="@string/satellite_map"
       app:showAsAction="never"/>
   <item android:id="@+id/terrain_map"
       android:title="@string/terrain_map"
       app:showAsAction="never"/>
</menu>
  1. منابع رشته‌ای برای ویژگی‌های title ایجاد کنید.
  2. در فایل MapsActivity ، کلاس را طوری تغییر دهید که به جای بسط کلاس FragmentActivity ، از کلاس AppCompatActivity ارث‌بری کند. استفاده از AppCompatActivity نوار برنامه را نمایش می‌دهد و بنابراین منو را نیز نشان می‌دهد.
  3. در MapsActivity ، متد onCreateOptionsMenu() را بازنویسی کنید و فایل map_options inflate کنید:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
   MenuInflater inflater = getMenuInflater();
   inflater.inflate(R.menu.map_options, menu);
   return true;
}
  1. برای تغییر نوع نقشه، از متد setMapType () روی شیء GoogleMap استفاده کنید و یکی از ثابت‌های نوع نقشه را به آن ارسال کنید.

متد onOptionsItemSelected() را بازنویسی کنید. کد زیر را برای تغییر نوع نقشه هنگام انتخاب یکی از گزینه‌های منو توسط کاربر، قرار دهید:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       // Change the map type based on the user's selection.
       switch (item.getItemId()) {
           case R.id.normal_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
               return true;
           case R.id.hybrid_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
               return true;
           case R.id.satellite_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
               return true;
           case R.id.terrain_map:
               mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
               return true;
           default:
               return super.onOptionsItemSelected(item);
       }
    }
  1. برنامه را اجرا کنید. از منوی موجود در نوار برنامه برای تغییر نوع نقشه استفاده کنید. توجه کنید که ظاهر نقشه چگونه تغییر می‌کند.

۲.۲ مکان پیش‌فرض نقشه را جابجا کنید

به طور پیش‌فرض، تابع فراخوانی onMapReady() شامل کدی است که یک نشانگر را در سیدنی، استرالیا، جایی که نقشه‌های گوگل ایجاد شده‌اند، قرار می‌دهد. این تابع فراخوانی پیش‌فرض همچنین نقشه را طوری متحرک می‌کند که به سیدنی حرکت کند. در این مرحله، شما نقشه را بدون قرار دادن نشانگر به موقعیت مکانی خود حرکت می‌دهید، سپس تا سطحی که مشخص می‌کنید بزرگنمایی می‌کنید.

  1. در متد onMapReady() ، کدی که نشانگر را در سیدنی قرار می‌دهد و دوربین را حرکت می‌دهد، حذف کنید.
  2. در مرورگر خود به آدرس www.google.com/maps بروید و خانه خود را پیدا کنید.
  3. روی مکان مورد نظر کلیک راست کرده و گزینه‌ی «اینجا چیست؟» را انتخاب کنید.

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

  1. یک شیء LatLng جدید به نام home ایجاد کنید. در شیء LatLng ، از مختصاتی که از نقشه‌های گوگل در مرورگر پیدا کرده‌اید، استفاده کنید.
  2. یک متغیر float به نام zoom ایجاد کنید و متغیر را روی سطح زوم اولیه دلخواه خود تنظیم کنید. لیست زیر به شما ایده‌ای از میزان جزئیاتی که هر سطح زوم نشان می‌دهد، می‌دهد:
  • 1 : جهان
  • 5 : خشکی/قاره
  • 10 : شهر
  • 15 : خیابان‌ها
  • 20 : ساختمان‌ها
  1. با استفاده از CameraUpdateFactory.newLatLngZoom() ‎، یک شیء CameraUpdate ایجاد کنید و شیء LatLng و متغیر zoom خود را به آن ارسال کنید. با فراخوانی moveCamera() ‎ روی شیء GoogleMap و ارسال شیء جدید CameraUpdate ، دوربین را حرکت داده و بزرگنمایی کنید:
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(home, zoom));
  1. برنامه را اجرا کنید. نقشه باید به سمت خانه شما حرکت کند و روی سطح مورد نظر زوم شود.

۲.۳ اضافه کردن نشانگرهای نقشه

نقشه‌های گوگل می‌توانند با استفاده از یک نشانگر که شما با استفاده از کلاس Marker ایجاد می‌کنید، یک مکان را مشخص کنند. نشانگر پیش‌فرض از آیکون استاندارد نقشه‌های گوگل استفاده می‌کند: نشانگر نقشه‌های گوگل

شما می‌توانید نشانگرها را گسترش دهید تا اطلاعات زمینه‌ای را در پنجره‌های اطلاعات نشان دهید.

در این مرحله، وقتی کاربر مکانی را روی نقشه لمس کرده و نگه می‌دارد، یک نشانگر اضافه می‌کنید. سپس یک InfoWindow اضافه می‌کنید که مختصات نشانگر را هنگام لمس نشانگر نمایش می‌دهد.

یک پنجره اطلاعات برای پین افتاده

  1. یک متد stub در MapsActivity به نام setMapLongClick() ایجاد کنید که یک GoogleMap final را به عنوان آرگومان دریافت کرده و void را برمی‌گرداند:
private void setMapLongClick(final GoogleMap map) {}
  1. از متد setOnMapLongClickListener() شیء GoogleMap برای قرار دادن یک نشانگر در جایی که کاربر لمس کرده و نگه می‌دارد استفاده کنید. یک نمونه جدید از OnMapLongClickListener را که متد onMapLongClick() را لغو می‌کند، به آن ارسال کنید. آرگومان ورودی یک شیء LatLng است که شامل مختصات مکانی است که کاربر فشار داده است:
private void setMapLongClick(final GoogleMap map) {
   map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
       @Override
       public void onMapLongClick(LatLng latLng) {
       }
   });
}
  1. درون onMapLongClick() ، متد addMarker() را فراخوانی کنید. یک شیء MarkerOptions جدید با موقعیت تنظیم شده روی LatLng ارسالی، به آن ارسال کنید:
map.addMarker(new MarkerOptions().position(latLng));
  1. تابع setMapLongClick() را در انتهای متد onMapReady() فراخوانی کنید. mMap را به آن ارسال کنید.
  2. برنامه را اجرا کنید. برای قرار دادن یک نشانگر در یک مکان، روی نقشه لمس کرده و نگه دارید.
  3. روی نشانگر ضربه بزنید، که آن را در مرکز صفحه قرار می‌دهد.

دکمه‌های ناوبری در سمت چپ پایین صفحه نمایش داده می‌شوند و به کاربر اجازه می‌دهند تا از برنامه Google Maps برای پیمایش به موقعیت مشخص شده استفاده کند.

برای افزودن یک پنجره اطلاعات برای نشانگر:

  1. در شیء MarkerOptions ، فیلد title و فیلد snippet را تنظیم کنید.
  2. در onMapLongClick() ، فیلد title را روی "Dropped Pin" تنظیم کنید. فیلد snippet را روی مختصات مکان درون متد addMarker() تنظیم کنید.
map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {
   @Override
   public void onMapLongClick(LatLng latLng) {
       String snippet = String.format(Locale.getDefault(),
               "Lat: %1$.5f, Long: %2$.5f",
               latLng.latitude,
               latLng.longitude);

       map.addMarker(new MarkerOptions()
               .position(latLng)
               .title(getString(R.string.dropped_pin))
               .snippet(snippet));
   }
});
  1. برنامه را اجرا کنید. برای نمایش نشانگر مکان، روی نقشه لمس کرده و نگه دارید. برای نمایش پنجره اطلاعات، روی نشانگر ضربه بزنید.

۲.۴ افزودن شنونده‌ی POI

به طور پیش‌فرض، نقاط مورد علاقه (POI) به همراه نمادهای مربوطه‌شان روی نقشه ظاهر می‌شوند. POIها شامل پارک‌ها، مدارس، ساختمان‌های دولتی و موارد دیگر می‌شوند. وقتی نوع نقشه روی normal تنظیم شود، POIهای تجاری نیز روی نقشه ظاهر می‌شوند. POIهای تجاری نشان‌دهنده مشاغلی مانند مغازه‌ها، رستوران‌ها و هتل‌ها هستند.

در این مرحله، یک GoogleMap.OnPoiClickListener به نقشه اضافه می‌کنید. این click-listener به جای اینکه منتظر لمس و نگه داشتن انگشت بماند، فوراً یک نشانگر روی نقشه قرار می‌دهد. click-listener همچنین پنجره اطلاعاتی را که شامل نام POI است نمایش می‌دهد.

نشانگر نقطه مورد نظر

  1. یک متد stub در MapsActivity به نام setPoiClick() ایجاد کنید که یک GoogleMap final را به عنوان آرگومان دریافت کرده و void را برمی‌گرداند:
private void setPoiClick(final GoogleMap map) {}
  1. در متد setPoiClick() ، یک OnPoiClickListener روی GoogleMap ارسالی تنظیم کنید:
map.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
   @Override
   public void onPoiClick(PointOfInterest poi) {
   }
});
  1. در متد onPoiClick() ، یک نشانگر در محل POI قرار دهید. عنوان را برابر با نام POI قرار دهید. نتیجه را در متغیری به نام poiMarker ذخیره کنید.
public void onPoiClick(PointOfInterest poi) {
   Marker poiMarker = mMap.addMarker(new MarkerOptions()
       .position(poi.latLng)
       .title(poi.name);
}
  1. برای نمایش فوری پنجره اطلاعات، تابع showInfoWindow() را روی poiMarker فراخوانی کنید.
poiMarker.showInfoWindow();
  1. تابع setPoiClick() در انتهای تابع onMapReady() فراخوانی کنید. mMap را به آن ارسال کنید.
  2. برنامه خود را اجرا کنید و یک POI مانند یک پارک پیدا کنید. روی POI ضربه بزنید تا یک نشانگر روی آن قرار گیرد و نام POI در یک پنجره اطلاعات نمایش داده شود.

۵. وظیفه ۳. نقشه خود را سبک‌بندی کنید

شما می‌توانید نقشه‌های گوگل را از بسیاری جهات سفارشی کنید و به نقشه خود ظاهر و حس منحصر به فردی ببخشید.

شما می‌توانید یک شیء MapFragment را با استفاده از ویژگی‌های XML موجود، همانطور که هر قطعه دیگری را سفارشی می‌کنید، سفارشی کنید. با این حال، در این مرحله، ظاهر و حس محتوای MapFragment را با استفاده از متدهای موجود در شیء GoogleMap سفارشی می‌کنید. شما از جادوگر استایل‌دهی آنلاین برای اضافه کردن یک استایل به نقشه خود و سفارشی کردن نشانگرهای خود استفاده می‌کنید. همچنین یک GroundOverlay به مکان اصلی خود اضافه می‌کنید که با نقشه مقیاس‌بندی و چرخش می‌شود.

۳.۱ به نقشه خود سبک اضافه کنید

برای ایجاد یک سبک سفارشی برای نقشه خود، یک فایل JSON ایجاد می‌کنید که نحوه نمایش ویژگی‌های نقشه را مشخص می‌کند. لازم نیست این فایل JSON را به صورت دستی ایجاد کنید: گوگل Styling Wizard را ارائه می‌دهد که پس از استایل‌دهی بصری نقشه، JSON را برای شما تولید می‌کند. در این روش عملی، شما نقشه را برای "حالت شب" استایل‌دهی می‌کنید، به این معنی که نقشه از رنگ‌های کم‌رنگ و کنتراست کم برای استفاده در شب استفاده می‌کند.

  1. در مرورگر خود به آدرس https://mapstyle.withgoogle.com/ بروید.
  2. ایجاد یک سبک را انتخاب کنید.
  3. تم شب را انتخاب کنید.
  4. روی گزینه‌های بیشتر در پایین منو کلیک کنید.
  5. در پایین لیست نوع ویژگی ، آب > پر کردن را انتخاب کنید. رنگ آب را به آبی تیره تغییر دهید (برای مثال، #160064).
  6. روی Finish کلیک کنید. کد JSON را از پنجره‌ی بازشو کپی کنید.
  7. در اندروید استودیو، یک پوشه منابع به نام raw در پوشه res ایجاد کنید. یک فایل در res/raw به نام map_style.json ایجاد کنید.
  8. کد JSON را در فایل منبع جدید قرار دهید.
  9. برای تنظیم سبک JSON روی نقشه، تابع setMapStyle() را روی شیء GoogleMap فراخوانی کنید. یک شیء MapStyleOptions به آن ارسال کنید که فایل JSON را بارگذاری می‌کند. متد setMapStyle() یک مقدار بولی برمی‌گرداند که نشان‌دهنده موفقیت‌آمیز بودن استایل‌بندی است. اگر فایل قابل بارگذاری نباشد، متد خطای Resources.NotFoundException را صادر می‌کند.

کد زیر را در متد onMapReady() کپی کنید تا نقشه را استایل‌دهی کنید. ممکن است لازم باشد یک رشته TAG برای دستورات لاگ خود ایجاد کنید:

     try {
        // Customize the styling of the base map using a JSON object defined
        // in a raw resource file.
        boolean success = googleMap.setMapStyle(
           MapStyleOptions.loadRawResourceStyle(
                   this, R.raw.map_style));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
     } catch (Resources.NotFoundException e) {
        Log.e(TAG, "Can't find style. Error: ", e);
     }
  1. برنامه خود را اجرا کنید. استایل جدید باید زمانی که نقشه در حالت normal است، قابل مشاهده باشد.

نقشه گوگل در حالت شب

۳.۲ به نشانگر خود استایل بدهید

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

  1. در متد onMapLongClick() ، خط کد زیر را به سازنده‌ی MarkerOptions() اضافه کنید تا از نشانگر پیش‌فرض استفاده شود اما رنگ آن به آبی تغییر کند:
.icon(BitmapDescriptorFactory.defaultMarker
       (BitmapDescriptorFactory.HUE_BLUE))
  1. برنامه را اجرا کنید. نشانگرهایی که قرار می‌دهید اکنون به رنگ آبی سایه‌دار شده‌اند که با تم حالت شب برنامه سازگارتر است.

توجه داشته باشید که نشانگرهای POI هنوز قرمز هستند، زیرا شما به متد onPoiClick() استایل اضافه نکرده‌اید.

۳.۳ یک پوشش اضافه کنید

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

  • اشکال: می‌توانید چندخطی‌ها ، چندضلعی‌ها و دایره‌ها را به نقشه اضافه کنید.
  • اشیاء TileOverlay : یک پوشش کاشی، مجموعه‌ای از تصاویر را تعریف می‌کند که روی کاشی‌های نقشه پایه اضافه می‌شوند. پوشش‌های کاشی زمانی مفید هستند که می‌خواهید تصاویر گسترده‌ای به نقشه اضافه کنید. یک پوشش کاشی معمولی، منطقه جغرافیایی بزرگی را پوشش می‌دهد.
  • اشیاء GroundOverlay : یک پوشش زمینی، تصویری است که به نقشه ثابت می‌شود. برخلاف نشانگرها، پوشش‌های زمینی به جای صفحه نمایش، به سمت سطح زمین جهت‌گیری می‌شوند. چرخاندن، کج کردن یا بزرگنمایی نقشه، جهت تصویر را تغییر می‌دهد. پوشش‌های زمینی زمانی مفید هستند که می‌خواهید یک تصویر واحد را در یک ناحیه روی نقشه ثابت کنید.

در این مرحله، یک پوشش زمینی به شکل یک اندروید به محل خانه خود اضافه می‌کنید.

  1. این تصویر اندروید را دانلود کنید و آن را در پوشه res/drawable خود ذخیره کنید.
  2. در onMapReady() ، پس از فراخوانی برای انتقال دوربین به موقعیت خانه، یک شیء GroundOverlayOptions ایجاد کنید. این شیء را به متغیری به نام homeOverlay اختصاص دهید:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions();
  1. از متد BitmapDescriptorFactory.fromResource() برای ایجاد یک شیء BitmapDescriptor از تصویر بالا استفاده کنید. شیء را به متد image() از شیء GroundOverlayOptions ارسال کنید:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.android));
  1. با فراخوانی متد position() ویژگی position را برای شیء GroundOverlayOptions تنظیم کنید. شیء home LatLng و یک float برای عرض پوشش مورد نظر بر حسب متر ارسال کنید. برای این مثال، عرض ۱۰۰ متر به خوبی کار می‌کند:
GroundOverlayOptions homeOverlay = new GroundOverlayOptions()
     .image(BitmapDescriptorFactory.fromResource(R.drawable.android))
       .position(home, 100);
  1. تابع addGroundOverlay() را روی شیء GoogleMap فراخوانی کنید. شیء GroundOverlayOptions خود را به آن ارسال کنید:
mMap.addGroundOverlay(homeOverlay);
  1. برنامه را اجرا کنید. روی موقعیت مکانی خود زوم کنید، تصویر اندروید را به صورت یک لایه رویی مشاهده خواهید کرد.

۶. وظیفه ۴. فعال کردن ردیابی موقعیت مکانی و نمای خیابان

کاربران اغلب از نقشه‌های گوگل برای دیدن مکان فعلی خود استفاده می‌کنند و شما می‌توانید با استفاده از API سرویس‌های مکان، مکان دستگاه را به دست آورید. برای نمایش مکان دستگاه روی نقشه خود بدون استفاده بیشتر از داده‌های Location ، می‌توانید از لایه داده‌های مکان استفاده کنید.

لایه داده‌های مکانی، دکمه‌ای با عنوان «موقعیت مکانی من» را به سمت راست بالای نقشه اضافه می‌کند. وقتی کاربر روی این دکمه ضربه می‌زند، نقشه روی موقعیت مکانی دستگاه متمرکز می‌شود. اگر دستگاه ثابت باشد، موقعیت مکانی به صورت نقطه آبی و اگر در حال حرکت باشد، به صورت یک شورون آبی نشان داده می‌شود.

یک نقشه گوگل با استایل خاص و قابلیت ردیابی موقعیت مکانی

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

در این کار، شما لایه داده‌های مکانی و نمای خیابان را فعال می‌کنید تا وقتی کاربر روی پنجره اطلاعات مربوط به نشانگر POI ضربه می‌زند، نقشه به حالت نمای خیابان برود.

۴.۱ فعال کردن ردیابی موقعیت مکانی

فعال کردن ردیابی موقعیت مکانی در گوگل مپ به یک خط کد نیاز دارد. با این حال، باید مطمئن شوید که کاربر مجوزهای موقعیت مکانی را اعطا کرده است (با استفاده از مدل runtime-permission).

در این مرحله، مجوزهای موقعیت مکانی را درخواست می‌کنید و ردیابی موقعیت مکانی را فعال می‌کنید.

  1. در فایل AndroidManifest.xml ، تأیید کنید که مجوز FINE_LOCATION از قبل وجود دارد. اندروید استودیو این مجوز را هنگام انتخاب الگوی Google Maps وارد کرده است.
  2. برای فعال کردن ردیابی موقعیت مکانی در برنامه خود، یک متد در MapsActivity به نام enableMyLocation() ایجاد کنید که هیچ آرگومانی دریافت نمی‌کند و چیزی را برنمی‌گرداند.
  3. متد enableMyLocation() را تعریف کنید. مجوز ACCESS_FINE_LOCATION را بررسی کنید. اگر مجوز اعطا شده باشد، لایه موقعیت مکانی را فعال کنید. در غیر این صورت، مجوز را درخواست کنید:
private void enableMyLocation() {
   if (ContextCompat.checkSelfPermission(this,
           Manifest.permission.ACCESS_FINE_LOCATION)
           == PackageManager.PERMISSION_GRANTED) {
       mMap.setMyLocationEnabled(true);
   } else {
       ActivityCompat.requestPermissions(this, new String[]
                       {Manifest.permission.ACCESS_FINE_LOCATION},
               REQUEST_LOCATION_PERMISSION);
   }
}
  1. برای فعال کردن لایه موقعیت مکانی، تابع enableMyLocation() را از تابع onMapReady() فراخوانی کنید.
  2. متد onRequestPermissionsResult() را بازنویسی کنید. اگر مجوز اعطا شد، enableMyLocation() را فراخوانی کنید:
@Override
public void onRequestPermissionsResult(int requestCode,
       @NonNull String[] permissions,
       @NonNull int[] grantResults) {
   // Check if location permissions are granted and if so enable the
   // location data layer.
   switch (requestCode) {
       case REQUEST_LOCATION_PERMISSION:
           if (grantResults.length > 0
                   && grantResults[0]
                   == PackageManager.PERMISSION_GRANTED) {
               enableMyLocation();
               break;
           }
   }
}
  1. برنامه را اجرا کنید. گوشه بالا سمت راست اکنون شامل دکمه «موقعیت مکانی من » است که مکان فعلی دستگاه را نمایش می‌دهد.

۴.۲ فعال کردن نمای خیابان

نقشه‌های گوگل، نمای خیابان (Street View) را ارائه می‌دهند که یک نمای پانوراما از یک مکان با کنترل‌هایی برای پیمایش در امتداد یک مسیر مشخص است. نمای خیابان پوشش جهانی ندارد .

در این مرحله، شما یک پانورامای نمای خیابان را فعال می‌کنید که وقتی کاربر روی پنجره اطلاعات یک POI ضربه می‌زند، فعال می‌شود. شما باید دو کار انجام دهید:

  1. نشانگرهای POI را از سایر نشانگرها متمایز کنید، زیرا می‌خواهید عملکرد برنامه شما فقط روی نشانگرهای POI کار کند. به این ترتیب، می‌توانید نمای خیابان را زمانی که کاربر روی پنجره اطلاعات POI ضربه می‌زند، شروع کنید، اما نه زمانی که کاربر روی هر نوع نشانگر دیگری ضربه می‌زند.

کلاس Marker شامل یک متد setTag() است که به شما امکان می‌دهد داده‌ها را پیوست کنید. (داده‌ها می‌توانند هر چیزی باشند که از Object امتداد می‌یابند). شما یک برچسب روی نشانگرهایی که هنگام کلیک کاربران روی POIها ایجاد می‌شوند، تنظیم خواهید کرد.

  1. وقتی کاربر روی یک پنجره اطلاعات برچسب‌گذاری شده در OnInfoWindowClickListener ضربه می‌زند، MapFragment با StreetViewPanoramaFragment جایگزین کنید. (کد زیر SupportMapFragment و SupportStreetViewPanoramaFragment برای پشتیبانی از نسخه‌های اندروید پایین‌تر از API 12 استفاده می‌کند.)

اگر هر یک از قطعات در زمان اجرا تغییر کنند، باید آنها را در کلاس Activity حاوی آن اضافه کنید، و نه به صورت ایستا در XML.

نشانگر POI را برچسب گذاری کنید

  1. در تابع فراخوانی onPoiClick() ، تابع setTag() را روی poiMarker فراخوانی کنید. هر رشته دلخواهی را به آن ارسال کنید:
poiMarker.setTag("poi");

جایگزین کردن SupportMapFragment استاتیک با یک نمونه‌ی زمان اجرا

  1. activity_maps.xml را باز کنید و طرح‌بندی عنصر را به یک قاب تغییر دهید که به عنوان ظرفی برای قطعات شما عمل کند:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/fragment_container"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
  1. در onCreate() در MapsActivity ، کدی که SupportMapFragment بر اساس شناسه پیدا می‌کند، حذف کنید، زیرا دیگر SupportMapFragment استاتیک در XML وجود ندارد. در عوض، با فراخوانی SupportMapFragment.newInstance() ، یک نمونه زمان اجرای جدید از SupportMapFragment ایجاد کنید:
SupportMapFragment mapFragment = SupportMapFragment.newInstance();
  1. با استفاده از یک تراکنش fragment با FragmentManager ، قطعه کد را به FrameLayout اضافه کنید:
getSupportFragmentManager().beginTransaction()
       .add(R.id.fragment_container, mapFragment).commit();
  1. خط کدی که بارگذاری ناهمگام نقشه را آغاز می‌کند، دست‌نخورده باقی می‌ماند:
mapFragment.getMapAsync(this);

یک OnInfoWindowClickListener تنظیم کنید و تگ marker را بررسی کنید.

  1. یک متد stub در MapsActivity به نام setInfoWindowClickToPanorama() ایجاد کنید که یک GoogleMap به عنوان آرگومان دریافت کرده و void را برمی‌گرداند:
private void setInfoWindowClickToPanorama(GoogleMap map) {}
  1. یک OnInfoWindowClickListener برای GoogleMap تنظیم کنید:
map.setOnInfoWindowClickListener(
       new GoogleMap.OnInfoWindowClickListener() {
           @Override
           public void onInfoWindowClick(Marker marker) {
           }
       });
  1. در متد onInfoWindowClick() ، بررسی کنید که آیا نشانگر حاوی برچسب رشته‌ای است که شما در متد onPoiClick() تنظیم کرده‌اید یا خیر:
if (marker.getTag() == "poi") {}

SupportMapFragment را با SupportStreetViewPanoramaFragment جایگزین کنید.

  1. در صورتی که نشانگر حاوی تگ باشد، با استفاده از شیء StreetViewPanoramaOptions مکان پانورامای نمای خیابان را مشخص کنید. ویژگی position شیء را روی موقعیت نشانگر وارد شده تنظیم کنید:
StreetViewPanoramaOptions options =
       new StreetViewPanoramaOptions().position(
               marker.getPosition());
  1. یک نمونه جدید از SupportStreetViewPanoramaFragment ایجاد کنید و شیء options که ایجاد کرده‌اید را به آن ارسال کنید:
SupportStreetViewPanoramaFragment streetViewFragment
       = SupportStreetViewPanoramaFragment
       .newInstance(options);
  1. یک تراکنش fragment را شروع کنید. محتویات کانتینر fragment را با fragment جدید، streetViewFragment ، جایگزین کنید. تراکنش را به پشته اضافه کنید، به طوری که با فشردن دکمه back به SupportMapFragment برگردید و از برنامه خارج نشوید:
getSupportFragmentManager().beginTransaction()
       .replace(R.id.fragment_container,
               streetViewFragment)
       .addToBackStack(null).commit();
  1. بعد از فراخوانی تابع setPoiClick()، تابع setInfoWindowClickToPanorama(mMap) را در onMapReady() فراخوانی کنید setPoiClick().
  2. برنامه را اجرا کنید. روی شهری که پوشش نمای خیابان دارد، مانند مانتین ویو (محل استقرار دفتر مرکزی گوگل)، زوم کنید و یک نقطه مورد نظر (POI)، مانند یک پارک، پیدا کنید. برای قرار دادن یک نشانگر و نمایش پنجره اطلاعات، روی POI ضربه بزنید. برای ورود به حالت نمای خیابان برای مکان نشانگر، روی پنجره اطلاعات ضربه بزنید. برای بازگشت به بخش نقشه، دکمه بازگشت را فشار دهید.

نمای خیابان گوگل در یک برنامه اندروید

۷. کد راه‌حل

کد حل Wander .

۸. چالش کدنویسی

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

  • برای بررسی اینکه آیا نمای خیابان در یک منطقه در دسترس است یا خیر، تابع فراخوانی OnStreetViewPanomaraReady را در ترکیب با StreetViewPanorama.OnStreetViewPanoramaChangeListener پیاده‌سازی کنید.
  • اگر نمای خیابان در یک منطقه انتخاب‌شده در دسترس نیست، به قطعه نقشه برگردید و خطایی را نشان دهید.

۹. خلاصه

  • برای استفاده از API نقشه‌ها، به یک کلید API از کنسول API گوگل نیاز دارید.
  • در اندروید استودیو، استفاده از الگوی Activity نقشه‌های گوگل، یک Activity با یک SupportMapFragment واحد در طرح‌بندی برنامه ایجاد می‌کند. این الگو همچنین ACCESS_FINE_PERMISSION را به مانیفست برنامه اضافه می‌کند، OnMapReadyCallback را در فعالیت شما پیاده‌سازی می‌کند و متد onMapReady() مورد نیاز را نادیده می‌گیرد.

برای تغییر نوع نقشه‌ی GoogleMap در زمان اجرا، از متد GoogleMap.setMapType() استفاده کنید. یک نقشه‌ی گوگل می‌تواند یکی از انواع نقشه‌های زیر باشد:

  • عادی : نقشه راه‌های معمولی. جاده‌ها، برخی از عوارض ساخته شده توسط انسان و عوارض طبیعی مهم مانند رودخانه‌ها را نشان می‌دهد. برچسب‌های جاده‌ها و عوارض نیز قابل مشاهده هستند.
  • ترکیبی : داده‌های عکس ماهواره‌ای به همراه نقشه‌های جاده‌ای اضافه شده است. برچسب‌های جاده و عوارض نیز قابل مشاهده هستند.
  • ماهواره : داده‌های عکس. برچسب‌های جاده و عوارض قابل مشاهده نیستند.
  • عوارض زمین : داده‌های توپوگرافی. نقشه شامل رنگ‌ها، خطوط تراز و برچسب‌ها و سایه‌های پرسپکتیو است. برخی از جاده‌ها و برچسب‌ها نیز قابل مشاهده هستند.
  • هیچکدام **:** نقشه‌ای وجود ندارد.

درباره نقشه‌های گوگل:

  • نشانگر، نشانه‌ای برای یک موقعیت جغرافیایی خاص است.
  • وقتی روی نشانگر ضربه زده می‌شود، رفتار پیش‌فرض آن نمایش یک پنجره اطلاعات با اطلاعاتی درباره مکان است.
  • به طور پیش‌فرض، نقاط مورد علاقه (POI) به همراه آیکون‌های مربوطه‌شان روی نقشه پایه ظاهر می‌شوند. POIها شامل پارک‌ها، مدارس، ساختمان‌های دولتی و موارد دیگر می‌شوند.
  • علاوه بر این، نقاط مورد علاقه تجاری (مغازه‌ها، رستوران‌ها، هتل‌ها و موارد دیگر) به طور پیش‌فرض روی نقشه ظاهر می‌شوند، زمانی که نوع نقشه normal باشد.
  • شما می‌توانید با استفاده از OnPoiClickListener کلیک‌های روی POIها را ثبت کنید.
  • شما می‌توانید ظاهر بصری تقریباً تمام عناصر یک نقشه گوگل را با استفاده از Styling Wizard تغییر دهید. Styling Wizard یک فایل JSON تولید می‌کند که شما آن را با استفاده از متد setMapStyle() به نقشه گوگل ارسال می‌کنید.
  • شما می‌توانید نشانگرهای خود را با تغییر رنگ پیش‌فرض یا جایگزینی آیکون نشانگر پیش‌فرض با یک تصویر سفارشی، سفارشی کنید.

سایر اطلاعات مهم:

  • از یک پوشش زمینی برای تثبیت تصویر بر روی یک موقعیت جغرافیایی استفاده کنید.
  • از شیء GroundOverlayOptions برای مشخص کردن تصویر، اندازه تصویر بر حسب متر و موقعیت تصویر استفاده کنید. این شیء را به متد GoogleMap.addGroundOverlay() ارسال کنید تا همپوشانی روی نقشه تنظیم شود.
  • مشروط بر اینکه برنامه شما مجوز ACCESS_FINE_LOCATION را داشته باشد، می‌توانید ردیابی موقعیت مکانی را با استفاده از متد mMap.setMyLocationEnabled(true) فعال کنید.
  • گوگل استریت ویو (Google Street View) نمای پانورامای ۳۶۰ درجه از جاده‌های تعیین‌شده در سراسر منطقه تحت پوشش خود ارائه می‌دهد.
  • از متد StreetViewPanoramaFragment.newInstance() برای ایجاد یک قطعه جدید نمای خیابان استفاده کنید.
  • برای مشخص کردن گزینه‌های مربوط به نما، از شیء StreetViewPanoramaOptions استفاده کنید. شیء را به متد newInstance() ارسال کنید.

۱۰. بیشتر بدانید

مستندات مفهومی مرتبط در نسخه ۹.۱: Google Maps API آمده است.

مستندات توسعه‌دهندگان اندروید:

مستندات مرجع:

۱۱. تکالیف

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

  • در صورت لزوم، تکالیف منزل را تعیین کنید.
  • نحوه ارائه تکالیف را به دانش آموزان اطلاع دهید.
  • تکالیف را نمره دهید.

مربیان می‌توانند از این پیشنهادات به میزان کم یا زیاد استفاده کنند و باید در تعیین تکالیف دیگری که مناسب می‌دانند، آزاد باشند.

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

ساخت و اجرای یک برنامه

  1. یک برنامه جدید ایجاد کنید که از الگوی فعالیت نقشه‌های گوگل (Google Maps Activity) استفاده کند، که هنگام راه‌اندازی برنامه، نقشه‌های گوگل را بارگذاری می‌کند.
  2. وقتی نقشه گوگل بارگذاری شد، دوربین را به محل مدرسه، محل خانه یا هر مکان دیگری که برایتان معنی‌دار است، منتقل کنید.
  3. دو علامت به نقشه اضافه کنید، یکی در محل مدرسه‌تان و یکی در خانه‌تان یا هر مکان معنادار دیگری.
  4. با تغییر رنگ پیش‌فرض یا جایگزینی آیکون نشانگر پیش‌فرض با یک تصویر سفارشی، آیکون‌های نشانگر را سفارشی کنید.

نکته: به مستندات onMapReady (GoogleMap googleMap) مراجعه کنید.

به این سوالات پاسخ دهید

سوال ۱

کدام متد هنگام بارگذاری نقشه و آماده شدن برای استفاده در برنامه فراخوانی می‌شود؟

سوال ۲

از کدام کامپوننت‌های اندروید می‌توانید برای گنجاندن نقشه‌های گوگل در برنامه خود استفاده کنید؟

  • MapView و MapFragment
  • MapFragment و MapActivity
  • MapView و MapActivity
  • فقط MapFragment

سوال ۳

API اندروید نقشه‌های گوگل چه نوع نقشه‌هایی ارائه می‌دهد؟

  • معمولی، ترکیبی، زمینی، ماهواره‌ای و نقشه راه
  • معمولی، هیبریدی، زمینی، ماهواره‌ای و «هیچکدام»
  • ترکیبی، زمینی، ماهواره‌ای، نقشه راه و «هیچکدام»
  • عادی، زمین، ماهواره، نقشه تصویر و «هیچکدام»

سوال ۴

برای افزودن قابلیت کلیک به یک نقطه مورد نظر (POI)، چه رابطی را پیاده‌سازی می‌کنید؟

  • GoogleMap.OnPoiListener
  • GoogleMap.OnPoiClickListener
  • GoogleMap.OnPoiClick
  • GoogleMap.OnPoiClicked

برنامه خود را برای رتبه بندی ارسال کنید

راهنمایی برای کلاسداران

بررسی کنید که آیا برنامه دارای ویژگی‌های زیر است:

  • وقتی برنامه اجرا می‌شود، نقشه گوگل به درستی نمایش داده می‌شود که نشان می‌دهد کلید API به درستی ایجاد شده است.
  • پس از بارگذاری نقشه گوگل، دوربین به محل خانه یا مدرسه دانش‌آموز منتقل می‌شود. در کد، این مرحله باید در متد فراخوانی onMapReady (GoogleMap googleMap) اتفاق بیفتد.
  • نشانگرها در محل مدرسه دانش‌آموز و مکان دیگری مانند خانه دانش‌آموز نمایش داده می‌شوند.
  • این دو نشانگر سفارشی‌سازی شده‌اند. برای مثال، نشانگرها از رنگی غیر از رنگ قرمز پیش‌فرض استفاده می‌کنند یا از یک آیکون سفارشی بهره می‌برند.

۱۲. آزمایشگاه کد بعدی

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