高德地图导航的时候微信位置导航添加高德不会动怎么回事

现在好多小伙伴都会用高德地图导航, 但有些小伙伴在使用高德地图导航时发现突然光标突然不能动了,很是着急不知道怎么办,下面小编从网上找来高德地图导航时光标不动时的解决方法。
&高德地图导航时光标不动怎么办&
第一步:需确认:如果是IOS用户,反馈主图定位正常但自驾导航无法定位:
上一次重启手机的时间?如超过50天,请您重启手机后尝试。
第二步:主图和导航情况下光标(定位)都不动
1. 查看手机是是否开启定位。
安卓手机:如果您的设备无法定位,请确保开启位置服务GPS、Wifi(别称WLAN/无线局域网)、移动数据,Wifi无需连接,打开即可。
快捷方式:手指从屏幕最上向下滑动,出现快捷开关,点亮按钮即可。
苹果手机:如果您的iPhone无法定位,请确保开启iPhone定位服务,步骤如下:打开 设置-&隐私-&定位服务-&打开开关(显示为绿色)-&找到高德地图-&勾选&始终&。
2.开启GPS定位、Wifi、移动网络后,依旧无法定位。
第一情况:请检查应用授权情况,步骤如下:(不同设备可能操作不同)
设置-&应用管理-&授权管理-&高德地图-&权限管理-&定位-&允许,重新进入高德地图。
第二种情况:有些设备权限管理更严格,尽管开启了位置服务权限,需选择&使用GPS、WLAN和移动网络确定位置&才能确保无论在室内或室外都有定位。
若仅勾选&使用WLAN和移动网络确定位置&在户外WLAN稀疏区域会导致定位失败;若仅勾选&使用GPS确定您的位置&会导致在建筑内部/无法看到天空时设备无法接收GPS信号导致定位失败。
为了保证您的定位质量,小德建议您勾选&使用GPS、WLAN和移动网络确定位置&。不同设备操作步骤根据实际情况而定,还可能存在如下界面,建议您全部勾选以确保定位质量。
3.如果确认定位和应用权限都已经开启,但仍无法定位。建议您尝试以下方法:
GPS定位与天气情况,车辆所处位置,内置GPS模块强弱有关,建议您将手机的GPS关闭再重新打开,到空旷地方重新尝试或是检测一下手机GPS模块。
【安卓用户检测手机GPS模板方法】:
在导航中遇到提示&当前GPS信号弱,请到开阔地带&问题时,基本都是搜星慢或者系统gps无法定位问题。推荐您安装APP&GPStest&进行自查。
软件使用方法:
左上角 GPS Status处显示卫星定位状态,No Fix为未定位成功,3D Fix标识GPS已定位。
图中 In View标识可见卫星数量,In Use标识已连接卫星数量,In Use卫星卫星数量低于4颗即无法定位。
如软件检测为No Fix状态,则无法导航为正常现象,该问题与手机质量、当前所处环境有关。
如手机GPS质量较差则容易出现不能定位或首次GPS定位时间过长;环境遮挡(如高架桥下,高楼密集地区、室内等)会容易出现无法定位的情况。
【IOS用户检测手机GPS模块方法】:推荐您安装&GPS状态&APP。
软件使用方法:用户在运动状态(自驾页面),手机滑动到第二页,如果显示当前速度,说明手机GPS定位没问题;如果在运动状态(驾驶中)下,页面不显示速度,说明手机接收GPS信号有问题,建议您去售后检测。
4.如果安卓手机安装APP&GPStest&后,发现手机GPS定位正常,但是高德地图仍无法定位。需要您提供下手机品牌、手机型号、手机系统版本、高德软件版本、点击设置-关于高德地图,快速联系点击上方的小飞机图标10次,出现的界面复制过来、手机GPS监测截图给高德官方。
第三步:主图定位正常,但导航定位异常。
也同样提供上述所需信息。
相关文章:
以上就是高德地图导航时光标不动时的解决办法介绍。
版权所有Copyright(C) Ruan8.com copyright 上海凯匠网络科技有限公司
var first=document.body.lastC//得到页面的最后一个元素
document.body.insertBefore(divObj,first);
$(document).on('click', "#icons", function () {
$("#advbox").hide();学习的心态
高德地图定位及显示位置
如何找到设备的位置和如何在地图上显示位置。
Core Location
Core Location不是一个UI的东西,没有用户界面,它只是关于找到该设备的位置。新设备有很多定位装置,比如磁力计、加速度计、全球定位系统(GPS),各种无线,各种能找出你在哪里的东西。Core Location的基本对象是一个CLLocation,CL是Core Location库的前缀,location是基本对象。CLLocation里的properties:
@properties: coordinate, altitude, horizontal/verticalAccuracy, timestamp, speed, course
关于这个位置读数的精度,会谈到时间戳(timestamp),就是这个位置何时被记录。speed,移动的速度有多快,通过GPS坐标的瞬时读数判断。course,类似移动的航行。最重要的是coordinate,它告诉你这个CLLocation在哪里。
coordinate是一个C结构体,只有latitude(经度)和longitude(纬度):
@property (readonly) CLLocationCoordinate2D
CLLocationD
//a double
CLLocationD
//a double
} CLLocationCoordinate2D;
@property (readonly) CLLocationD // meters
CLLocationDegrees基本上是double,浮点数。altitude(海拔)单位是米,可以得到海拔的高度。
coordinate的latitude和longitude有多精确?CLLocation有一对properties:
@property (readonly) CLLocationAccuracy horizontalA
// in meters
@property (readonly) CLLocationAccuracy verticalA
// in meters
它告诉你漂移量是多少,单位是米。通常不会把它们当做数值来看,会更多地看这些预定义的值,如AccuracyBestForNavigation,它将不断更新GPS。GPS可以测量垂直。
kCLLocationAccuracyNearestTenMeters就基本是你在的位置;kCLLocationAccuracyHundredMeters就是你在这一区域的某处;kCLLocationAccuracyKilometer和kCLLocationAccuracyThreeKilometers都是采用基站的方式,精度非常粗糙。
最好的是用不断更新的GPS(精度最高,耗电量最大),次好的是用WiFi(设备可以发现周围的WiFi热点和信号有多强,并通过查看互联网上的一个数据库来找出你在哪里),第三个也是最不准确的是基站(最不准确的,几乎不耗电)。所以是根据你的app需要什么精度来选择。
速度、航向、时间戳,这些都是一种即时测量,比如speed只计算最后一定数量的GPS位置,course就是航向,所有这些API都是抽象的,它只是根据你的设备来向你汇报最佳信息。
怎么得到CLLocation,这些Core Location里的位置对象?几乎总是通过另一个对象CLLocationManager获取。
在ios 5中要注意的一件重要的事情是,你可以模拟你的位置,当你在模拟器上使用这个运行时才出现的菜单,基本上可以在地球上随便挑个地方作为你的位置,甚至可以有自己的GPX文件,它像个简单的XML格式,里面编码了一堆经度和纬度,甚至可以模拟移动之类的:
有四件事与CLLocationManager有关,四个都要做:
第一个,是你要检查有什么硬件可用;
第二个,你要创建这些CLLocationManagers之一,并设置自己为delegate,因为CLLocationManager将要使用delegate来进行更新;
第三个,你要配置这个manager,你想要什么样的位置更新、航行或仅仅是位置移动,有各种不同的定位监测,它不是只能告诉我我在哪里, 它有相当的灵活性,当你设置好后要进行下一步;
第四个,就是你要开始监测,当你启动它的监测,它会根据你的配置来给delegate发消息。
有哪些基于位置的监控?有基于精度的持续更新,这意味着你设置了精度,然后在这个精度等级下的移动都会得到持续的更新;再有就是只有发生显著变化时才更新;还有基于区域的更新,定义一个地球上的区域,当人进入该地区时,你会得到更新;当然还有航行监测,它只会在设备指向不同的方向时进行报告。
第一个步骤是检查,看看你的硬件可以做什么:
+(BOOL)locationServicesE //has the user enabled location monitoring in Settings?
+(BOOL)headingA
// can this hardware provide heading info (compass)?
+(BOOL)significantLocationChangeMonitoringA //only if device has cellular?
+(BOOL)regionMonitoringA//only certain iOS4 devices
+(BOOL)regionMonitoringE//by the user in Settings
你必须要检查一些事情,比如locationServicesEnabled,因为当你请求这些东西的时候,系统会弹出警告说这个app要使用你的位置,如果用户选择no,定位服务不会开启。甚至要检查,看看这些东西是否可行,并非所有的设备可以做这些事情。
当系统提示你的app要使用位置服务的时候,它会用这个字符串,CLLocationManager里的Purpose string:
@property (copy) NSString *
这就是提示的内容,所以这会用来解释为什么这个app要使用你的位置服务,这样的目的可能是用你的GPS位置来标记你的图片。你设置了CLLocationManager里的Purpose string,当你开始监控,如果系统询问用户,将会使用此字符串。如果终端用户允许你使用定位服务,几乎肯定可以得到他们的GPS定位。
在苹果公司有很多政策文件,它们建议你如何做用户界面,甚至是在App Store审核的时候的一些强制条款。
一旦检查过了有什么硬件可用,现在你就可以从CLLocationManager获取信息了,你通常不会主动获取,通常你可以设置它的delegate,然后设置你想要的精度,然后你还可以设置distanceFilter,只有离开上个更新点一定距离才进行更新:
@property CLLocationAccuracy desiredA //always set this as low as possible
@property CLLocationDistance distanceF
你设置了这些,然后你只需要调用CLLocationManager的startUpdatingLocation,它将开始向你的delegate发消息:
- (void)startUpdatingL
- (void)stopUpdatingL
最主要的方法是:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldL
它会向你发送一个新的CLLocation对象,也将发送给你上次那个,这样你就可以跟踪用户在做什么。
Heading monitoring基本上和location monitoring是一样的,只是监测航向。当它给你一个航向,heading长什么样子?就像CLLocation一样,是CLHeading,CLHeading有magneticHeading(磁场航向)和trueHeading(真实航向),如果位置服务被关闭了,GPS和wifi所有这一切都是通过磁力计的,都是magneticHeading。位置服务必须打开,否则无法得到trueHeading,只能得到magneticHeading。
磁力计会让你把手机做8字移动,这样它就能测量磁力计收到的电磁干扰,这是由ios自动完成。可以通过在以下方法里返回NO来阻止它:
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)
你不应该忽略此delegate方法,不能得到很好的航向信息,就会得到error,就会知道发生了什么事:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)
这是基于精度的更新,还有其他各种位置监测,一个被称为Significant location change monitoring(显著位置变化监测),它只监视大的变化,酷的是你的app甚至不用运行,一旦你的app注册以后,你就会开始接收这些显著的位置变化。如果app因为Significant location change而被运行,你会得到appdelegate.m中的application:didFinishLaunchingWithOptions:方法。如果你打开这个Significant
location change,然后Significant location change发生了,并且app在后台,app仍然会得到其delegate方法,app会得到唤醒。
类似的,还有基于区域的东西,指定一个区域,当进入或离开该区域,你都会得到更新。同样的,没有运行也会得到这些更新。
这是一个不同的framework,这是你如何使用这种谷歌地图技术来图形地显示位置。
Map Kit里的主要类是MKMapView,它只是一个UIView,用来显示地图。在地图上,MKMapView有一个非常重要的property称为annotations,它是一个实现MKAnnotation protocol的对象的NSArray,该protocol仅仅是一个coordinate、一个title和一个subtitle。annotations使用MKAnnotationView来显示在地图上,它们以红色的pins的形式出现,annotations还可以有一个callout,当你点击pin,一种灰色的矩形会出现就是callout,并展示了一些信息,比如它要同时呈现title和subtitle,也可以有左右callout
accessory。
要如何创建一个MapView?通常将它从对象库里拖到你的东西里面。还有这个property,annotations的数组:
@property (readonly) NSArray * // contains id &MKAnnotation& objects
这是一个id&MKAnnotation&对象的数组,它们可以是任何类对象,但它们必须要实现MKAnnotation protocol。所以这不是delegation,这是一个不同的protocol使用,这仅是定义一个对象可以做什么。
MKAnnotation protocol里有什么?其中之一是required的,就是coordinate,这只是一个CLLocationCoordinate2D;其他两个是optional:title和subtitle。annotation里的对象只要实现这几个。
注意annotations是只读的,可以通过以下方法来添加annotations或删除annotations:
- (void)addAnnotation:(id &MKAnnotation&)
- (void)addAnnotations:(NSArray *)
- (void)removeAnnotation:(id &MKAnnotation&)
- (void)removeAnnotations:(NSArray *)
通常一开始你就把你的annotations都放进去,因为MapView会像TableView那样重用这些pins。如果把它们都放进去,就会知道所有pins的位置,可以更高效的知道当前哪些地方需要pins。
annotations在地图上的外观:这些pins,这些MKPinAnnotationView,是在Map Kit里的默认的view,它有几个property,比如可以设置pins的颜色。也可以创建自己的MKAnnotationView子类,基础类是image,MKPinAnnotationView就是设置该image为pin,不要把MKAnnotation使用的image如这个pin image和callout里的image混淆了。
当你点击一个annotation view会发生什么呢?callout会出来。如何控制callout的内容,在MapView里有个非常重要的delegate,设置它的delegate就会得到这个消息:
- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aV
当annotation被点击的时候它会发消息给你。记住,annotation view知道哪个annotation正在被浏览,所以也就可以得到被点击的那个annotation。
如何创建这些MKAnnotationViews?如果什么都不做,会得到pin,当你点击pin,会得到一个带有title和subtitle的callout。如果你想控制callout的内容或外观,你可以实现MapView的delegate方法:
- (MKAnnotationView *)mapView:(MKMapView *)sender
viewForAnnotation:(id &MKAnnotation&)annotation
MKAnnotationView *aView = [sender dequeueReusableAnnotationViewWithIdentifier:IDENT];
if (!aView) {
aView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:IDENT];
// set canShowCallout to YES and build aView’s callout accessory views here
aView.annotation = // yes, this happens twice if no dequeue
// maybe load up accessory views here (if not too expensive)?
// or reset them and wait until mapView:didSelectAnnotationView: to load actual data
这和tableView的cellForRowAtIndexPath非常相似。每次要在地图上显示一个特定的annotation的时候,它会被调用,它要调用这个来得到要显示的veiw。要让canShowCallout等于YES,否则点击的时候就不会得到callout。不管aView是被创建或被出队,都要设置annotations。
如果设置了callout的左侧或右侧为一个control,就像一个按钮,当有人点击它,就会调用MKMapViewDelegate的方法:
- (void)mapView:(MKMapView *)sender
annotationView:(MKAnnotationView *)aView
calloutAccessoryControlTapped:(UIControl *)
因此这样就不用再建target action,这是一个callout view内部的按钮。不要把这个方法和didSelectAnnotationView弄混了,这是点击在callout里的按钮上,而后者是点击在pin上。
通常直到didSelectAnnotationView发生了,才显示callout里的左右测:
- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView {
if ([aView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {
UIImageView *imageView = (UIImageView *)aView.leftCalloutAccessoryV
imageView.image=...; //if you do this in a GCD queue,be careful,views are reused!
不希望在viewForAnnotation里加载所有callout的图片,要在didSelectAnnotationView里才加载。如果正在使用GCD加载Flickr的图像的缩略图,用了另一个线程,线程返回时要小心,因为pins是被重用的。pins可能在某个地方被点击了,然后用户滚动到其他地方了,当Flickr的东西下载回来的时候,所选择的annotation view可能早就不在了,所以返回的时候得做一些检查,当Flickr的图像回来的时候得确保界面还是原来的样子。所以要做个测试,以确保在写image=之前一切仍然是老样子。
配置display type:用MKMapType mapType来指定显示卫星模式或街道模式和卫星模式的混合体。还可以用一个特殊的pin显示用户当前的位置,也可以在地图上缩放和滚动:
@property MKMapType mapT
@property BOOL showsUserL
@property (readonly) BOOL isUserLocationV
@property (readonly) MKUserLocation *userL
@property BOOL zoomE
@property BOOL scrollE
可以通过设置MapView的region property来控制显示的区域,它只是个CLLocationCoordinate2D,这是经度、纬度和一个跨度,span(跨度)就是纬度上有多远,center就是其中心,region有一定的跨度。当你设置了region,地图将可以滚动和放大显示该区域,也可以只设置中心点,这样就只能滚动不能缩放。
@property MKCoordinateR
typedef struct {
CLLocationCoordinate2D
MKCoordinateS
} MKCoordinateR
typedef struct {
CLLocationDegrees latitudeD
CLLocationDegrees longitudeD
- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL) // animate
开始加载地图时,delegate会得到通知。记住,整个世界、卫星图像都不在手机上,所以当你左右滚动,它从Google Map上下载地图信息,因此它是一块一块显示的。这将告诉你什么时候开始向网络获取更多,和何时它完成加载。
Remember that the maps are downloaded from Google earth.
- (void)mapViewWillStartLoadingMap:(MKMapView *)
- (void)mapViewDidFinishLoadingMap:(MKMapView *)
- (void)mapViewDidFailLoadingMap:(MKMapView *)sender withError:(NSError *)
它和annotations非常相似,不同的地方只是绘制图像、点击一下,可以绘制Overlays。通常情况下,Overlays更大,它们不是在一个点上,它们将是Overlays的重叠,你要实际绘制它。
设置Overlays的方法和annotations一样:
- (void)addOverlay:(id &MKOverlay&)
// also addOverlays:(NSArray *)
- (void)removeOverlay:(id&MKOverlay&) //alsoremoveOverlays:(NSArray*)
也有和cellForRowAtIndexPath或viewForAnnotation相同的机制:
- (MKOverlayView *)mapView:(MKMapView *)sender
viewForOverlay:(id &MKOverlay&)
MKOverlayView基本上就是实现了类似drawRect的东西,它不叫drawRect,而是:
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)
不调用UIGraphics获得context,它给你一个context来做CoreGraphics的绘制。
要用上次的shutterbug,把它加入Spli View,details一侧是master里对应项的地图。
从对象库中拖出一个Spli View,并删除它的master,用control+drag的方式指定新的master。重新创建一个UIViewController的子类叫MapViewController,设置detail的类为MapViewController,再对象库中拖一个Map View到detail中,然后为mapView创建一个outlet到MapViewController,这时会出现一个红色的error,这是因为MKMapView所属的framework还没有链接到这个app。那么要怎么解决呢?回到project
navigator,点击project,再点击target,然后去到build phases,可以看到link binary with libraries,这就是添加framework的地方,选择MapKit.framework和CoreLocation.framework。回到MapViewController,#import &MapKit/MapKit.h&,红色的error就会消失。
在MapViewController.h文件中创建一个model,是annotations数组,最终是要把这些东西传递给Map View。但因为Map View不是public的,所以需要有一些公共的API。
对FlickrPhotoTableViewController.m文件添加了以下一些代码:
- (NSArray *)mapAnnotations
NSMutableArray *annotations = [NSMutableArray arrayWithCapacity:[self.photos count]];
for (NSDictionary *photo in self.photos) {
[annotations addObject:[FlickrPhotoAnnotation annotationForPhoto:photo]];
- (void)updateSplitViewDetail
id detail = [self.splitViewController.viewControllers lastObject];
if ([detail isKindOfClass:[MapViewController class]]) {
MapViewController *mapVC = (MapViewController *)
mapVC.delegate =
mapVC.annotations = [self mapAnnotations];
- (void)setPhotos:(NSArray *)photos
if (_photos != photos) {
[self updateSplitViewDetail];
// Model changed, so update our View (the table)
if (self.tableView.window) [self.tableView reloadData];
创建一个实现了MKAnnotation protocol的NSOject的子类,将其命名为FlickrPhotoAnnotation,FlickrPhotoAnnotation.h文件代码如下:
#import &Foundation/Foundation.h&
#import &MapKit/MapKit.h&
@interface FlickrPhotoAnnotation : NSObject &MKAnnotation&
+ (FlickrPhotoAnnotation *)annotationForPhoto:(NSDictionary *) // Flickr photo dictionary
@property (nonatomic, strong) NSDictionary *
FlickrPhotoAnnotation.m文件代码:
#import "FlickrPhotoAnnotation.h"
#import "FlickrFetcher.h"
@implementation FlickrPhotoAnnotation
@synthesize photo = _
+ (FlickrPhotoAnnotation *)annotationForPhoto:(NSDictionary *)photo
FlickrPhotoAnnotation *annotation = [[FlickrPhotoAnnotation alloc] init];
annotation.photo =
#pragma mark - MKAnnotation
- (NSString *)title
return [self.photo objectForKey:FLICKR_PHOTO_TITLE];
- (NSString *)subtitle
return [self.photo valueForKeyPath:FLICKR_PHOTO_DESCRIPTION];
- (CLLocationCoordinate2D)coordinate
CLLocationCoordinate2D
coordinate.latitude = [[self.photo objectForKey:FLICKR_LATITUDE] doubleValue];
coordinate.longitude = [[self.photo objectForKey:FLICKR_LONGITUDE] doubleValue];
当你有一个通用类,想让它从另一个类获取数据的时候,你要怎么做?子类或delegation。
MapViewController.h文件代码:
#import &UIKit/UIKit.h&
#import &MapKit/MapKit.h&
@class MapViewC
@protocol MapViewControllerDelegate &NSObject&
- (UIImage *)mapViewController:(MapViewController *)sender imageForAnnotation:(id &MKAnnotation&)
@interface MapViewController : UIViewController
@property (nonatomic, strong) NSArray * // of id &MKAnnotation&
@property (nonatomic, weak) id &MapViewControllerDelegate& delegate;
MapViewController.m文件代码:
#import "MapViewController.h"
@interface MapViewController() &MKMapViewDelegate&
@property (weak, nonatomic) IBOutlet MKMapView *mapV
@implementation MapViewController
@synthesize mapView = _mapV
@synthesize annotations = _
@synthesize delegate = _
#pragma mark - Synchronize Model and View
- (void)updateMapView
if (self.mapView.annotations) [self.mapView removeAnnotations:self.mapView.annotations];
if (self.annotations) [self.mapView addAnnotations:self.annotations];
- (void)setMapView:(MKMapView *)mapView
_mapView = mapV
[self updateMapView];
- (void)setAnnotations:(NSArray *)annotations
_annotations =
[self updateMapView];
#pragma mark - MKMapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id&MKAnnotation&)annotation
MKAnnotationView *aView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"MapVC"];
if (!aView) {
aView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"MapVC"];
aView.canShowCallout = YES;
aView.leftCalloutAccessoryView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
// could put a rightCalloutAccessoryView here
aView.annotation =
[(UIImageView *)aView.leftCalloutAccessoryView setImage:nil];
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)aView
UIImage *image = [self.delegate mapViewController:self imageForAnnotation:aView.annotation];
[(UIImageView *)aView.leftCalloutAccessoryView setImage:image];
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
NSLog(@"callout accessory tapped for annotation %@", [view.annotation title]);
#pragma mark - View Controller Lifecycle
- (void)viewDidLoad
[super viewDidLoad];
self.mapView.delegate =
- (void)viewDidUnload
[self setMapView:nil];
[super viewDidUnload];
#pragma mark - Autorotation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
return YES;
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 微信位置导航添加高德 的文章

 

随机推荐