簡單的路線規(guī)劃demo

前言

這個騰訊地圖的demo可以做到:1.定位位置2.規(guī)劃起點和終點的路線3.顯示規(guī)劃路線距離以及計算路費4.動畫模擬小車在規(guī)劃路線上的平滑移動啸驯。

實現(xiàn)步驟

先看下實現(xiàn)效果:
image

新建個Android項目并新建個Activity,命名為DrivingRouteActivity祟峦,先來畫一下UI布局罚斗,布局比較簡單,由一個騰訊SDK包下的地圖組件MapView宅楞,以及兩個用于輸入起始位置的輸入框针姿,兩個確認路線規(guī)劃的Button,一個定位當前位置的ImageView厌衙,一個用于顯示行程信息的TextView組成距淫,布局代碼只是為了方便展示實現(xiàn)功能,所以下面直接貼出布局代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".activity.DrivingRouteActivity">
 
    <com.tencent.tencentmap.mapsdk.maps.MapView
        android:id="@+id/mapview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:gravity="bottom"
        android:paddingTop="10dp">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <EditText
                android:id="@+id/from_et"
                android:hint="您在哪兒上車"
                android:layout_weight="1"
                android:layout_marginTop="10dp"
                android:layout_marginBottom="10dp"
                android:layout_marginLeft="10dp"
                android:layout_width="match_parent"
                android:layout_height="50dp"></EditText>
            <ImageButton
                android:id="@+id/location_ib"
                android:background="@drawable/sendtocar_balloon"
                android:layout_marginTop="10dp"
                android:layout_marginBottom="10dp"
                android:layout_marginRight="10dp"
                android:layout_width="50dp"
                android:layout_height="50dp"></ImageButton>
        </LinearLayout>
        <EditText
            android:id="@+id/to_et"
            android:hint="您要去哪兒"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"></EditText>
        <TextView
            android:id="@+id/orderdesc_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:textSize="20sp"></TextView>
        <Button
            android:id="@+id/confirm_btn"
            android:text="確定"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:visibility="gone"></Button>
        <Button
            android:id="@+id/order_btn"
            android:text="預(yù)約快車"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginBottom="10dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"></Button>
    </LinearLayout>
 
</LinearLayout>

1.賬號注冊與配置

在開發(fā)之前婶希,我們需要到騰訊位置服務(wù)官網(wǎng)注冊一個賬號


image

注冊后進入控制臺


image
選擇key管理榕暇,點擊創(chuàng)建新秘鑰,按照申請信息提交申請

將上面申請的key在application標簽下進行如下配置(value替換成自己的key)

<meta-data
    android:name="TencentMapSDK"
    android:value="XXXXX-XXXXX-XXXXX-XXXXX-XXXXX-XXXXX" />
image

2.引入騰訊Android地圖SDK

進入Android地圖SDK喻杈,下載3D版地圖SDK壓縮包


image

下載完成后打開壓縮包彤枢,將libs文件夾下的jar包拷貝到app的libs目錄下,右鍵該jar包選擇add as library添加為依賴奕塑,并且在項目app\src\main路徑下建立名為jniLibs的目錄堂污,把壓縮包libs/jniLibs/strip文件夾下的所有包放到j(luò)niLibs目錄下


image
引入后在AndroidManifest.xml文件下配置相關(guān)權(quán)限
<!-- 訪問網(wǎng)絡(luò)獲取地圖服務(wù) -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 檢查網(wǎng)絡(luò)可用性 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 訪問WiFi狀態(tài) -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 需要外部存儲寫權(quán)限用于保存地圖緩存 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 獲取 device id 辨別設(shè)備 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

3.地圖初始化

配置完成,現(xiàn)在開始實現(xiàn)我們的邏輯交互龄砰,為了讓實現(xiàn)邏輯更加清晰,我將業(yè)務(wù)邏輯代碼與視圖渲染代碼分到了兩個包中讨衣,除了activity包中的DrivingRouteActivity之外换棚,新建了一個present包,并在包下建立一個DrivingRoutePresent類反镇,分別由DrivingRouteActivity負責對UI組件進行視圖渲染固蚤,由DrivingRoutePresent類負責業(yè)務(wù)邏輯。這里我還新建了一個contract包歹茶,并創(chuàng)建一個DrivingRouteContract接口,通過這個接口定義的方法燎孟,實現(xiàn)DrivingRoutePresent與DrivingRouteActivity之間的交互尸昧。我們在DrivingRouteContract接口中定義兩個接口揩页,一個View接口供DrivingRouteActivity實現(xiàn)烹俗,一個Presenter接口供DrivingRoutePresent實現(xiàn)萍程,并定義一些初始化的方法

public interface DrivingRouteContract {
    
    interface View{
        void initView();//初始化View
        void initOnClick();//初始化OnClickListener
        void setOrderDescTV(String content);//渲染訂單行程信息
        EditText getFromET();
    }
 
    interface Presenter{
        void attachView(DrivingRouteContract.View view);//綁定View
    }
}

接著再讓DrivingRouteActivity實現(xiàn)DrivingRouteContract.View接口并聲明UI中的組件進行初始化

public class DrivingRouteActivity extends Activity implements DrivingRouteContract.View, View.OnClickListener {
    private MapView mapView;
    private TencentMap mMap;
    private Button confirmBtn;
    private Button orderBtn;
    private ImageButton locationIB;
    private EditText fromET;
    private EditText toET;
    private TextView orderDescTV;
   private DrivingRoutePresent drivingRoutePresent;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_driving_route);
        initView();
        initOnClick();
    }
 
    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.order_btn:
                //實現(xiàn)行程路線規(guī)劃
                break;
            case R.id.confirm_btn:
                //開啟動畫移動
                break;
            case R.id.location_ib:
                //定位當前位置
                break;
        }
    }
 
    /**
     * mapview的生命周期管理
     */
    @Override
    protected void onStart() {
        super.onStart();
        mapView.onStart();
    }
 
    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }
 
    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }
 
    @Override
    protected void onStop() {
        super.onStop();
        mapView.onStop();
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }
 
    @Override
    protected void onRestart() {
        super.onRestart();
        mapView.onRestart();
    }
 
    @Override
    public void initView() {
        mapView = findViewById(R.id.mapview);
        confirmBtn = findViewById(R.id.confirm_btn);
        orderBtn = findViewById(R.id.order_btn);
        locationIB = findViewById(R.id.location_ib);
        fromET = findViewById(R.id.from_et);
        toET = findViewById(R.id.to_et);
        orderDescTV = findViewById(R.id.orderdesc_tv);
        mMap = mapView.getMap();
 
        drivingRoutePresent = new DrivingRoutePresent();
        drivingRoutePresent.attachView(this);
    }
 
    @Override
    public void initOnClick() {
        orderBtn.setOnClickListener(this);
        confirmBtn.setOnClickListener(this);
        locationIB.setOnClickListener(this);
    }
    
    @Override
    public void setOrderDescTV(String content) {
        orderDescTV.setText(content);
    }
 
    @Override
    public EditText getFromET() {
        return fromET;
    }
}

DrivingRoutePresent實現(xiàn)DrivingRouteContract.Presenter接口

public class DrivingRoutePresent implements DrivingRouteContract.Presenter {
    
    private DrivingRouteContract.View drinvingRouteView;
    
    @Override
    public void attachView(DrivingRouteContract.View view) {
        drinvingRouteView = view;
    }
}

因為我們后面在多個地方都需要用到當前應(yīng)用的上下文,為了方便兔仰,需要再編寫一個全局的應(yīng)用上下文工具類來幫助我們獲取上下文乎赴,建立一個util包并創(chuàng)建一個GlobalApplication類

public class GlobalApplication extends Application {
 
    private static Context context;
 
    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }
 
    public static Context getContext(){
        return context;
    }
}

同時,在Android類文件的application標簽中加入下面屬性缔赠,讓應(yīng)用啟動時加載上面的GlobalApplication

android:name=".util.GlobalApplication"

到這里友题,我們就完成了界面與業(yè)務(wù)代碼的基本設(shè)計,運行app踢匣,可以看到顯示的基本地圖信息戈抄。接下來我們來實現(xiàn)一下路線規(guī)劃的功能。騰訊官方Android地圖SDK開發(fā)文檔對路線規(guī)劃服務(wù)和地址解析都有較詳細的說明输莺。
另外還提供了調(diào)用示例Demo裸诽。如果不清楚如何調(diào)用的話可以參考官方Demo或參考下面代碼。

4.地址解析與路線規(guī)劃

首先我們在DrivingRouteContract.Presenter接口申明一個用于通過地址查找經(jīng)緯度的geocoder方法和一個用于路線規(guī)劃的routePlan方法

public interface DrivingRouteContract {
    
    interface View{
        void initView();//初始化View
        void initOnClick();//初始化OnClickListener
        void setOrderDescTV(String content);//渲染訂單行程信息
        EditText getFromET();
    }
 
    interface Presenter{
        void attachView(DrivingRouteContract.View view);//綁定View
        void geocoder(String address, Integer type);//地址解碼嘱函,轉(zhuǎn)經(jīng)緯度
        void routePlan();//實現(xiàn)路線規(guī)劃
    }
}

通過騰訊Android地圖SDK路線規(guī)劃服務(wù)的開發(fā)文檔往弓,我們了解到要獲得規(guī)劃路線需要先獲取起點和終點的經(jīng)緯度蓄氧,而在一般業(yè)務(wù)場景中,我們幾乎不會讓用戶手動輸入經(jīng)緯度缴淋,所以我這里還需要用到地址解析服務(wù),通過輸入中文地址來獲取經(jīng)緯度露氮,再通過經(jīng)緯度規(guī)劃路線(不過在實際業(yè)務(wù)中最好是加上關(guān)鍵詞輸入提示這個服務(wù)钟沛,方便用戶找到輸入的位置)。

在DrivingRoutePresent類中實現(xiàn)這兩個方法

public static final Integer FROM_TYPE = 0x100; //獲取起始位置坐標
public static final Integer TO_TYPE = 0x101; //獲取目的位置坐標
private LatLng fromLatLng;
private LatLng toLatLng;
 
/**
 * 地址解碼
 * @param address 傳入需要解碼的地址
 * @param type 地址類型叁扫,起始位置畜埋、目的位置
 */
@Override
public void geocoder(String address, final Integer type) {
    TencentSearch tencentSearch = new TencentSearch(GlobalApplication.getContext());
    Address2GeoParam address2GeoParam =
            new Address2GeoParam(address);
    tencentSearch.address2geo(address2GeoParam, new HttpResponseListener<BaseObject>() {
 
        @Override
        public void onSuccess(int arg0, BaseObject arg1) {
            if (arg1 == null) {
                return;
            }
            Address2GeoResultObject obj = (Address2GeoResultObject)arg1;
            if (obj.result.latLng != null) {
                if (type==FROM_TYPE)
                    fromLatLng = obj.result.latLng;
                else if (type==TO_TYPE)
                    toLatLng = obj.result.latLng;
                routePlan();
            }
        }
 
        @Override
        public void onFailure(int arg0, String arg1, Throwable arg2) {
            Log.e("test", "error code:" + arg0 + ", msg:" + arg1);
        }
    });
}
 
private TencentSearch tencentSearch = new TencentSearch(GlobalApplication.getContext());
private StringBuffer lineStringBuilder = new StringBuffer();//路線坐標
private Double taxiFare = 0d;//預(yù)估打車費用
private Float distance = 0f;//預(yù)計全程里程
 
/**
 * 路線規(guī)劃
 */
@Override
public void routePlan() {
    if (fromLatLng!=null&&toLatLng!=null){
        Toast.makeText(GlobalApplication.getContext(), "正在為您規(guī)劃路線", Toast.LENGTH_SHORT).show();
        DrivingParam drivingParam = new DrivingParam(fromLatLng, toLatLng);
        drivingParam.policy(DrivingParam.Policy.TRIP);//駕車路線規(guī)劃策略悠鞍,網(wǎng)約車場景,送乘客
        drivingParam.setCarNumber("粵A00001");//填入車牌號掩宜,在路線規(guī)劃時會避讓車牌限行區(qū)域
        tencentSearch.getRoutePlan(drivingParam, new HttpResponseListener<DrivingResultObject>() {
 
            @Override
            public void onSuccess(int i, DrivingResultObject drivingResultObject) {
                for (DrivingResultObject.Route route : drivingResultObject.result.routes){
                    for (LatLng latLng : route.polyline){
                        lineStringBuilder.append(latLng.latitude + "," + latLng.longitude);
                        lineStringBuilder.append(",");
                    }
                    distance += route.distance;
                    taxiFare += route.taxi_fare.fare;
                }
                drinvingRouteView.setOrderDescTV("行程大約" + distance + "m,預(yù)計¥" + taxiFare + "元");
 
                //清空行程路線么翰,里程,費用信息
                lineStringBuilder = new StringBuffer();
                distance = 0f;
                taxiFare = 0d;
            }
 
            @Override
            public void onFailure(int i, String s, Throwable throwable) {
                Log.d("DrivingRouteActivity", "onSuccess: " + s + i);
            }
        });
 
        fromLatLng=null;
        toLatLng=null;
    }
}

其中g(shù)eocoder方法用于獲得我們輸入的起始位置(從哪兒上車)檐迟,以及輸入的目的位置(到哪兒下車)的坐標經(jīng)緯度,記錄位置的經(jīng)緯度后調(diào)用routePlan方法請求路線規(guī)劃接口扫尖,并記錄下里程,費用信息桦沉,路線行駛過程中經(jīng)過的點的經(jīng)緯度(用于后面實現(xiàn)小車移動)金闽。

路線規(guī)劃接口除了上面使用的幾個常用參數(shù)外代芜,還有很多接口參數(shù),具體可以查看官方接口文檔按需要加入

參考官方接口文檔:https://lbs.qq.com/AndroidDocs/doc_3d/index.html

5.車輛行駛動畫

有了路線規(guī)劃方法后钞速,給"預(yù)約快車"按鈕添加實現(xiàn)

@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.order_btn:
            drivingRoutePresent.geocoder(fromET.getText().toString(), DrivingRoutePresent.FROM_TYPE);
            drivingRoutePresent.geocoder(toET.getText().toString(), DrivingRoutePresent.TO_TYPE);
            confirmBtn.setVisibility(View.VISIBLE);
            orderBtn.setVisibility(View.GONE);
            break;
        case R.id.confirm_btn:
            //開啟動畫移動
            break;
        case R.id.location_ib:
            //定位當前位置
            break;
    }
}

此時,運行APP渴语,輸入起點和終點就可以獲得駕車的規(guī)劃路線了

接下來驾凶,我們再實現(xiàn)一下效果圖上小車根據(jù)規(guī)劃路線行駛的功能

在DrivingRouteContract.View接口中加入小車動畫初始化方法initAnimation

public interface DrivingRouteContract {
 
    interface Model{
    }
 
    interface View{
        void initView();//初始化View
        void initOnClick();//初始化OnClickListener
        void setOrderDescTV(String content);//渲染訂單行程信息
        EditText getFromET();
        void initAnimation(String line);//初始化小車移動動畫
    }
 
    interface Presenter{
        void attachView(DrivingRouteContract.View view);//綁定View
        void startLocation(boolean single);
        void stopLocation();
        void geocoder(String address, Integer type);//地址解碼,轉(zhuǎn)經(jīng)緯度
        void routePlan();//實現(xiàn)路線規(guī)劃
    }
}

實現(xiàn)initAnimation方法窟哺,關(guān)于Marker其他參數(shù)同樣參考上面的接口文檔

private Marker mCarMarker;
private LatLng[] mCarLatLngArray;
private MarkerTranslateAnimator mAnimator;
 
@Override
public void initAnimation(String line) {
    //拆分獲得經(jīng)緯度數(shù)組
    String[] linePointsStr = line.split(",");
    mCarLatLngArray = new LatLng[linePointsStr.length / 2];
    for (int i = 0; i < mCarLatLngArray.length; i++) {
        double latitude = Double.parseDouble(linePointsStr[i * 2]);
        double longitude = Double.parseDouble(linePointsStr[i * 2 + 1]);
        mCarLatLngArray[i] = new LatLng(latitude, longitude);
    }
 
    //添加小車路線
    mMap.addPolyline(new PolylineOptions().add(mCarLatLngArray)
        .color(R.color.colorLine));//這個顏色是colors.xml中自定義的顏色
 
    //添加小車
    LatLng carLatLng = mCarLatLngArray[0];
    mCarMarker = mMap.addMarker(
            new MarkerOptions(carLatLng)
                    .anchor(0.5f, 0.5f)
                    .icon(BitmapDescriptorFactory.fromResource(R.mipmap.taxi_t))//小車圖標
                    .flat(true)
                    .clockwise(false));
 
    //創(chuàng)建移動動畫
    mAnimator = new MarkerTranslateAnimator(mCarMarker, 50 * 1000, mCarLatLngArray, true);
 
    //調(diào)整最佳視野
    mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(
            LatLngBounds.builder().include(Arrays.asList(mCarLatLngArray)).build(), 50));
}

并在routePlan方法中調(diào)用這個方法且轨,傳入行駛路線字符串

//初始化小車動畫
drinvingRouteView.initAnimation(lineStringBuilder.substring(0, lineStringBuilder.length()-1));

完整代碼參考

/**
 * 路線規(guī)劃
 */
@Override
public void routePlan() {
    if (fromLatLng!=null&&toLatLng!=null){
        Toast.makeText(GlobalApplication.getContext(), "正在為您規(guī)劃路線", Toast.LENGTH_SHORT).show();
        DrivingParam drivingParam = new DrivingParam(fromLatLng, toLatLng);
        drivingParam.policy(DrivingParam.Policy.TRIP);//駕車路線規(guī)劃策略亩鬼,網(wǎng)約車場景,送乘客
        drivingParam.setCarNumber("粵A00001");//填入車牌號黄绩,在路線規(guī)劃時會避讓車牌限行區(qū)域
        tencentSearch.getRoutePlan(drivingParam, new HttpResponseListener<DrivingResultObject>() {
 
            @Override
            public void onSuccess(int i, DrivingResultObject drivingResultObject) {
                for (DrivingResultObject.Route route : drivingResultObject.result.routes){
                    for (LatLng latLng : route.polyline){
                        lineStringBuilder.append(latLng.latitude + "," + latLng.longitude);
                        lineStringBuilder.append(",");
                    }
                    distance += route.distance;
                    taxiFare += route.taxi_fare.fare;
                }
                //初始化小車動畫
                drinvingRouteView.initAnimation(lineStringBuilder.substring(0, lineStringBuilder.length()-1));
                drinvingRouteView.setOrderDescTV("行程大約" + distance + "m,預(yù)計¥" + taxiFare + "元");
 
                //清空行程路線爽丹,里程辛蚊,費用信息
                lineStringBuilder = new StringBuffer();
                distance = 0f;
                taxiFare = 0d;
            }
 
            @Override
            public void onFailure(int i, String s, Throwable throwable) {
                Log.d("DrivingRouteActivity", "onSuccess: " + s + i);
            }
        });
 
        fromLatLng=null;
        toLatLng=null;
    }
}

最后我們在"確定"按鈕的點擊事件上調(diào)用MarkerTranslateAnimator的startAnimation方法來開始動畫

@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.order_btn:
            drivingRoutePresent.geocoder(fromET.getText().toString(), DrivingRoutePresent.FROM_TYPE);
            drivingRoutePresent.geocoder(toET.getText().toString(), DrivingRoutePresent.TO_TYPE);
            confirmBtn.setVisibility(View.VISIBLE);
            orderBtn.setVisibility(View.GONE);
            break;
        case R.id.confirm_btn:
            //開啟動畫移動
            mAnimator.startAnimation();
            orderBtn.setVisibility(View.VISIBLE);
            confirmBtn.setVisibility(View.GONE);
            break;
        case R.id.location_ib:
            //定位當前位置
            break;
    }
}

6.引入騰訊Android定位SDK

基本效果已經(jīng)完成了袋马,現(xiàn)在還差最后一個定位功能,要實現(xiàn)定位功能需要引入另一個SDK(Android定位SDK)

我們打開Android定位SDK開發(fā)文檔碑宴,下載最新的SDK


image

將壓縮包內(nèi)的jar包放入app的libs包下延柠,并添加為依賴


image
再把壓縮包libs文件夾下的各個so文件拷貝到項目jniLibs的對應(yīng)目錄中
image
image

打開AndroidManifest.xml文件贞间,加入下面權(quán)限配置

<!-- 通過GPS得到精確位置 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 通過網(wǎng)絡(luò)得到粗略位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 訪問網(wǎng)絡(luò). 某些位置信息需要從網(wǎng)絡(luò)服務(wù)器獲取 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 訪問WiFi狀態(tài). 需要WiFi信息用于網(wǎng)絡(luò)定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 修改WiFi狀態(tài). 發(fā)起WiFi掃描, 需要WiFi信息用于網(wǎng)絡(luò)定位 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 訪問網(wǎng)絡(luò)狀態(tài), 檢測網(wǎng)絡(luò)的可用性. 需要網(wǎng)絡(luò)運營商相關(guān)信息用于網(wǎng)絡(luò)定位 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 訪問網(wǎng)絡(luò)的變化, 需要某些信息用于網(wǎng)絡(luò)定位 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 訪問手機當前狀態(tài), 需要device id用于網(wǎng)絡(luò)定位 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 支持A-GPS輔助定位 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<!-- 用于 log 日志 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

7.顯示當前定位

配置完成后增热,我們在DrivingRouteContract.Presenter接口中加入一個開始定位的startLocation和一個結(jié)束定位的stopLocation方法

void startLocation(boolean single);
void stopLocation();

再實現(xiàn)一下DrivingRoutePresent的方法

private boolean IS_SINGLE_LOCATION_MODE = false;//是否連續(xù)定位
private TencentLocationManager mLocationManager = TencentLocationManager.getInstance(GlobalApplication.getContext());
private TencentLocationRequest locationRequest;
 
@Override
public void startLocation(boolean single) {
    IS_SINGLE_LOCATION_MODE = single;//因為這里只需要定位一次钓葫,所以加了個參數(shù)
    locationRequest = TencentLocationRequest.create();
    locationRequest.setInterval(5000);//定位間隔
    //根據(jù)用戶獲取的位置信息的詳細程度,REQUEST_LEVEL_ADMIN_AREA:包含經(jīng)緯度帆调,位置所處的中國大陸行政區(qū)劃
    locationRequest.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_ADMIN_AREA);
    locationRequest.setAllowGPS(true);//是否允許使用GPS定位
    mLocationManager.requestLocationUpdates(locationRequest, this);//連續(xù)定位
}
 
@Override
public void stopLocation() {
    mLocationManager.removeUpdates(this);
}

除此之外豆同,為了獲得定位的位置信息,我們還需要讓DrivingRoutePresent額外實現(xiàn)TencentLocationListener接口芹务,實現(xiàn)onLocationChanged(用于接收定位結(jié)果)和onStatusUpdate(用于接收GPS,WiFi,Cell的狀態(tài)碼)方法鸭廷。

@Override
    public void onLocationChanged(TencentLocation tencentLocation, int i, String s) {
        if (IS_SINGLE_LOCATION_MODE)
            stopLocation();
        switch (i){
            case TencentLocation.ERROR_OK:
                //定位成功
                drinvingRouteView.setLocation(tencentLocation);
                //渲染定位信息
                if (drinvingRouteView.getFromET()!=null&&drinvingRouteView.getFromET().getText().toString().trim().equals(""))
                    drinvingRouteView.getFromET().setText(tencentLocation.getAddress());
//                Toast.makeText(GlobalApplication.getContext(), "定位成功", Toast.LENGTH_SHORT).show();
                break;
            case TencentLocation.ERROR_NETWORK:
                Toast.makeText(GlobalApplication.getContext(), "網(wǎng)絡(luò)問題引起的定位失敗", Toast.LENGTH_SHORT).show();
                break;
            case TencentLocation.ERROR_BAD_JSON:
                Toast.makeText(GlobalApplication.getContext(), "GPS, Wi-Fi 或基站錯誤引起的定位失敗", Toast.LENGTH_SHORT).show();
                break;
            case TencentLocation.ERROR_WGS84:
                Toast.makeText(GlobalApplication.getContext(), "無法將WGS84坐標轉(zhuǎn)換成GCJ-02坐標時的定位失敗", Toast.LENGTH_SHORT).show();
                break;
            case TencentLocation.ERROR_UNKNOWN:
                Toast.makeText(GlobalApplication.getContext(), "未知原因引起的定位失敗", Toast.LENGTH_SHORT).show();
                break;
        }
    }
 
    @Override
    public void onStatusUpdate(String s, int i, String s1) {
        //TencentLocationListener回調(diào)此方法傳入的GPS,WiFi,Cell狀態(tài)碼辆床,具體狀態(tài)碼查看Android定位SDK開發(fā)文檔
    }

最后,我們再把給定位的小按鈕綁定的點擊事件加上實現(xiàn)轿秧,在onResume和onPause方法調(diào)用一下startLocation和stopLocation方法讓app在開啟或切換回當前Activity時自動定位

@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.order_btn:
            drivingRoutePresent.geocoder(fromET.getText().toString(), DrivingRoutePresent.FROM_TYPE);
            drivingRoutePresent.geocoder(toET.getText().toString(), DrivingRoutePresent.TO_TYPE);
            confirmBtn.setVisibility(View.VISIBLE);
            orderBtn.setVisibility(View.GONE);
            break;
        case R.id.confirm_btn:
            //開啟動畫移動
            mAnimator.startAnimation();
            orderBtn.setVisibility(View.VISIBLE);
            confirmBtn.setVisibility(View.GONE);
            break;
        case R.id.location_ib:
            //定位一次
            drivingRoutePresent.startLocation(true);
            break;
    }
}
 
@Override
protected void onResume() {
    super.onResume();
    mapView.onResume();
    drivingRoutePresent.startLocation(true);
}
 
@Override
protected void onPause() {
    super.onPause();
    mapView.onPause();
    drivingRoutePresent.stopLocation();
}

結(jié)尾

寫到這里咨堤,效果圖上所有的功能就基本完成了一喘,總的來說,功能還是十分強大的铝侵,對于有相關(guān)需求的企業(yè)來說開發(fā)起來非常省時省力触徐。另外開發(fā)文檔和接口文檔也比較詳細狐赡。由于時間有限,暫時只體驗了其中的幾個服務(wù)鸟雏,有更多需求的同學可以自行到官網(wǎng)探索。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炊琉,一起剝皮案震驚了整個濱河市又活,隨后出現(xiàn)的幾起案子柳骄,更是在濱河造成了極大的恐慌,老刑警劉巖舔清,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曲初,死亡現(xiàn)場離奇詭異,居然都是意外死亡抒痒,警方通過查閱死者的電腦和手機目锭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門痢虹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人惨缆,你說我怎么就攤上這事丰捷。” “怎么了捣染?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵耍攘,是天一觀的道長。 經(jīng)常有香客問我蕾各,道長式曲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任兰伤,我火速辦了婚禮脆贵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘会烙。我一直安慰自己筒捺,他們只是感情好系吭,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沃缘,像睡著了一般则吟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上水慨,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天敬扛,我揣著相機與錄音啥箭,去河邊找鬼。 笑死抬驴,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的布持。 我是一名探鬼主播题暖,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捉超,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了枝誊?” 一聲冷哼從身側(cè)響起惜纸,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤耐版,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后古瓤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體腺阳,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡亭引,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了朝氓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片主届。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡君丁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出橡庞,到底是詐尸還是另有隱情,我是刑警寧澤丑勤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布吧趣,位于F島的核電站,受9級特大地震影響岔霸,放射性物質(zhì)發(fā)生泄漏俯渤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臀叙。 院中可真熱鬧,春花似錦渊涝、人聲如沸床嫌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缆娃。三九已至瑰排,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崇渗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工葫掉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跟狱,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓套腹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親幢码。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容