如何實現騰訊地圖的路徑規划功能?


前言

開發者在面對配送行業場景,諸如外賣,B2C零售,商超等需要路線規划的功能,尤其網約車行業,還需要用到計算路費、動畫模擬小車在路線上行駛等功能,這個騰訊位置服務產品的小demo就可以實現定位、規划路線、計算距離和路費,以及模擬小車平滑移動等基礎功能。

實現步驟

先看下實現效果:

新建個Android項目並新建個Activity,命名為DrivingRouteActivity,先來畫一下UI布局,布局比較簡單,由一個騰訊SDK包下的地圖組件MapView,以及兩個用於輸入起始位置的輸入框,兩個確認路線規划的Button,一個定位當前位置的ImageView,一個用於顯示行程信息的TextView組成,布局代碼只是為了方便展示實現功能,所以下面直接貼出布局代碼:

<?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="預約快車"
            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.賬號注冊與配置

在開發之前,我們需要到騰訊位置服務官網注冊一個賬號
注冊后進入控制台
選擇key管理,點擊創建新秘鑰,按照申請信息提交申請

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

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

2.引入騰訊Android地圖SDK

進入Android地圖SDK,下載3D版地圖SDK壓縮包
下載完成后打開壓縮包,將libs文件夾下的jar包拷貝到app的libs目錄下,右鍵該jar包選擇add as library添加為依賴,並且在項目app\src\main路徑下建立名為jniLibs的目錄,把壓縮包libs/jniLibs/strip文件夾下的所有包放到jniLibs目錄下
引入后在AndroidManifest.xml文件下配置相關權限

<!-- 訪問網絡獲取地圖服務 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 檢查網絡可用性 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 訪問WiFi狀態 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 需要外部存儲寫權限用於保存地圖緩存 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 獲取 device id 辨別設備 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

3.地圖初始化

配置完成,現在開始實現我們的邏輯交互,為了讓實現邏輯更加清晰,我將業務邏輯代碼與視圖渲染代碼分到了兩個包中,除了activity包中的DrivingRouteActivity之外,新建了一個present包,並在包下建立一個DrivingRoutePresent類,分別由DrivingRouteActivity負責對UI組件進行視圖渲染,由DrivingRoutePresent類負責業務邏輯。這里我還新建了一個contract包,並創建一個DrivingRouteContract接口,通過這個接口定義的方法,實現DrivingRoutePresent與DrivingRouteActivity之間的交互。我們在DrivingRouteContract接口中定義兩個接口,一個View接口供DrivingRouteActivity實現,一個Presenter接口供DrivingRoutePresent實現,並定義一些初始化的方法

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實現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:
                //實現行程路線規划
                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實現DrivingRouteContract.Presenter接口

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

因為我們后面在多個地方都需要用到當前應用的上下文,為了方便,需要再編寫一個全局的應用上下文工具類來幫助我們獲取上下文,建立一個util包並創建一個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標簽中加入下面屬性,讓應用啟動時加載上面的GlobalApplication

android:name=".util.GlobalApplication"

到這里,我們就完成了界面與業務代碼的基本設計,運行app,可以看到顯示的基本地圖信息。接下來我們來實現一下路線規划的功能。騰訊官方Android地圖SDK開發文檔對路線規划服務和地址解析都有較詳細的說明。
另外還提供了調用示例Demo。如果不清楚如何調用的話可以參考官方Demo或參考下面代碼。

4.地址解析與路線規划

首先我們在DrivingRouteContract.Presenter接口申明一個用於通過地址查找經緯度的geocoder方法和一個用於路線規划的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);//地址解碼,轉經緯度
        void routePlan();//實現路線規划
    }
}

通過騰訊Android地圖SDK路線規划服務的開發文檔,我們了解到要獲得規划路線需要先獲取起點和終點的經緯度,而在一般業務場景中,我們幾乎不會讓用戶手動輸入經緯度,所以我這里還需要用到地址解析服務,通過輸入中文地址來獲取經緯度,再通過經緯度規划路線(不過在實際業務中最好是加上關鍵詞輸入提示這個服務,方便用戶找到輸入的位置)。

在DrivingRoutePresent類中實現這兩個方法

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;//預估打車費用
private Float distance = 0f;//預計全程里程
 
/**
 * 路線規划
 */
@Override
public void routePlan() {
    if (fromLatLng!=null&&toLatLng!=null){
        Toast.makeText(GlobalApplication.getContext(), "正在為您規划路線", Toast.LENGTH_SHORT).show();
        DrivingParam drivingParam = new DrivingParam(fromLatLng, toLatLng);
        drivingParam.policy(DrivingParam.Policy.TRIP);//駕車路線規划策略,網約車場景,送乘客
        drivingParam.setCarNumber("粵A00001");//填入車牌號,在路線規划時會避讓車牌限行區域
        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,預計¥" + 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;
    }
}

其中geocoder方法用於獲得我們輸入的起始位置(從哪兒上車),以及輸入的目的位置(到哪兒下車)的坐標經緯度,記錄位置的經緯度后調用routePlan方法請求路線規划接口,並記錄下里程,費用信息,路線行駛過程中經過的點的經緯度(用於后面實現小車移動)。

路線規划接口除了上面使用的幾個常用參數外,還有很多接口參數,具體可以查看官方接口文檔按需要加入

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

5.車輛行駛動畫

有了路線規划方法后,給"預約快車"按鈕添加實現

@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,輸入起點和終點就可以獲得駕車的規划路線了

接下來,我們再實現一下效果圖上小車根據規划路線行駛的功能

在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);//地址解碼,轉經緯度
        void routePlan();//實現路線規划
    }
}

實現initAnimation方法,關於Marker其他參數同樣參考上面的接口文檔

private Marker mCarMarker;
private LatLng[] mCarLatLngArray;
private MarkerTranslateAnimator mAnimator;
 
@Override
public void initAnimation(String line) {
    //拆分獲得經緯度數組
    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));
 
    //創建移動動畫
    mAnimator = new MarkerTranslateAnimator(mCarMarker, 50 * 1000, mCarLatLngArray, true);
 
    //調整最佳視野
    mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(
            LatLngBounds.builder().include(Arrays.asList(mCarLatLngArray)).build(), 50));
}

並在routePlan方法中調用這個方法,傳入行駛路線字符串

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

完整代碼參考

/**
 * 路線規划
 */
@Override
public void routePlan() {
    if (fromLatLng!=null&&toLatLng!=null){
        Toast.makeText(GlobalApplication.getContext(), "正在為您規划路線", Toast.LENGTH_SHORT).show();
        DrivingParam drivingParam = new DrivingParam(fromLatLng, toLatLng);
        drivingParam.policy(DrivingParam.Policy.TRIP);//駕車路線規划策略,網約車場景,送乘客
        drivingParam.setCarNumber("粵A00001");//填入車牌號,在路線規划時會避讓車牌限行區域
        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,預計¥" + 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;
    }
}

最后我們在"確定"按鈕的點擊事件上調用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

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

我們打開Android定位SDK開發文檔,下載最新的SDK
將壓縮包內的jar包放入app的libs包下,並添加為依賴
再把壓縮包libs文件夾下的各個so文件拷貝到項目jniLibs的對應目錄中
打開AndroidManifest.xml文件,加入下面權限配置

<!-- 通過GPS得到精確位置 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 通過網絡得到粗略位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 訪問網絡. 某些位置信息需要從網絡服務器獲取 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 訪問WiFi狀態. 需要WiFi信息用於網絡定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 修改WiFi狀態. 發起WiFi掃描, 需要WiFi信息用於網絡定位 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 訪問網絡狀態, 檢測網絡的可用性. 需要網絡運營商相關信息用於網絡定位 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 訪問網絡的變化, 需要某些信息用於網絡定位 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 訪問手機當前狀態, 需要device id用於網絡定位 -->
<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和一個結束定位的stopLocation方法

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

再實現一下DrivingRoutePresent的方法

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

除此之外,為了獲得定位的位置信息,我們還需要讓DrivingRoutePresent額外實現TencentLocationListener接口,實現onLocationChanged(用於接收定位結果)和onStatusUpdate(用於接收GPS,WiFi,Cell的狀態碼)方法。

@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(), "網絡問題引起的定位失敗", 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坐標轉換成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回調此方法傳入的GPS,WiFi,Cell狀態碼,具體狀態碼查看Android定位SDK開發文檔
    }

最后,我們再把給定位的小按鈕綁定的點擊事件加上實現,在onResume和onPause方法調用一下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();
}

結尾

寫到這里,效果圖上所有的功能就基本完成了,總的來說,功能還是十分強大的,對於有相關需求的企業來說開發起來非常省時省力。另外開發文檔和接口文檔也比較詳細。由於時間有限,暫時只體驗了其中的幾個服務,有更多需求的同學可以自行到官網探索。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM