zoukankan      html  css  js  c++  java
  • 【Android】3.13 路径规划功能

    分类:C#、Android、VS2015、百度地图应用; 创建日期:2016-02-04

    一、简介

    线路规划支持以下功能:

    • 公交信息查询:可对公交详细信息进行查询;
    • 公交换乘查询:根据起、终点,查询策略,进行线路规划方案;
    • 驾车线路规划:提供不同策略,规划驾车路线;(支持设置途经点)
    • 步行路径检索:支持步行路径的规划。

    其中驾车线路规划自v3.4.0版本起支持多线路检索结果的能力。

    二、运行截图

    简介:介绍公交、驾车和步行三种线路规划方法和自设路线方法。

    详述:

    (1)驾车查询新增路径点查询功能,具体使用方法详见开发者指南路径规划部分,只需重载接口;

    (2)自设路线功能演示开发者如何自己设定一条路线,包括如何设定起点、终点、途径站点和路段;

    (3)自设路线功能同时也介绍如何在两个Activity之间切换的时候管理Mapview的生命周期;

    (4)可自定义路线的起终点图标;

    本示例运行截图如下:

    image

    三、设计步骤

    1、添加自定义类【代码太多,就不再粘贴在这里了】

    本示例用到的文件很多,主要涉及的是自定义覆盖物的相关类,这些文件都在SrcOverlayUtil文件夹下,除了上一节列出的OverlayManager.cs文件和PoiOverlay.cs外,还包括下面的文件。

    (1)BikingRouteOverlay.cs文件

    用于显示骑行路线的Overlay,自3.4.0版本起可实例化多个添加在地图中显示。

    (2)BusLineOverlay.cs文件

    用于显示一条公交详情结果的Overlay。

    (3)DrivingRouteOverlay.cs文件

    用于显示一条驾车路线的overlay,自3.4.0版本起可实例化多个添加在地图中显示,当数据中包含路况数据时,则默认使用路况纹理分段绘制。

    (4)TransitRouteOverlay.cs文件

    用于显示换乘路线的Overlay,自3.4.0版本起可实例化多个添加在地图中显示。

    (5)WalkingRouteOverlay.cs文件

    用于显示步行路线的overlay,自3.4.0版本起可实例化多个添加在地图中显示。

    2、添加demo13_routeplan.xml文件

    在layout文件夹下添加该文件,然后将代码改为下面的内容:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
            <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="起点:" />
            <EditText
                android:id="@+id/start"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:text="龙泽" >
                <requestFocus />
            </EditText>
        </LinearLayout>
    
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="终点:" />
            <EditText
                android:id="@+id/end"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:text="西单" >
                <requestFocus />
            </EditText>
        </LinearLayout>
    
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dip"
            android:layout_marginTop="5dip"
            android:orientation="horizontal" >
            <Button
                android:id="@+id/drive"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:layout_weight="1.0"
                android:background="@drawable/button_style"
                android:text="驾车搜索" />
            <Button
                android:id="@+id/transit"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:layout_weight="1.0"
                android:background="@drawable/button_style"
                android:text="公交搜索" />
            <Button
                android:id="@+id/walk"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:layout_weight="1.0"
                android:background="@drawable/button_style"
                android:text="步行搜索" />
            <Button
                android:id="@+id/bike"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:layout_weight="1.0"
                android:background="@drawable/button_style"
                android:text="骑行搜索" />
        </LinearLayout>
    
        <RelativeLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
    
           <com.baidu.mapapi.map.TextureMapView
                android:id="@+id/map"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:clickable="true" />
    
           <LinearLayout
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_alignParentTop="true"
                android:layout_alignWithParentIfMissing="false"
                android:layout_marginRight="10dp"
                android:layout_marginTop="10dip"
                android:orientation="vertical" >
                <Button
                    android:id="@+id/customicon"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:layout_marginTop="10dip"
                    android:layout_weight="1.0"
                    android:background="@drawable/button_style"
                    android:text="自定义起终点图标" />
            </LinearLayout>
    
            <LinearLayout
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_alignWithParentIfMissing="false"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="false"
                android:layout_marginBottom="10dip" >
    
                <Button
                    android:id="@+id/pre"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="2dip"
                    android:layout_marginRight="2dip"
                    android:layout_weight="1.0"
                    android:background="@drawable/pre_" />
    
                <Button
                    android:id="@+id/next"
                    android:layout_width="fill_parent"
                    android:layout_height="fill_parent"
                    android:layout_marginLeft="2dip"
                    android:layout_marginRight="2dip"
                    android:layout_weight="1.0"
                    android:background="@drawable/next_" />
            </LinearLayout>
        </RelativeLayout>
    
    </LinearLayout>

    3、添加Demo13RoutePlan.cs文件

    在SrcSdkDemos文件夹下添加该文件,然后将代码改为下面的内容:

    using Android.App;
    using Android.Content.PM;
    using Android.OS;
    using Android.Views;
    using Android.Widget;
    using Com.Baidu.Mapapi.Map;
    using Com.Baidu.Mapapi.Model;
    using Com.Baidu.Mapapi.Search.Core;
    using Com.Baidu.Mapapi.Search.Route;
    using BdMapV371Demos.SrcOverlayUtil;
    
    namespace BdMapV371Demos.SrcSdkDemos
    {
        /// <summary>
        ///此demo用来展示如何进行驾车、步行、公交路线搜索并在地图使用RouteOverlay、TransitOverlay绘制,
        ///同时展示如何进行节点浏览并弹出泡泡。
        /// </summary>
        [Activity(Label = "@string/demo_name_route",
            ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden,
            ScreenOrientation = ScreenOrientation.Sensor)]
        public class Demo13RoutePlan : Activity
        {
            //浏览路线节点相关
            Button btnPre = null;//上一个节点
            Button btnNext = null;//下一个节点
            int nodeIndex = -2;//节点索引,供浏览节点时使用
            RouteLine route = null;
            OverlayManager routeOverlay = null;
            bool useDefaultIcon = false;
            private TextView popupText = null;//泡泡view
    
            //地图相关,使用MyRouteMapView目的是重写touch事件实现泡泡处理。
            //如果不处理touch事件,则无需继承,直接使用TextureMapView即可。
            TextureMapView mMapView = null;   // 地图View
            BaiduMap mBaidumap = null;
            //搜索相关
            RoutePlanSearch mSearch = null;    // 搜索模块,也可去掉地图模块独立使用
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                SetContentView(Resource.Layout.demo13_routeplan);
    
                //初始化地图
                mMapView = FindViewById<TextureMapView>(Resource.Id.map);
                mBaidumap = mMapView.Map;
    
                btnPre = FindViewById<Button>(Resource.Id.pre);
                btnNext = FindViewById<Button>(Resource.Id.next);
                btnPre.Visibility = ViewStates.Invisible;
                btnNext.Visibility = ViewStates.Invisible;
    
                //处理地图点击事件
                mBaidumap.MapClick += (s, e) =>
                {
                    //LatLng point = e.P0;
                    //Toast.MakeText(this, point.ToString(), ToastLength.Long).Show();
                    mBaidumap.HideInfoWindow();
                };
    
                //--begin--初始化搜索模块,注册处理事件
                mSearch = RoutePlanSearch.NewInstance();
                //处理驾车搜索结果
                mSearch.GetDrivingRouteResult += (s, e) =>
                {
                    var result = e.P0;
                    if (result == null || result.Error != SearchResult.ERRORNO.NoError)
                    {
                        Toast.MakeText(this, "抱歉,未找到结果", ToastLength.Short).Show();
                    }
                    if (result.Error == SearchResult.ERRORNO.AmbiguousRoureAddr)
                    {
                        //起终点或途经点地址有岐义,通过result.SuggestAddrInfo属性获取建议查询信息
                        //......
                        return;
                    }
                    if (result.Error == SearchResult.ERRORNO.NoError)
                    {
                        nodeIndex = -1;
                        btnPre.Visibility = ViewStates.Visible;
                        btnNext.Visibility = ViewStates.Visible;
                        route = result.RouteLines[0];
                        DrivingRouteOverlay overlay = new MyDrivingRouteOverlay(this, mBaidumap);
                        routeOverlay = overlay;
                        mBaidumap.MarkerClick += (sender, args) =>
                        {
                            //......
                        };
                        overlay.SetData(result.RouteLines[0]);
                        overlay.AddToMap();
                        overlay.ZoomToSpan();
                    }
                };
                //处理公交搜索结果
                mSearch.GetTransitRouteResult += (s,e) =>
                {
                    var result = e.P0;
                    if (result == null || result.Error != SearchResult.ERRORNO.NoError)
                    {
                        Toast.MakeText(this, "抱歉,未找到结果", ToastLength.Short).Show();
                    }
                    if (result.Error == SearchResult.ERRORNO.AmbiguousRoureAddr)
                    {
                        //起终点或途经点地址有岐义,通过以下接口获取建议查询信息
                        //result.getSuggestAddrInfo()
                        return;
                    }
                    if (result.Error == SearchResult.ERRORNO.NoError)
                    {
                        nodeIndex = -1;
                        btnPre.Visibility = ViewStates.Visible;
                        btnNext.Visibility = ViewStates.Visible;
                        route = result.RouteLines[0];
                        TransitRouteOverlay overlay = new MyTransitRouteOverlay(this, mBaidumap);
                        mBaidumap.MarkerClick += (sender, args) =>
                        {
                            //......
                        };
                        routeOverlay = overlay;
                        overlay.SetData(result.RouteLines[0]);
                        overlay.AddToMap();
                        overlay.ZoomToSpan();
                    }
                };
                //处理步行搜索结果
                mSearch.GetWalkingRouteResult += (s, e) =>
                {
                    var result = e.P0;
                    if (result == null || result.Error != SearchResult.ERRORNO.NoError)
                    {
                        Toast.MakeText(this, "抱歉,未找到结果", ToastLength.Short).Show();
                    }
                    if (result.Error == SearchResult.ERRORNO.AmbiguousRoureAddr)
                    {
                        //起终点或途经点地址有岐义,通过以下接口获取建议查询信息
                        //result.getSuggestAddrInfo()
                        return;
                    }
                    if (result.Error == SearchResult.ERRORNO.NoError)
                    {
                        nodeIndex = -1;
                        btnPre.Visibility = ViewStates.Visible;
                        btnNext.Visibility = ViewStates.Visible;
                        route = result.RouteLines[0];
                        WalkingRouteOverlay overlay = new MyWalkingRouteOverlay(this, mBaidumap);
                        mBaidumap.MarkerClick += (sender, args) =>
                        {
                            //......
                        };
                        routeOverlay = overlay;
                        overlay.SetData(result.RouteLines[0]);
                        overlay.AddToMap();
                        overlay.ZoomToSpan();
                    }
                };
                //处理骑行搜索结果
                mSearch.GetBikingRouteResult += (s, e) =>
                {
                    var result = e.P0;
                    if (result == null || result.Error != SearchResult.ERRORNO.NoError)
                    {
                        Toast.MakeText(this, "抱歉,未找到结果", ToastLength.Short).Show();
                    }
                    if (result.Error == SearchResult.ERRORNO.AmbiguousRoureAddr)
                    {
                        // 如果起终点或途经点地址有岐义,可通过result.SuggestAddrInfo属性获取建议查询信息
                        //......
                        return;
                    }
                    if (result.Error == SearchResult.ERRORNO.NoError)
                    {
                        nodeIndex = -1;
                        btnPre.Visibility = ViewStates.Visible;
                        btnNext.Visibility = ViewStates.Visible;
                        route = result.RouteLines[0];
                        BikingRouteOverlay overlay = new MyBikingRouteOverlay(this, mBaidumap);
                        routeOverlay = overlay;
                        mBaidumap.MarkerClick += (sender, args) =>
                        {
                            //......
                        };
                        overlay.SetData(result.RouteLines[0]);
                        overlay.AddToMap();
                        overlay.ZoomToSpan();
                    }
                };
                //--end--初始化搜索模块,注册监听事件
    
                //处理【驾车搜素】按钮点击事件
                var btnDrive = FindViewById<Button>(Resource.Id.drive);
                btnDrive.Click += delegate
                {
                    SearchButtonProcess(Resource.Id.drive);
                };
    
                //处理【公交搜素】按钮点击事件
                var btnTransit = FindViewById<Button>(Resource.Id.transit);
                btnTransit.Click += delegate
                {
                    SearchButtonProcess(Resource.Id.transit);
                };
    
                //处理【步行搜素】按钮点击事件
                var btnWalk = FindViewById<Button>(Resource.Id.walk);
                btnWalk.Click += delegate
                {
                    SearchButtonProcess(Resource.Id.walk);
                };
    
                //处理【骑行搜素】按钮点击事件
                var btnBike = FindViewById<Button>(Resource.Id.bike);
                btnBike.Click += delegate
                {
                    SearchButtonProcess(Resource.Id.bike);
                };
    
                //处理【自定义起终点图标】按钮点击事件
                var btnCustomicon = FindViewById<Button>(Resource.Id.customicon);
                btnCustomicon.Click += delegate
                {
                    //切换路线图标,刷新地图使其生效。注意:起终点图标使用中心对齐。
                    if (routeOverlay == null) return;
                    if (useDefaultIcon)
                    {
                        btnCustomicon.Text = "自定义起终点图标";
                        Toast.MakeText(this,"将使用系统起终点图标", ToastLength.Short).Show();
                    }
                    else
                    {
                        btnCustomicon.Text = "系统起终点图标";
                        Toast.MakeText(this, "将使用自定义起终点图标", ToastLength.Short).Show();
                    }
                    useDefaultIcon = !useDefaultIcon;
                    routeOverlay.RemoveFromMap();
                    routeOverlay.AddToMap();
                };
    
                //处理节点浏览相关的按钮事件
                btnPre.Click += delegate
                {
                    NodeClick(Resource.Id.pre);
                };
                btnNext.Click += delegate
                {
                    NodeClick(Resource.Id.next);
                };
            }
    
            /// <summary>
            /// 发起路线规划搜索
            /// </summary>
            /// <param name="id">按钮的id</param>
            public void SearchButtonProcess(int id)
            {
                //重置浏览节点的路线数据
                route = null;
                btnPre.Visibility = ViewStates.Invisible;
                btnNext.Visibility = ViewStates.Invisible;
                mBaidumap.Clear();
                // 处理搜索按钮响应示例
                EditText editSt = FindViewById<EditText>(Resource.Id.start);
                EditText editEn = FindViewById<EditText>(Resource.Id.end);
                //设置起终点信息,对于tranist search 来说,城市名无意义
                PlanNode stNode = PlanNode.WithCityNameAndPlaceName("北京", editSt.Text);
                PlanNode enNode = PlanNode.WithCityNameAndPlaceName("北京", editEn.Text);
    
                // 实际使用中请对起点终点城市进行正确的设定
                if (id == Resource.Id.drive)
                {
                    mSearch.DrivingSearch(new DrivingRoutePlanOption()
                        .From(stNode).To(enNode));
                }
                else if (id == Resource.Id.transit)
                {
                    mSearch.TransitSearch(new TransitRoutePlanOption()
                        .From(stNode).City("北京").To(enNode));
                }
                else if (id == Resource.Id.walk)
                {
                    mSearch.WalkingSearch(new WalkingRoutePlanOption()
                        .From(stNode).To(enNode));
                }
                else if (id == Resource.Id.bike)
                {
                    mSearch.BikingSearch(new BikingRoutePlanOption()
                        .From(stNode).To(enNode));
                }
            }
    
            /// <summary>
            /// 节点浏览示例
            /// </summary>
            /// <param name="id">按钮的id</param>
            public void NodeClick(int id)
            {
                if (nodeIndex < -1 || route == null ||
                    route.AllStep == null || nodeIndex > route.AllStep.Count)
                {
                    return;
                }
                //设置节点索引
                if (id == Resource.Id.next && nodeIndex < route.AllStep.Count - 1)
                {
                    nodeIndex++;
                }
                else if (id == Resource.Id.pre && nodeIndex > 1)
                {
                    nodeIndex--;
                }
                if (nodeIndex < 0 || nodeIndex >= route.AllStep.Count)
                {
                    return;
                }
    
                //获取节结果信息
                LatLng nodeLocation = null;
                string nodeTitle = null;
                var step = route.AllStep[nodeIndex];
                if (step is DrivingRouteLine.DrivingStep)
                {
                    nodeLocation = ((DrivingRouteLine.DrivingStep)step).Entrance.Location;
                    nodeTitle = ((DrivingRouteLine.DrivingStep)step).Instructions;
                }
                else if (step is WalkingRouteLine.WalkingStep)
                {
                    nodeLocation = ((WalkingRouteLine.WalkingStep)step).Entrance.Location;
                    nodeTitle = ((WalkingRouteLine.WalkingStep)step).Instructions;
                }
                else if (step is TransitRouteLine.TransitStep)
                {
                    nodeLocation = ((TransitRouteLine.TransitStep)step).Entrance.Location;
                    nodeTitle = ((TransitRouteLine.TransitStep)step).Instructions;
                }
    
                if (nodeLocation == null || nodeTitle == null)
                {
                    return;
                }
                //移动节点至中心
                mBaidumap.SetMapStatus(MapStatusUpdateFactory.NewLatLng(nodeLocation));
                // Show popup
                popupText= new TextView(this);
                popupText.SetBackgroundResource(Resource.Drawable.popup);
                popupText.SetTextColor(Android.Graphics.Color.Black);
                popupText.Text = nodeTitle;
                mBaidumap.ShowInfoWindow(new InfoWindow(popupText, nodeLocation, 0));
            }
    
            protected override void OnRestoreInstanceState(Bundle savedInstanceState)
            {
                base.OnRestoreInstanceState(savedInstanceState);
            }
    
            //定制RouteOverly
            private class MyDrivingRouteOverlay : DrivingRouteOverlay
            {
                Demo13RoutePlan routePlanDemo;
    
                public MyDrivingRouteOverlay(Demo13RoutePlan routePlanDemo, BaiduMap baiduMap) :
                    base(baiduMap)
                {
                    this.routePlanDemo = routePlanDemo;
                }
    
                public override BitmapDescriptor GetStartMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_st);
                    }
                    return null;
                }
    
                public override BitmapDescriptor GetTerminalMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_en);
                    }
                    return null;
                }
            }
    
            private class MyWalkingRouteOverlay : WalkingRouteOverlay
            {
                Demo13RoutePlan routePlanDemo;
                public MyWalkingRouteOverlay(Demo13RoutePlan routePlanDemo, BaiduMap baiduMap) :
                    base(baiduMap)
                {
                    this.routePlanDemo = routePlanDemo;
                }
    
                public new BitmapDescriptor GetStartMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_st);
                    }
                    return null;
                }
    
                public new BitmapDescriptor GetTerminalMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_en);
                    }
                    return null;
                }
            }
    
            private class MyTransitRouteOverlay : TransitRouteOverlay
            {
                Demo13RoutePlan routePlanDemo;
    
                public MyTransitRouteOverlay(Demo13RoutePlan routePlanDemo, BaiduMap baiduMap) :
                    base(baiduMap)
                {
                    this.routePlanDemo = routePlanDemo;
                }
    
                public override BitmapDescriptor GetStartMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_st);
                    }
                    return null;
                }
    
                public override BitmapDescriptor GetTerminalMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_en);
                    }
                    return null;
                }
            }
    
            private class MyBikingRouteOverlay : BikingRouteOverlay
            {
                Demo13RoutePlan routePlanDemo;
                public MyBikingRouteOverlay(Demo13RoutePlan routePlanDemo, BaiduMap baiduMap) : base(baiduMap)
                {
                    this.routePlanDemo = routePlanDemo;
                }
    
                public new BitmapDescriptor GetStartMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_st);
                    }
                    return null;
                }
    
                public new BitmapDescriptor GetTerminalMarker()
                {
                    if (routePlanDemo.useDefaultIcon)
                    {
                        return BitmapDescriptorFactory.FromResource(Resource.Drawable.icon_en);
                    }
                    return null;
                }
            }
    
            protected override void OnPause()
            {
                mMapView.OnPause();
                base.OnPause();
            }
    
            protected override void OnResume()
            {
                mMapView.OnResume();
                base.OnResume();
            }
    
            protected override void OnDestroy()
            {
                mSearch.Destroy();
                mMapView.OnDestroy();
                base.OnDestroy();
            }
        }
    }

    4、修改MainActivity.cs

    在MainActivity.cs文件的demos字段定义中,去掉【示例13】下面的注释。

    运行观察结果。

  • 相关阅读:
    IIS7.x经典模式与集成模式
    pocketsphinx实现连续大词汇量语音识别
    js对象冒充实现的继承
    你不得不知道的HTML5的新型标签
    (译)开发优秀的虚拟现实体验:从开发I Expect You to Die中总结的六个要点
    《构建之法》阅读梳理篇读后感
    VR介绍
    推荐
    VR设备
    开发VR游戏的基本要求
  • 原文地址:https://www.cnblogs.com/rainmj/p/5181595.html
Copyright © 2011-2022 走看看