1.获取当前地理位置:
Android中提供了一个LocationManager的类,用于管理地理位置。不能通过构造函数获取该类的实例,而是通过Context的getSystemService():
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
该类中有几个比较常用的方法:
getLastKnownLocation(String provider)用于根据传入的provider获取一个Location对象,该对象存储了地理位置信息,包括经度、纬度、海拔、速度等。provider指明采用何种方式获取地理位置信息,在LocationManager中定义了几个字符串常量,用于指定地理位置信息的提供者:
NETWORK_PROVIDER:采用网络的方式获取
GPS_PROVIDER:采用GPS获取
PASSIVE_PROVIDER:被动定位方式,当其他应用使用定位更新了定位信息,系统会保存下来,该应用接收到消息后直接读取就可以了
注意:在使用真机测试时,一定要走到室外。因为常用的定位方式是GPS或者NETWORK,但是在室内这两个基本没起作用,我刚开始还以为是代码的问题,后来走出去测试才发现代码没有问题。
获取地理位置信息之前,最好先查看下手机支持哪些定位方式,哪些是可用的,然后再选择一个可用的来定位:
getAllProviders()返回所有的地理位置提供者的所有字符串描述
getBestProvider()根据传入的评判准则,返回一个最佳的地理位置提供者的字符串描述,第二个参数设置为true,则返回所有可用中的最佳的;若为false则返回最佳的,不管是否可用。
getProviders()返回地理位置提供者的字符串描述,参数为true,则返回所有的可用的描述,false则返回所有的。
getProviders()根据传入的评判准则,及第二个参数标识是否可用,来返回地理位置提供者的字符串描述。
1 List<String> providers = lm.getProviders(true); 2 3 for(int i=0; i<providers.size();i++){ 4 5 System.out.println(providers.get(i)); 6 7 }
当前是GPS和PASSIVE方式可用:
1 List<String> providers = lm.getProviders(true); 2 3 String lp = null; 4 5 if(providers.contains(LocationManager.GPS_PROVIDER)){ 6 7 lp = LocationManager.GPS_PROVIDER; 8 9 }else if(providers.contains(LocationManager.NETWORK_PROVIDER)){ 10 11 lp = LocationManager.NETWORK_PROVIDER; 12 13 }else{ 14 15 Toast.makeText(this, "当前没有获取地理位置的方式可用,请打开GPS", Toast.LENGTH_LONG).show(); 16 17 return; 18 19 } 20 21 Location loc = lm.getLastKnownLocation(lp);
获取了Location实例,就可以从中获取关心的地理信息了:
getLatitude():获取纬度信息,单位度
getLongitude():获取经度信息,单位度
getAltitude():获取海拔信息,单位米
getSpeed():获取速度信息,单位米/秒
getTime():获取时间信息,返回从1970.1.1到现在的毫秒数。
如:
Toast.makeText(MainActivity.this, "纬度:"+location.getLatitude() +",经度:"+location.getLongitude()+",速度:"+location.getSpeed()+"m/s," +"海拔:"+location.getAltitude()+"米", 0).show();
以上,只能获取一次地理位置信息,如何动态实时地获取地理位置信息呢?
这就要用到LocationManager的requestLocationUpdates()方法:
该方法有多重重载形式,这里只简单试用下这种重载形式,参数说明:
provider:指定获取地理位置的方式;
minTime:指定监听位置变化的时间间隔,单位毫秒;
minDistance:指定监听位置变化的最小距离间隔,单位米;
listener:指定监听器,设置不同事件的回调处理。
注意:注册了监听器之后,但应用退出时,应当将注册的监听器移除,可以选择在Activity的onDestroy()方法中,调用LocationManager的removeUpdates(listener)方法,来将requestLocationUpdates()注册的事件监听移除。
如:
1 listener = new LocationListener() { 2 3 4 5 @Override 6 7 public void onStatusChanged(String provider, int status, Bundle extras) { 8 9 // TODO Auto-generated method stub 10 11 Toast.makeText(MainActivity.this, "onStatusChanged", 0).show(); 12 13 } 14 15 16 17 @Override 18 19 public void onProviderEnabled(String provider) { 20 21 // TODO Auto-generated method stub 22 23 Toast.makeText(MainActivity.this, "onProviderEnabled", 0).show(); 24 25 } 26 27 28 29 @Override 30 31 public void onProviderDisabled(String provider) { 32 33 // TODO Auto-generated method stub 34 35 Toast.makeText(MainActivity.this, "onProviderDisabled", 0).show(); 36 37 } 38 39 40 41 @Override 42 43 public void onLocationChanged(Location location) { 44 45 // TODO Auto-generated method stub 46 47 tv_lat.setText(location.getLatitude()+""); 48 49 tv_lng.setText(location.getLongitude()+""); 50 51 Toast.makeText(MainActivity.this, "纬度:"+location.getLatitude() 52 53 +",经度:"+location.getLongitude()+",速度:"+location.getSpeed()+"m/s," 54 55 +"海拔:"+location.getAltitude()+"米", 0).show(); 56 57 } 58 59 }; 60 61 lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 1, listener);
每隔5秒监测下位置的变化情况,一旦距离变化超过1米,就会回调onLocationChanged()方法,并将新的Location实例作为参数传入该方法。
以上,就是简单的获取地理位置的方法,帮助文档中关于LocationManager还有其他一些可能也会用到的方法,如临近警告,测距等,在用到的时候可以再查阅。
2.百度地图控制器的简单使用,设置地图的旋转,缩放,及视角变化:
跟2.x版本不同,之前在控制器中直接就可以调用各个方法进行旋转、缩放等操作,新版的控制器类名为BaiduMap,这里要用到的是它的animateMapStatus()方法:
所有要执行的旋转、缩放等动作没有直接对应的方法,而是把这些地图状态变化的动作封装到MapStatusUpdate对象中,然后传递给BaiduMap的animateMapStatus()以动画的方式执行动作。
所以,这里的关键是获取MapStatusUpdate对象,封装要执行的动作。
但是,查看帮助文档中,MapStatusUpdate类没有任何实际的帮助信息……
但是,有几个相关的类:MapStatus、MapStatus.Builder、MapStatusUpdateFactory。
首先看MapStatus:
有这么几个字段,用于存放地图状态信息,注意文档中说明zoom的取值范围为3-20,overlook的取值是-45-0。但是没有对应的设置方法,所以猜测应该在其内部类Builder中存在相关设置方法
MapStatus.Builder:
构造方法,第二个带参的构造应该会比较有用,要进行地图状态变化,肯定要有一个参照,是在当前状态基础之上进行旋转缩放等。
build()方法返回一个MapStatus对象,如同之前常用到的android中的Builder内部类一样,在进行完一连串的设置之后,最后调用该方法得到一个需要的MapStatus对象。
overlook()方法,设置地图视角,传入一个-45~0的float值
rotate()方法,设置逆时针旋转角度
target()方法,设置地图中心店
targetScreen()方法设置地图中心点在屏幕的坐标
zoom()方法,设置地图的缩放级别。
通过MapStatus.Builder就能获取一个MapStatus对象了,但是需要的却是MapStausUpdate对象。
继续看下一个类:
MapStatusUpdateFactory类:
MapStatusUpdate的工厂类,通过它可以获取到需要的MapStatusUpdate对象:
newMapStatus()方法,可以根据传入的MapStatus获取一个MapStatusUpdate对象;
zoomIn()方法:返回一个放大地图缩放级别的MapStatusUpdate对象
zoomOut()方法:返回一个缩小地图缩放级别的MapStatusUpdate对象
zoomTo()方法:返回一个到指定缩放级别的MapStatusUpdate对象
下面根据这几个类,试着进行地图的旋转、缩放、设置中心点及视角变化:
1)设置缩放级别:
修改布局文件,在MapView下方添加几个控件,用于控制地图缩放:
1 <LinearLayout 2 3 android:orientation="horizontal" 4 5 android:layout_width="match_parent" 6 7 android:layout_height="wrap_content" 8 9 > 10 11 <EditText 12 13 android:id="@+id/et_level" 14 15 android:layout_height="wrap_content" 16 17 android:layout_width="0dp" 18 19 android:layout_weight="1" 20 21 android:inputType="number" 22 23 android:hint="@string/et_hint" 24 25 /> 26 27 <Button 28 29 android:id="@+id/btn_set" 30 31 android:layout_height="wrap_content" 32 33 android:layout_width="0dp" 34 35 android:layout_weight="1" 36 37 android:onClick="zoomTo" 38 39 android:text="@string/btn_set_text" 40 41 /> 42 43 <Button 44 45 android:id="@+id/btn_in" 46 47 android:layout_height="wrap_content" 48 49 android:layout_width="0dp" 50 51 android:layout_weight="1" 52 53 android:onClick="zoomIn" 54 55 android:text="@string/btn_text_in"/> 56 57 <Button 58 59 android:id="@+id/btn_out" 60 61 android:layout_height="wrap_content" 62 63 android:layout_width="0dp" 64 65 android:layout_weight="1" 66 67 android:onClick="zoomOut" 68 69 android:text="@string/btn_out_text" 70 71 /> 72 73 </LinearLayout>
修改MainActivity.java添加按钮回调方法:
1 public class MainActivity extends Activity { 2 3 private static final String TAG = "MainActivity"; 4 5 private EditText et_level; 6 7 private Button btn_set, btn_in, btn_out; 8 9 private MapView mv; 10 11 private BaiduMap map; 12 13 @Override 14 15 protected void onCreate(Bundle savedInstanceState) { 16 17 super.onCreate(savedInstanceState); 18 19 SDKInitializer.initialize(getApplicationContext()); 20 21 setContentView(R.layout.activity_main); 22 23 mv = (MapView) findViewById(R.id.mv); 24 25 et_level = (EditText) findViewById(R.id.et_level); 26 27 map.setOnMapLoadedCallback(new OnMapLoadedCallback() { 28 29 @Override 30 31 public void onMapLoaded() { 32 33 mv.setScaleControlPosition(new Point(20,20)); 34 35 mv.setZoomControlsPosition(new Point(150,50)); 36 37 } 38 39 }); 40 41 } 42 43 public void zoomTo(View view){ 44 45 try { 46 47 String s_level = et_level.getText().toString(); 48 49 float level = Float.parseFloat(s_level); 50 51 MapStatusUpdate zt = MapStatusUpdateFactory.zoomTo(level); 52 53 map.animateMapStatus(zt); 54 55 } catch (NumberFormatException e) { 56 57 Toast.makeText(this, "请输入正确的缩放级别", Toast.LENGTH_SHORT).show(); 58 59 } 60 61 } 62 63 public void zoomIn(View view){ 64 65 MapStatusUpdate zi = MapStatusUpdateFactory.zoomIn(); 66 67 map.animateMapStatus(zi); 68 69 } 70 71 public void zoomOut(View view){ 72 73 MapStatusUpdate zo = MapStatusUpdateFactory.zoomOut(); 74 75 map.animateMapStatus(zo); 76 77 } 78 79 @Override 80 81 protected void onResume() { 82 83 // TODO Auto-generated method stub 84 85 super.onResume(); 86 87 mv.onResume(); 88 89 } 90 91 @Override 92 93 protected void onPause() { 94 95 // TODO Auto-generated method stub 96 97 super.onPause(); 98 99 mv.onPause(); 100 101 } 102 103 @Override 104 105 protected void onDestroy() { 106 107 // TODO Auto-generated method stub 108 109 super.onDestroy(); 110 111 mv.onDestroy(); 112 113 } 114 115 }
运行效果:
2)设置地图中心点:
map.animateMapStatus(MapStatusUpdateFactory.newLatLng(new LatLng(30.757, 103.9339)));
运行结果:
3)旋转地图:
修改布局文件,添加一个旋转按钮:
1 <Button 2 3 android:id="@+id/btn_rot" 4 5 android:layout_width="0dp" 6 7 android:layout_height="wrap_content" 8 9 android:layout_weight="1" 10 11 android:onClick="rotate" 12 13 android:text="@string/btn_rot_text" 14 15 />
修改MainActivity.java,添加旋转按钮的回调:
1 public void rotate(View view){ 2 3 float r = map.getMapStatus().rotate; 4 5 MapStatus ms = new MapStatus.Builder(map.getMapStatus()).rotate(r+30).build(); 6 7 map.animateMapStatus(MapStatusUpdateFactory.newMapStatus(ms)); 8 9 }
运行结果:
4)设置视角:
修改布局文件:
1 <Button 2 3 android:id="@+id/btn_up" 4 5 android:layout_height="wrap_content" 6 7 android:layout_width="0dp" 8 9 android:layout_weight="1" 10 11 android:onClick="overlook" 12 13 android:text="@string/btn_up_text"/> 14 15 <Button 16 17 android:id="@+id/btn_down" 18 19 android:layout_height="wrap_content" 20 21 android:layout_width="0dp" 22 23 android:layout_weight="1" 24 25 android:onClick="overlook" 26 27 android:text="@string/btn_down_text" 28 29 />
修改MainActivity.java:添加修改视角的按钮的回调:
1 public void overlook(View view){ 2 3 float f = map.getMapStatus().overlook; 4 5 MapStatus ms = null; 6 7 if(view.getId() == R.id.btn_up){ 8 9 ms = new MapStatus.Builder(map.getMapStatus()).overlook(f+10).build(); 10 11 }else{ 12 13 ms = new MapStatus.Builder(map.getMapStatus()).overlook(f-10).build(); 14 15 } 16 17 map.animateMapStatus(MapStatusUpdateFactory.newMapStatus(ms)); 18 19 }
运行结果: