برمجة الأندرويد

Google Maps بالعربية – الدرس الثالث

[mhc_section admin_label=”section”][mhc_row admin_label=”row”][mhc_column type=”1_4″][mhc_image admin_label=”صورة” src=”http://hendiware.16mb.com/wp-content/uploads/2016/08/gm.png” show_in_lightbox=”off” url_new_window=”off” animation=”off” hoverfx=”none” sticky=”off” image_mask=”off” border_radius=”0″ align=”right” force_center_on_mobile=”on” saved_tabs=”all”] [/mhc_image][mhc_text admin_label=”نص” shared_module=”8537″ saved_tabs=”all” background_layout=”light” text_orientation=”right”]
الدرس الأول

ابدأ مع Google Map

الدرس الثانى

انواع الخرائط والـ Gestures والـ Markers

الدرس الثالث

الموقع الحالى وتحديد الإتجاهات


اذا واجهتك أى مشكلة

قم بطرحها فى جروب

Hendiware Developers

[/mhc_text][/mhc_column][mhc_column type=”3_4″][mhc_post_header admin_label=”عنوان المقالة” title=”on” meta=”off” avatar=”on” author=”on” date=”on” categories=”on” comments=”off” views=”off” text_orientation=”right” text_color=”dark” featured_image=”on” featured_placement=”above” parallax=”on” parallax_method=”off” animation=”off” custom_paddings=”40″ size=”30px” title_bold=”on” text_shadow=”off” text_background=”off” text_bg_color=”#ffffff” overlay=”on” saved_tabs=”all”] [/mhc_post_header][mhc_text admin_label=”نص” background_layout=”light” text_orientation=”right”]

فى الدرس السابق Google Maps بالعربية – الدرس الثانى تحدثنا عن انواع الخرائط وكذلك كيفية الاستجابة للضغطات على الخريطة بالاضافة لكيفية اضافة Marker على الخريطة يمكنك اضافة دوائر او مضلعات او ايقونات  لكن لن نتطرق الى ذلك الان وسنتحدث عن موضوعين مهمين جدا فى استخدام الخرائط وهما تحديد الموقع الحالى للمستخدم وكذلك تحديد الإتجاهات على الخريطة .

 

تحديد الموقع الحالى 

يمكنك تحديد الموقع  الحالى للمستخدم عن طريق ما يعرف بالـ Last Know Location وهو عباره عن اخر موقع معروف للمستخدم والذى فى اغلب الاحيان هو الموقع الحالى لكن قبل أن تقوم ببدء التكويد للحصول على الموقع الحالى مباشرة يجب التحقق من أمرين أولا : صلاحيات الوصول لموقع المستخدم خصوصا لأجهزة مارشميلو عن طريق عمل Request Permission  لصلاحيات الـ Location  فى الـ Runtime حيث يعد الـ Location من الصلاحيات الخطيرة ويمكنك مراجعة تدوينة الصلاحيات فى أندرويد مارشميلو لمعرفة تفاصيل أكثر عن كيفية طلب الصلاحيات حيث لن اقوم باعادة شرحها هنا لكن سأضع الكود مباشرة اثناء الشرح  ،

ثانيا : التأكد من الـ Location او GPS مفعل حاليا من قبل المستخدم ويمكنك استخدام هذا الكود اختصارا للوقت

   LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            Toast.makeText(this, "GPS is Enabled in your device", Toast.LENGTH_SHORT).show();
        }else{
            showGPSDisabledAlertToUser();
        }

والميثود showGPSDisabledAlertToUser محتواها كالاتى :

private void showGPSDisabledAlertToUser(){
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setMessage("GPS is disabled in your device. Would you like to enable it?")
                .setCancelable(false)
                .setPositiveButton("Goto Settings Page To Enable GPS",
                        new DialogInterface.OnClickListener(){
                            public void onClick(DialogInterface dialog, int id){
                                Intent callGPSSettingIntent = new Intent(
                                        android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                startActivity(callGPSSettingIntent);
                            }
                        });
        alertDialogBuilder.setNegativeButton("Cancel",
                new DialogInterface.OnClickListener(){
                    public void onClick(DialogInterface dialog, int id){
                        dialog.cancel();
                    }
                });
        AlertDialog alert = alertDialogBuilder.create();
        alert.show();
    }

 

وهذا الكود ببساطة يقوم بانشاء Reference من الـ location manager ثم يقوم بفحص اذا ما كان ال gps مفعلا ام لا اذا كان مفعل اظهر toast انه مفعل واذا كان غير مفعل قم باظهار Dialog توضيحية للمستخدم  تظهر بها رسالة توضيحية للمستخدم ان ال gps غير مفعل هل تريد تفعيله وزر يذهب مباشرة للاعدادات الخاصة بالLocation لكى يقوم المستخدم بالتفعيل وبالتالى يمكن للتطبيق الخاص بنا تحديد موقعه .

 

نبدأ الان بكتابة كود تحديد الموقع

أولا سنقوم بإنشاء GoogleAPIClient حيث اننا فى تحديدنا للموقع نعتمد على ال Google API وتحديدا FusedLocationApi سنقوم بذلك كالاتى :

ببساطة قمنا ببناء GoogleApiClient واضفنا له الـ ConnectionCallbacks اى ماذا سيحدث عند الاتصال عند انقطاع الاتصال وهكذا واعطينا this لاننا سنقوم بعمل implement بعد قليل مثلما فعلنا مع ال map سابقا لو تذكر وكذلك الـ listener الخاص بفشل الاتصال اعطيناه this بالاضافة الى اضافة API الـ LocationService

الان سنقوم بعمل implement لـ ConnectionCallbacks و OnConnectionFailedListener حيث اننا اشرنا اليهم اثناء بناء ال googleApiClient بـ this وسيتم ذلك كالتالى :

وطبعا الخط الأحمر هذا يشير الى انه هناك بعض الـ methods التى يجب علينا عمل override لها  سنضغط alt+ enter ونختار

وستجد انه تم اضافة الـ Methods للأكتيتفى

الميثود onConnect يتم تنفيذها بعد الاتصال بالـ Google Api مباشرة و onConnectionSuspended تستدعى عندما يتم ايقاف الاتصال والـ onConnectionFailed تستدعى فى حالة فشل الاتصال حتى يتاح لك عمل handel لكل الحالات المختلفة .

 

الان كل شىء يبدو جيدا وينقص شىء واحد فقط يجب أن نقوم يدويا بعمل connect لل google api client وكذلك يدويا بعمل disconnect لايقاف الاتصال وسنقوم بذلك فى الميثود onStart() والميثود onStop() كاالتالى :

 

الان يمكننا استخدام الـ googleClientApi للحصول على الموقع الحالى وسنقوم بذلك بداخل ميثود onConnect والتى تستدعى بعد اتمام الاتصال ب googleAPI بنجاح وبالتالى يكون الـ client الخاص بنا جاهز

عن طريق استخدام الميثود getLastLocation والتى تأخذ Google Api Client كباراميتر نقوم بالحصول على الـ Location وكما تلاحظ الان الخط الأحمر بالكود وهو للتنبيه بأننا لم نقم بعمل طلب صلاحيات للمارشميلو وهذا الكود يستلزم تصريح احد الصلاحيات الخطيرة فى الأندرويد لذلك سأقوم بإضافة كود الـ Permissions كالتالى :

نقوم الان بتشغيل التطبيق والتجربة وان قمت بالتجربة على المارشميلو سيطلب الصلاحيات وافق عليها ثم شاهد الـ Logcat

سنقوم بفعل شىء افضل من ذلك وهو ان نضع بالونة على الموقع الحالى للمستخدم هل تتذكر كيفية اضافة Marker فى الدرس السابق ؟

 

وبعد التشغيل ستجد أنه قام بعرض الموقع الحالى لك  وتحريك الكاميرا نحوه

 

 

 

الكود الكامل للأكتيتيفى الان :

package com.hendiware.myfirstmap;

import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AlertDialog;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private GoogleMap mMap;
    private GoogleApiClient googleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
         SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);

        mapFragment.getMapAsync(this);

        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Toast.makeText(this, "GPS is Enabled in your devide", Toast.LENGTH_SHORT).show();
        } else {
            showGPSDisabledAlertToUser();
        }


        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

    }

    @Override
    protected void onStart() {
        googleApiClient.connect();
        super.onStart();
    }


    @Override
    protected void onStop() {
        googleApiClient.disconnect();
        super.onStop();
    }

 
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
                    android.Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        } else {
            Location userCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
            if (userCurrentLocation != null) {
                MarkerOptions currentUserLocation = new MarkerOptions();
                LatLng currentUserLatLang = new LatLng(userCurrentLocation.getLatitude(), userCurrentLocation.getLongitude());
                currentUserLocation.position(currentUserLatLang);
                mMap.addMarker(currentUserLocation);
                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentUserLatLang, 16));

            }
        }

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            onConnected(null);
        } else {
            Toast.makeText(MapsActivity.this, "No Permitions Granted", Toast.LENGTH_SHORT).show();
        }
    }


    private void showGPSDisabledAlertToUser() {
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setMessage("GPS is disabled in your device. Would you like to enable it?")
                .setCancelable(false)
                .setPositiveButton("Goto Settings Page To Enable GPS",
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                Intent callGPSSettingIntent = new Intent(
                                        android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                startActivity(callGPSSettingIntent);
                            }
                        });
        alertDialogBuilder.setNegativeButton("Cancel",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                    }
                });
        AlertDialog alert = alertDialogBuilder.create();
        alert.show();
    }

}

 

 

تحديد الإتجاهات من مكان لأخر 

توفر لنا جوجل من ضمن مجموعة الـ APIs الخاصة بالخرائط الـ Direction API وهو الذى يوفر لنا خدمة تحديد الاتجاهات ورسمها على الخريطة وما يتعلق بذلك من امور

تتيح لك الخدمة معرفة الاتجاهات بين مكانين معينين عن طريق Http Request  تعطيه الباراميترز الازمة وتحصل على الـنتيجة كـ json وهى الطريقة العادية  بالاضافة للطريقة العادية توفر جوجل  مكتبات كـ Client Side أحدها  للجافا والتى بنى عليها عدة مكتبات أندرويد تسهل عليك موضوع تحديد الإتجاهات من أشهرهم مكتبة akexorcist/Android-GoogleDirectionLibrary  والتى تمكنك من التعامل مع الـ Direction API بسهولة سنقوم الان باضافتها لملف الجرادل

 compile 'com.akexorcist:googledirectionlibrary:1.0.4'

وقبل أن نبدأ بكتابة اى كود سنقوم الان بالذهاب للـ Google Console لتفعيل وتمكين استخدام  الـ Direction API

 

وبعد ذلك نقوم بعمل Enable والان تصبح جاهزا ننتقل للأندرويد

كما بالمثال الموضح لاستخدام المكتبة فهى تستخدم كالتالى :

نقوم بكتابة GoogleDirection اسم الكلاس الخاص بالمكتبة ثم الميثود withServerKey نعطيها الـ API Key الخاص بنا الذى حصلنا عليه فى الدرس الاول ثم الميثود from وهو المكان الذى سيتم تحديد الاتجاهات منه على شكل LatLang (خطوط الطول والعرض) يليها الميثود to وتأخذ باراميتر LatLang ايضا بمكان الوجهه او المكان الذى سيتم تحديد الاتجاهات ليه ثم بعد ذلك الميثود execute الخاصة بالتنفيذ وتأخذ باراميتر الـ CallBack الخاص بنتائج الاتصال هل هو ناجح أم فاشل واذا نجح الاتصال هل فشل جلب الاتجاهات ام نجح نقوم الان بتشغيل التطبيق ومشاهدة النتيجة

وستجد انه تم الوصول للاتجاهات بنجاح

ويعنى أنه تم تحديد الاتجاهات بنجاح  بين المكانين وطبعا أنت لا تحدد الاتجاهات فقط لمجرد تحديد الاتجاهات بل لتقوم بامر اخر والذى يكون فى اغلب الاحيان رسم خط على الخريطة يوضح هذه الاتجاهات

تأتى نتيجة الاتصال السابق على هيئة List تحتوى على Route أو اكثر حيث أحيانا يكون هناك عدة طرق للوصول لمكان اخر من هذا المكان

يحتوى الـ Route على Leg أو أكثر  وهو المسافه بين مكان واخر ويحتوى الـ Leg على step وهى المسافة بين مكان واخر داخل نفس الـ Leg لذلك نستدعى ذلك من النتيجة ونقوم بناءا عليه بإنشاء Polyline ونرسمه على الخريطة بناءا على بيانات الاتجاهات الى حصلنا عليها كما يتضح من الكود التالى

 

قمنا بجلب الـ Leg  ثم استخدمنا الميثود getDirectionPoint والتى تعطى لنا امكانية الحصول على الاتجاهاات على هيئة مصفوفة من خطوط الطول والعرض المتتالية ثم قمنا باستخدام الميثود createPolyline الموجودة بكلاس DirectionCoverter والتى أخذت منا باراميترات (الكونتكست ، ليست الاتجاهات ، سمك الخط ، اللون )
ثم قمنا باضافة هذا الـ polyline للخريطة .

 

وتكون النتيجة ظهور رسم الاتجاه على الخريطة كالتالى :

 

 

[/mhc_text][/mhc_column][/mhc_row][/mhc_section]
السابق
Google Maps بالعربية – الدرس الثانى
التالي
درس مكتبة EventBus : الإتصال بين مكونات التطبيق بسهولة

تعليق واحد

أضف تعليقا

  1. Tasneem قال:

    مرحبا كيفكم انا متابعتكم من غزة وباحب اشكركم على الجهد الرائع وباتمنى تستمروا في تقديم الشروحات
    وحابة اطلب منكم طلب ازا ممكن
    يا ريت لو تعملوا شرح كامل ومفصل عن الدفع الالكتروني لانو هي الاشي يلي ناقص ما حكيتوا عنه ومحتاجاه ضروري جدا الفترة الحالية
    وشكرا جزيلا لكم

اترك تعليقاً

This site uses Akismet to reduce spam. Learn how your comment data is processed.