آموزش های این وب سایت به صورت رایگان در دسترس است. اطلاعات بیشتر
بروز خطا
   [message]
اشتراک در سوال
رای ها
[dataList]

مسیریابی بر روی نقشه گوگل از داخل اپلیکیشن + سورس (آموزش)

کاشی زاده  11 سال پیش  8 سال پیش
+70 0

خُب من خیلی دنبال این قضیه بودم و برام خیلی مهم بود ، بعد از چند وقت روش این کار رو پیدا کردم .

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

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


 

اول از همه یه اکتیویتی میسازید به اسم NavigationActivity و از FragmentActivity اکستندز میکنید .

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

یه دکمه برای مسیر یابی میسازید و برای متد onClick رو Override میکنید.

داخل متد کلیک از این کد استفاده کنید :

findDirections( TEHRAN.latitude, TEHRAN.longitude,MASHAD.latitude, MASHAD.longitude, GMapV2Direction.MODE_DRIVING );

فقط یه توضیح میدم ما مختصات تهران و مشهد رو به صورت فیلدی از جنس LatLng (موقعیت جغرافی) در میاریم به شکل زیر :

 private static final LatLng TEHRAN = new LatLng(35.7014396, 51.3498186);
 private static final LatLng MASHAD = new LatLng(36.3164008, 59.5493205);

خب متد findDirections :

 public void findDirections(double fromPositionDoubleLat, double fromPositionDoubleLong,
double toPositionDoubleLat, double toPositionDoubleLong, String mode) { Map<String, String> map = new HashMap<String, String>(); map.put(GetDirectionsAsyncTask.USER_CURRENT_LAT, String.valueOf(fromPositionDoubleLat)); map.put(GetDirectionsAsyncTask.USER_CURRENT_LONG, String.valueOf(fromPositionDoubleLong)); map.put(GetDirectionsAsyncTask.DESTINATION_LAT, String.valueOf(toPositionDoubleLat)); map.put(GetDirectionsAsyncTask.DESTINATION_LONG, String.valueOf(toPositionDoubleLong)); map.put(GetDirectionsAsyncTask.DIRECTIONS_MODE, mode); GetDirectionsAsyncTask asyncTask = new GetDirectionsAsyncTask(this); asyncTask.execute(map); }

از HashMap استفاده میکنیم که قبلا در آموزش های استاد توضیحاتش داده شده و مقادیری که در کلاس AsyncTask که بعدا میسازیم وجود داره رو داخل این HashMap ذخیره میکنیم.

و در آخر هم کلاس GetDirectionsAsyncTask  رو اجرا میکنیم .

یک کلاس جدید میسازیم به نام GetDirectionsAsyncTask  و از AsyncTask اکستندز میکنیم .

داخلش فیلد های زیر رو میسازیم :

 public static final String USER_CURRENT_LAT = "user_current_lat";
 public static final String USER_CURRENT_LONG = "user_current_long";
 public static final String DESTINATION_LAT = "destination_lat";
 public static final String DESTINATION_LONG = "destination_long";
 public static final String DIRECTIONS_MODE = "directions_mode";

این فیلد ها همونطور که از اسمشون مشخصه مربوط به موقعیت کاربر و تنظیمات مسیریابی هستند که باهاشون بعدا آشنا میشید .

داخل این کلاس ما چند فیلد دیگه هم معرفی میکنیم :

  private NavigationActivity activity;
  private Exception exception;
  private ProgressDialog progressDialog;

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

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

 public GetDirectionsAsyncTask(NavigationActivity activity)
    {
        super();
        this.activity = activity;
    }

در متد onPreExecute دیالاگ رو به کاربر نشون میدیم توجه داشته باشید این متد داخل کلاس مین ترد اجرا میشه .

  public void onPreExecute()
    {
        progressDialog = new ProgressDialog(activity);
        progressDialog.setMessage("Calculating directions");
        progressDialog.show();
    }

داخل متد onPostExecute  دیالاگ رو در صورتی که خطایی وجود نداشته باشه میبندیم و متدی رو که در اصلی یا همون 

NavigationActivity هست رو صدا میزنیم . 

توضیحات متد handleGetDirectionsResult رو بعدا میدم، الان فقط در همین حد بدونید که یک متدی با این نام داخل اکتیویتیNavigationActivity وجود داره.

نکته ای که اینجا هست متد onPostExecute  هم داخل ترد مین اجرا میشه .

  public void onPostExecute(ArrayList result)
    {
        progressDialog.dismiss();
        if (exception == null)
        {
            activity.handleGetDirectionsResult(result);
        }
        else
        {
            processException();
        }
    }

میریم سراغ متد doInBackground ، توجه داشته باشید که این متد داخل ترد مین صدا زده نمیشه و ما نمیتونیم در UI اعمال تغییرات کنیم .

 

 protected ArrayList<LatLng> doInBackground(Map<String, String>... params)
    {
        Map<String, String> paramMap = params[0];
        try
        {
            LatLng fromPosition = new LatLng(Double.valueOf(paramMap.get(USER_CURRENT_LAT))
, Double.valueOf(paramMap.get(USER_CURRENT_LONG))); LatLng toPosition = new LatLng(Double.valueOf(paramMap.get(DESTINATION_LAT)) ,
Double.valueOf(paramMap.get(DESTINATION_LONG))); GMapV2Direction md = new GMapV2Direction(); Document doc = md.getDocument(fromPosition, toPosition, paramMap.get(DIRECTIONS_MODE)); ArrayList<LatLng> directionPoints = md.getDirection(doc); return directionPoints; } catch (Exception e) { exception = e; return null; } }

داخل این متد ما مختصاتی که قبلا براش در یک HashMap ذخیره کردیم رو فراخونی میکنیم و داخل یک متغیر از جنس LatLng (موقعیت جغرافیایی) میریزیم .

حالا اینجا یک کلاس جدید داریم به اسم GMapV2Direction که بهتون میگم این کلاس چیه در واقع.

غیر از این کلاس ما بایک کلاس جدید از کتابخانه اندروید آشنا میشیم به اسم Document که در واقع این کلاس برای نمایش xml , html به کار میره . توضیحات بیشتر رو میتونید در مستندات گوگل بخونید : لینک

 

 

کلاس GMapV2Direction  همه این داسان زیر سر این کلاس هست و نکات خیلی ریزی هم داره که نمیشه همش رو توضیح بدم یکم روش کار کنید متوجه میشید .

داخل این کلاس ما 2 فیلد تعریف میکنیم برای مشخص کردن نوع حرکت که پیاده هستید یا با ماشین :

  public final static String MODE_DRIVING = "driving";
  public final static String MODE_WALKING = "walking";

متدی داریم با نام getDocument  که کارش گرفتن اطلاعات مسیریابی از سرور گوگل هست . 

کد زیر کاملا واضح هست و توضیحی نداره ، اطلاعات بیشتر در مورد کلاس های لایبری اندروید و متد هاشون  میتونید در اسناد گوگل پیدا کنید .

  public Document getDocument(LatLng start, LatLng end, String mode) {
        String url = "http://maps.googleapis.com/maps/api/directions/xml?" 
                + "origin=" + start.latitude + "," + start.longitude  
                + "&destination=" + end.latitude + "," + end.longitude 
                + "&sensor=false&units=metric&mode=driving";

        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpContext localContext = new BasicHttpContext();
            HttpPost httpPost = new HttpPost(url);
            HttpResponse response = httpClient.execute(httpPost, localContext);
            InputStream in = response.getEntity().getContent();
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = builder.parse(in);
            return doc;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

خوب حالا متدی داریم شامل این دستورات :

 public ArrayList<LatLng> getDirection (Document doc) {
        NodeList nl1, nl2, nl3;
        ArrayList<LatLng> listGeopoints = new ArrayList<LatLng>();
        nl1 = doc.getElementsByTagName("step");
        if (nl1.getLength() > 0) {
            for (int i = 0; i < nl1.getLength(); i++) {
                Node node1 = nl1.item(i);
                nl2 = node1.getChildNodes();

                Node locationNode = nl2.item(getNodeIndex(nl2, "start_location"));
                nl3 = locationNode.getChildNodes();
                Node latNode = nl3.item(getNodeIndex(nl3, "lat"));
                double lat = Double.parseDouble(latNode.getTextContent());
                Node lngNode = nl3.item(getNodeIndex(nl3, "lng"));
                double lng = Double.parseDouble(lngNode.getTextContent());
                listGeopoints.add(new LatLng(lat, lng));

                locationNode = nl2.item(getNodeIndex(nl2, "polyline"));
                nl3 = locationNode.getChildNodes();
                latNode = nl3.item(getNodeIndex(nl3, "points"));
                ArrayList<LatLng> arr = decodePoly(latNode.getTextContent());
                for(int j = 0 ; j < arr.size() ; j++) {
                    listGeopoints.add(new LatLng(arr.get(j).latitude, arr.get(j).longitude));
                }

                locationNode = nl2.item(getNodeIndex(nl2, "end_location"));
                nl3 = locationNode.getChildNodes();
                latNode = nl3.item(getNodeIndex(nl3, "lat"));
                lat = Double.parseDouble(latNode.getTextContent());
                lngNode = nl3.item(getNodeIndex(nl3, "lng"));
                lng = Double.parseDouble(lngNode.getTextContent());
                listGeopoints.add(new LatLng(lat, lng));
            }
        }

        return listGeopoints;
    }

توضیحات این متد یکم زیاده خودتون مطالعه کنید فقط در این حد بهتون بگم که این متد مجموعه ای از موقعیت های جغرافیایی یا Geopoint رو به ما میده .

من روی این قسمت زیاد توضیح نمیدوم داخل کد خودتون بررسی کنید قسمت های که نوشته شده مربوط به الگوریتم های مسیریابی هست .

برمیگردیم سراغ متد handleGetDirectionsResult که داخل اکتیویتی اصلی ما قرار داره (NavigationActivity)  که کدش به صورت زیر هست :

 public void handleGetDirectionsResult(ArrayList<LatLng> directionPoints) {
		PolylineOptions rectLine = new PolylineOptions().width(5).color(Color.RED);

		for(int i = 0 ; i < directionPoints.size() ; i++) 
		{          
			rectLine.add(directionPoints.get(i));
		}
		if (newPolyline != null)
		{
			newPolyline.remove();
		}
		newPolyline = map.addPolyline(rectLine);
		latlngBounds = createLatLngBoundsObject(TEHRAN, MASHAD);
	        map.animateCamera(CameraUpdateFactory.newLatLngBounds(latlngBounds,
width, height, 150)); }

این متد هم مسیر های که بدست آورده رو روی نقشه رسم میکنه .

 

یکم سخت و پیچیده هست و شما با استفاده از این پروژه میتونید برای خودتون یک اپلیکیشن حرفه ای برای مسیریابی بسازید.

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

 

متاسفانه سورس اصلاح شده توسط در دسترس نیست

از این لینک میتونید سورس رو دریافت کنید

 

موفق و سربلند باشید :)

0 0
ممنون داداش دمت گرم (11 سال پیش)
0 0
سورس رو تو اکلیپس امپورت کردم خطای زیر رو بهم میده..ممنون میشم راهنمایم کنید : [2014-09-30 2208 - NavigationApplication] Unable to resolve target 'Google Inc.:Google APIs (x86 System Image):19' (11 سال پیش)
+2 0
من در پروژه از google Api 19 استفاده کردم شما هم این Api رو دانلود کنید مشکل حل میشه (11 سال پیش)
0 0
تو این لینک استاد یه سری فایل واسه جنی موشن واسه دانلود گذاشتن که واسه هر یه api داره از همونا دانلود کنم حل میشه؟! (11 سال پیش)
+2 0
اره از همون استفاده کنید و در قسمت تنظیمات و منی فست کتابخانه خودتون رو اضافی کنید (11 سال پیش)
0 0
من یه سوال دارم ربطی هم به اینجا نداره اما دیگه میپرسم genymotion شما هم به sdcard دسترسی نداره ؟ (11 سال پیش)
+1 0
به sd card دسترسی داره و میتونید فایل هارو ازش خارج کنید ولی به data/data دسترسی نداره (11 سال پیش)
0 0
ببخشید اینو میگم پررو پررو ، امکان دانلود سرس کد نیست ، میشه یه چک بکنی ؟ شاید مشکل از سمته منه . (11 سال پیش)
+1 0
شرمنده رفتم دیدم نیستش فایل تو سرور گشتم پیدا نکردم آخه یکم خونه تکونی داشتیمم تو ویندوز پیدا کردم برات میذارم (11 سال پیش)
+1 0
این لینک سورس پروژه هست اما کدی که محمد حسین گذاشته کامل تر و شسته رفته تره (11 سال پیش)
+1 0
کد اصلی رو میشه بزارید من خیلی نیاز دارم البته اگه پیدا شده باشه (11 سال پیش)
+2 0
لینکی که سپهر گذاشته همون سورس اصلی هست من فقط توش بعضی از مشکلات و چیزای اضافیش رو حل و حذف کرده بودم . (11 سال پیش)
+1 0
در متد ArrayList getDirection خطای The method getTextContent() is undefined for the type Node رو میده! (11 سال پیش)
+1 0
برای اینکه بخواهیم وقتی مسیر یابی کرد فاصله و زمان بین دو مکان را بدست بیاوریم چه کار باید کرد؟! (11 سال پیش)
+1 0
برای محاسبه فاصله بین دونقطه یک فرمول ریاضی داره که باید برید و سرچ کنید در استک وجود داره . زمان هم باید بررسی کنید سرعت اون فرد چقدر هست و مسافت رو تقسیم بر سرعت کنید . (11 سال پیش)
0 0
سلام سورسش کجاست !؟ (11 سال پیش)
0 0
سلام آقای کاشی زاده میشه لطف کنید بگید چجوری میشه بخشی از نقشه رو جهت مشاهده آفلاین روی حافظه گوشی ذخیره کرد؟ (9 سال پیش)
+1 0
خود Google Map اتوماتیک این کارو انجام میده و هر قسمتی که یکبار لود بشه به صورت آفلاین هم قابل مشاهده است . (9 سال پیش)
0 0
ممنون یه سوال دیگه اینکه بعضی نرم افزار ها قابلیت دانلود یه شهر خاص یا یه کشور خاص رو میزارن میشه بگید اون چطوریه؟ممنون (9 سال پیش)
0 0
اطلاعی ندارم باید برید API گوگل رو مطالعه کنید ببنید چه ویژگی هایی داره . (9 سال پیش)
0 0
The method getTextContent() is undefined for the type Node سلام اگر میشه بگید که این خطا رو چطور برطرف کنم؟ (8 سال پیش)
 برای این سوال پاسخی وجود ندارد.

پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .