1. 程式人生 > >Android 百度地圖開發--- 導航功能輸入起始地址實現導航,地址解析與反解析的使用

Android 百度地圖開發--- 導航功能輸入起始地址實現導航,地址解析與反解析的使用

本人主要介紹安卓開發使用百度地圖實現導航功能,使用者可以輸入當前位置和目的地,實現導航。

首先,我們需要當用戶輸入具體接到地址後將具體街道的地址轉化為經度和緯度,然後實現定位,因此,首先來講解一下地址解析,百度地圖API提供Geocode類進行地址解析,我們可以通過Geocoder.getPoint()方法將一段地址描述轉化為一個座標(經度和緯度)具體程式碼如下

/**
		 * 一下程式碼通過具體地址獲取經度緯度
		 * 起點地址獲得經度緯度
		 * 暫時這樣寫,具體應用時在封裝整理
		 */
		Geocoder gc = new Geocoder(RouteGuideDemo.this,Locale.CHINA);
	      List
addressList = null; try { addressList = gc.getFromLocationName(star_add, 1); if (!addressList.isEmpty()) { Address address_temp = addressList.get(0); //計算經緯度 double Latitude=address_temp.getLatitude(); //獲得緯度 double Longitude=address_temp.getLongitude(); //獲得經度 Star_Latitude=Latitude; Star_Longitude=Longitude; } }catch (IOException e) { e.printStackTrace(); }


當然大家在寫程式碼的時候記得匯入相應的包,使用eclipse開發的話,直接Ctrl+Shift+O組合快捷鍵自動匯入當前頁面所需要的所有包名,也刪除所有不需要的包名,非常方便。還有一點,記得在libs檔案下匯入百度地圖的SDK,去官網下載,這裡不詳細介紹了

上一步我們可以獲得輸入地址的經度緯度了,接下來我們直接使用如下程式碼實現呼叫

BaiduNaviManager.getInstance().launchNavigator(this,
				40.05087, 116.30142,"百度大廈", //起點緯度、經度、中文地址
		        39.90882, 116.39750,"北京天安門",//終點緯度、經度、中文地址
				NE_RoutePlan_Mode.ROUTE_PLAN_MOD_MIN_TIME, 		 //算路方式
				true, 									   		 //真實導航
				BaiduNaviManager.STRATEGY_FORCE_ONLINE_PRIORITY, //在離線策略
				new OnStartNavigationListener() {				 //跳轉監聽
					
					@Override
					public void onJumpToNavigator(Bundle configParams) {
						Intent intent = new Intent(RouteGuideDemo.this, BNavigatorActivity.class);
						intent.putExtras(configParams);
				        startActivity(intent);
					}
					
					@Override
					public void onJumpToDownloader() {
					}
				});

核心程式碼就這兩步就可以實現導航功能了,接下展示一個Demo,具體來看看完整的實現過程

首先佈局檔案:

具體實現功能程式碼

<span style="font-family:Microsoft YaHei;font-size:14px;">package com.baidu.navi.sdkdemo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.content.Intent;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.baidu.mapapi.search.MKSearch;
import com.baidu.navisdk.BNaviPoint;
import com.baidu.navisdk.BaiduNaviManager;
import com.baidu.navisdk.BaiduNaviManager.OnStartNavigationListener;
import com.baidu.navisdk.comapi.routeplan.RoutePlanParams.NE_RoutePlan_Mode;


/**
 * GPS導航Demo
 */
public class RouteGuideDemo extends Activity{
//    private BNaviPoint mStartPoint = new BNaviPoint(116.30142, 40.05087,
//            "百度大廈", BNaviPoint.CoordinateType.GCJ02);
    private BNaviPoint mStartPoint = new BNaviPoint(117.150419, 39.111972,
            "電子科技中心", BNaviPoint.CoordinateType.GCJ02);
    private BNaviPoint mEndPoint = new BNaviPoint(116.39750, 39.90882,
            "北京天安門", BNaviPoint.CoordinateType.GCJ02);
    private List<BNaviPoint> mViaPoints = new ArrayList<BNaviPoint>();
    private Button mBtnAddViaPoint;
    
    
    
    //初始化引數,預設起點為小蜜蜂公司,終點為北京天安門
    private double Star_Latitude=39.111972; //起點緯度
    private double Star_Longitude=117.150419;	//起點經度
    
    private double end_Latitude=39.90882; //終點緯度
    private double end_Longitude=116.39750;	//終點經度
    
    private MKSearch mMKSearch;     //定義搜尋服務類
    
    private EditText star_cityEditText;
    private EditText star_keyWordEditText;
    private EditText end_cityEditText;
    private EditText end_keyWordEditText;
    
    
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.activity_routeguide);
		Button btnStartNavigation = (Button)findViewById(R.id.button_navigation);

		//例項化輸入框
		star_cityEditText=(EditText)findViewById(R.id.edt_star_city);
		star_keyWordEditText=(EditText)findViewById(R.id.edt_star_keyWord);
		end_cityEditText=(EditText)findViewById(R.id.edt_end_city);
		end_keyWordEditText=(EditText)findViewById(R.id.edt_end_keyWord);

		btnStartNavigation.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
			    if (mViaPoints.size() == 0) {
			        launchNavigator();
			    } else {
			        launchNavigatorViaPoints();
			    }
			}
		});
		
		findViewById(R.id.start_nav2_btn).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                if (mViaPoints.size() == 0) {
                    launchNavigator2();
                } else {
                    launchNavigatorViaPoints();
                }
            }
        });
		
		mBtnAddViaPoint = (Button) findViewById(R.id.add_via_btn); 
		mBtnAddViaPoint.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View arg0) {
                    addViaPoint();
                }
            });
	}

    private void addViaPoint() {
        EditText viaXEditText = (EditText) findViewById(R.id.et_via_x);
        EditText viaYEditText = (EditText) findViewById(R.id.et_via_y);
        double latitude = 0, longitude = 0;
        try {
            latitude = Integer.parseInt(viaXEditText.getText().toString());
            longitude = Integer.parseInt(viaYEditText.getText().toString());
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        // 預設座標系為GCJ
        BNaviPoint viaPoint = new BNaviPoint(longitude/1e5, latitude/1e5,
                "途經點" + (mViaPoints.size()+1));
        mViaPoints.add(viaPoint);
        Toast.makeText(this, "已新增途經點:" + viaPoint.getName(),
                Toast.LENGTH_SHORT).show();
        if (mViaPoints.size() >= 3) {
            mBtnAddViaPoint.setEnabled(false);
        }
    }

	/**
	 * 啟動GPS導航. 前置條件:導航引擎初始化成功
	 */
	private void launchNavigator(){
		//起點
		String star_add=star_cityEditText.getText().toString().trim();
		star_add=star_add+star_keyWordEditText.getText().toString().trim();
		//終點
		String end_add=end_cityEditText.getText().toString().trim();
		end_add=end_add+end_keyWordEditText.getText().toString().trim();

		/**
		 * 一下程式碼通過具體地址獲取經度緯度
		 * 起點地址獲得經度緯度
		 * 暫時這樣寫,具體應用時在封裝整理
		 */
		Geocoder gc = new Geocoder(RouteGuideDemo.this,Locale.CHINA);
	      List<Address> addressList = null;
	    try {
	    addressList = gc.getFromLocationName(star_add, 1);
	        if (!addressList.isEmpty()) {
        		Address address_temp = addressList.get(0);
	      		//計算經緯度
	      		double Latitude=address_temp.getLatitude(); //獲得緯度
	      		double Longitude=address_temp.getLongitude();	//獲得經度
	      		Star_Latitude=Latitude;
	      		Star_Longitude=Longitude;
	        }
	    }catch (IOException e) {
  	      e.printStackTrace();
  	    }
	    
	    /**
		 * 一下程式碼通過具體地址獲取經度緯度
		 * 終點地址獲得經度緯度
		 * 暫時這樣寫,具體應用時在封裝整理
		 * 
		 */
		Geocoder gc2 = new Geocoder(RouteGuideDemo.this,Locale.CHINA);
	      List<Address> addressList2 = null;
	    try {
	    addressList2 = gc.getFromLocationName(end_add, 1);
	        if (!addressList2.isEmpty()) {
        		Address address_temp2 = addressList2.get(0);
	      		//計算經緯度
	      		double Latitude=address_temp2.getLatitude(); //獲得緯度
	      		double Longitude=address_temp2.getLongitude();	//獲得經度
	      		end_Latitude=Latitude;
	      		end_Longitude=Longitude;
	        }
	    }catch (IOException e) {
  	      e.printStackTrace();
  	    }
		
	    
		BaiduNaviManager.getInstance().launchNavigator(this,
//				40.05087, 116.30142,"百度大廈", 
//				39.111972,117.150419, "天津電子科技中心",
				Star_Latitude,Star_Longitude,star_add,	//起點緯度、經度、中文地址
				end_Latitude,end_Longitude,end_add,		//終點緯度、經度、中文地址
//		        39.90882, 116.39750,"北京天安門",
				NE_RoutePlan_Mode.ROUTE_PLAN_MOD_MIN_TIME, 		 //算路方式
				true, 									   		 //真實導航
				BaiduNaviManager.STRATEGY_FORCE_ONLINE_PRIORITY, //在離線策略
				new OnStartNavigationListener() {				 //跳轉監聽
					
					@Override
					public void onJumpToNavigator(Bundle configParams) {
						Intent intent = new Intent(RouteGuideDemo.this, BNavigatorActivity.class);
						intent.putExtras(configParams);
				        startActivity(intent);
					}
					
					@Override
					public void onJumpToDownloader() {
					}
				});
	}
	
    /**
     * 指定導航起終點啟動GPS導航.起終點可為多種型別座標系的地理座標。
     * 前置條件:導航引擎初始化成功
     */
    private void launchNavigator2(){
        //這裡給出一個起終點示例,實際應用中可以通過POI檢索、外部POI來源等方式獲取起終點座標
        BNaviPoint startPoint = new BNaviPoint(116.307854,40.055878,
                "百度大廈", BNaviPoint.CoordinateType.BD09_MC);
        BNaviPoint endPoint = new BNaviPoint(116.403875,39.915168,
                "北京天安門", BNaviPoint.CoordinateType.BD09_MC);
        BaiduNaviManager.getInstance().launchNavigator(this,
                startPoint,                                      //起點(可指定座標系)
                endPoint,                                        //終點(可指定座標系)
                NE_RoutePlan_Mode.ROUTE_PLAN_MOD_MIN_TIME,       //算路方式
                true,                                            //真實導航
                BaiduNaviManager.STRATEGY_FORCE_ONLINE_PRIORITY, //在離線策略
                new OnStartNavigationListener() {                //跳轉監聽
                    
                    @Override
                    public void onJumpToNavigator(Bundle configParams) {
                        Intent intent = new Intent(RouteGuideDemo.this, BNavigatorActivity.class);
                        intent.putExtras(configParams);
                        startActivity(intent);
                    }
                    
                    @Override
                    public void onJumpToDownloader() {
                    }
                });
    }

    /**
     * 增加一個或多個途經點,啟動GPS導航. 
     * 前置條件:導航引擎初始化成功
     */
    private void launchNavigatorViaPoints(){
        //這裡給出一個起終點示例,實際應用中可以通過POI檢索、外部POI來源等方式獲取起終點座標
//        BNaviPoint startPoint = new BNaviPoint(113.97348, 22.53951, "白石洲");
//        BNaviPoint endPoint   = new BNaviPoint(113.92576, 22.48876, "蛇口");
//        BNaviPoint viaPoint1 = new BNaviPoint(113.94104, 22.54343, "國人通訊大廈");
//        BNaviPoint viaPoint2 = new BNaviPoint(113.94863, 22.53873, "中國銀行科技園支行");
        List<BNaviPoint> points = new ArrayList<BNaviPoint>();
        points.add(mStartPoint);
        points.addAll(mViaPoints);
        points.add(mEndPoint);
        BaiduNaviManager.getInstance().launchNavigator(this,
                points,                                          //路線點列表
                NE_RoutePlan_Mode.ROUTE_PLAN_MOD_MIN_TIME,       //算路方式
                true,                                            //真實導航
                BaiduNaviManager.STRATEGY_FORCE_ONLINE_PRIORITY, //在離線策略
                new OnStartNavigationListener() {                //跳轉監聽
                    
                    @Override
                    public void onJumpToNavigator(Bundle configParams) {
                        Intent intent = new Intent(RouteGuideDemo.this, BNavigatorActivity.class);
                        intent.putExtras(configParams);
                        startActivity(intent);
                    }
                    
                    @Override
                    public void onJumpToDownloader() {
                    }
                });
    }
    
}</span>


接下來看看效果圖了

首頁:GPS導航和路線規劃

  

                                    首頁                                                                                                             導航頁面


模擬器上執行效果如上,還自帶語音播報導航功能。真實手機上效果會好很多,和百度地圖客戶端沒什麼區別


好了,實現之後再看看百度地圖的定位原理吧

定位原理

使用百度Android定位SDK必須註冊GPS和網路使用許可權。定位SDK採用GPS、基站、Wi-Fi訊號進行定位。當應用程式向定位SDK發起定位請求時,定位SDK會根據應用的定位因素(GPS、基站、Wi-Fi訊號)的實際情況(如是否開啟GPS、是否連線網路、是否有訊號等)來生成相應定位依據進行定位。
使用者可以設定滿足自身需求的定位依據:
若使用者設定GPS優先,則優先使用GPS進行定位,如果GPS定位未開啟或者沒有可用位置資訊,且網路連線正常,定位SDK則會返回網路定位(即Wi-Fi與基站)的最優結果。為了使獲得的網路定位結果更加精確,請開啟手機的Wi-Fi開關。


定位精度



在使用百度定位SDKv4.0之前,我們要下載最新的庫檔案,下載地址:點選下載相關庫檔案,將liblocSDK4.so檔案拷貝到libs/armeabi目錄下。將locSDK4.0.jar檔案拷貝到工程的libs目錄下