简单的路线规划demo

前言

这个腾讯地图的demo可以做到:1.定位位置2.规划起点和终点的路线3.显示规划路线距离以及计算路费4.动画模拟小车在规划路线上的平滑移动。

实现步骤

先看下实现效果:
image

新建个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.账号注册与配置

在开发之前,我们需要到腾讯位置服务官网注册一个账号


image

注册后进入控制台


image
选择key管理,点击创建新秘钥,按照申请信息提交申请

将上面申请的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文件夹下的所有包放到jniLibs目录下


image
引入后在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


image

将压缩包内的jar包放入app的libs包下,并添加为依赖


image
再把压缩包libs文件夹下的各个so文件拷贝到项目jniLibs的对应目录中
image
image

打开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();
}

结尾

写到这里,效果图上所有的功能就基本完成了,总的来说,功能还是十分强大的,对于有相关需求的企业来说开发起来非常省时省力。另外开发文档和接口文档也比较详细。由于时间有限,暂时只体验了其中的几个服务,有更多需求的同学可以自行到官网探索。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容