Android开发教程:NextBus之显示实时车辆位置信息
要实现的功能如下:首先点击menu会显示两条路线(仅仅做简单的模拟),点击路线之后去下载本条路线实时的车辆信息,并且画在地图上。点击另外一条路线的时候也执行以上操作,并且把原来的图像擦除。
好,我们首先新建一个工程TestActivity,继承与MapActivity,同时在layout的main.xml文件中加上mapview控件
- <com.google.Android.maps.MapView
- android:clickable="true"
- android:layout_width="fill_parent"
- android:id="@+id/mapView"
- android:layout_height="fill_parent"
- android:apiKey="0GPDZeAXmGQ3vHfDbNitJWUp-lghBsV8jouMc5g"
- ></com.google.android.maps.MapView>
还有哦,不要忘记在androidmanifest中添加上<uses-library android:name="com.google.android.maps" />,至于权限什么的,多加几条就多加几条吧
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
- <uses-permission android:name="android.permission.READ_LOGS"></uses-permission>
好,到此为止,至少打开我们新建的工程能够正常的显示google地图了。
接下来,变量初始化一下
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.setStreetView(true);
- mapView.setBuiltInZoomControls(true);
- mapOverlays = mapView.getOverlays();
- myloctionController=mapView.getController();
然后模拟个两条路线吧,在menu里面menu.add(0,0,0,"choose a route");在这个选项的点击响应中添加个函数showroutelist(),routestrings里面当然是放两条路线咯
- private void showRouteList() {
- // TODO Auto-generated method stub
- final ArrayList<String> routeStrings=new ArrayList<String>();
- routeStrings.add("1");
- routeStrings.add("10");
- ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, R.layout.item, R.id.textViewId, routeStrings);
- AlertDialog.Builder builder=new AlertDialog.Builder(this);
- builder.setTitle("当前两条路线");
- builder.setAdapter(adapter, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // TODO Auto-generated method stub
- achieveAllDirection(routeStrings.get(which));
- }
- });
- builder.show();
- }
这里得到了我们点击的路线的名称,根据路线名称我们可以下载到路线上所有车子的实时信息,下过来存在一个string中,然后把这个string拿来解析,将获得的数据放在ArrayList<VehicleLocationsData> vehicleLocationsData中把,VehicleLocationsData有多个数据成员,包括汽车的朝向,速度,经纬度等等。
- private void achieveAllDirection(String RouteName) {
- String path="http://webservices.nextbus.com/service/publicXMLFeed?command=vehicleLocations&a=mbta&r="+RouteName+"&t=0";
- HttpDownloader hd = new HttpDownloader();//下载实时信息
- String resultStr = hd.download(path);
- //System.out.println(resultStr);
- try{
- SAXParserFactory factory = SAXParserFactory.newInstance(); XMLReader reader = factory.newSAXParser().getXMLReader();
- VehicleLocationsPrase vehicleLocationsPrase=new VehicleLocationsPrase();
- reader.setContentHandler(vehicleLocationsPrase);
- //开始解析文件
- reader.parse(new InputSource(new StringReader(resultStr)));
- ArrayList<VehicleLocationsData> temp=vehicleLocationsPrase.getVehicleLocationsDatas();
- System.out.println(temp.size());
- if (temp.size()==0) {
- Toast.makeText(mapView.getContext(), "这辆车在这个方向上目前没有实时信息", Toast.LENGTH_LONG );
- }
- else {
- //下载解析好之后开始画图
- afterClickBusOnRoute(temp);
- }
- }
- catch(Exception e){
- e.printStackTrace();
- }
- }
解析之后我们得到了此刻汽车的朝向,经纬度等等信息就能画出车子在路上的位置了。画图的操作是这样的,首先我们要获得两个原始的图像,一个车的图像,一个箭头的图像,因为箭头是要变化的,我们先定义一个矩阵的,然后每次画一个车,就按照保存着的车辆朝向信息来把原始的箭头进行旋转,并且生成一副新的图像。然后把新的箭头位图添加到车辆位图的上面,产生叠加的效果。这里所有的车是一个图层,而每个箭头是单独的一个图层,因为每个图层的图像是要一样的嘛。接下来吧N+1个图层都添加到mapview中就可以了,添加之前记得把原来的先擦除,
- private void afterClickBusOnRoute(ArrayList<VehicleLocationsData> vehicleLocationsData) {
- Drawable routeDrawable=getResources().getDrawable(R.drawable.bus);//显示公交路线的图标
- Bitmap bitmap=BitmapFactory.decodeResource(this.getResources(),R.drawable.arrow);//获得位图
- int w = bitmap.getWidth();// 获得位图宽
- int h = bitmap.getHeight();// 获得位图高
- Matrix matrix = new Matrix();
- final MyOverlay Route_Overlay=new MyOverlay(routeDrawable, this);
- int lat=0,lon=0;
- float a;
- ArrayList<MyOverlay> allArrow=new ArrayList<MyOverlay>();
- for (int i = 0; i < vehicleLocationsData.size(); i++)
- {
- //System.out.println(vehicleLocationsData.get(i).toString());
- //获得应该旋转的角度
- a=Float.valueOf(vehicleLocationsData.get(i).getHeading());
- matrix.setRotate(a);//利用矩阵旋转
- Bitmap bm2 = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
- //获得Drawable对象
- BitmapDrawable bd= new BitmapDrawable(getResources(), bm2);
- lat=(int)(Double.parseDouble(vehicleLocationsData.get(i).getLat())*1000000);
- lon=(int)(Double.parseDouble(vehicleLocationsData.get(i).getLon())*1000000);
- GeoPoint point=new GeoPoint(lat,lon);
- MyOverlay arrow_Overlay=new MyOverlay(bd,this);
- OverlayItem overlayitem = new OverlayItem(point, vehicleLocationsData.get(i).getRouteTag(),
- vehicleLocationsData.get(i).getDirTag()+vehicleLocationsData.get(i).getHeading()+
- vehicleLocationsData.get(i).getHeading());
- Route_Overlay.addOverlay(overlayitem);
- arrow_Overlay.addOverlay(overlayitem);
- allArrow.add(arrow_Overlay);
- }
- mapOverlays.clear();
- mapOverlays=mapView.getOverlays();
- mapOverlays.add(Route_Overlay);
- //注意图层放置的顺序,先放的在下面
- for (int i = 0; i < allArrow.size(); i++) {
- mapOverlays.add(allArrow.get(i));
- }
- GeoPoint lastpPoint=new GeoPoint(lat, lon );
- myloctionController.animateTo(lastpPoint);
- myloctionController.setZoom(13);
- myloctionController.setCenter(lastpPoint);
- //mapView.invalidate();
- }
这样就能正常显示车辆的实时路线了。这个里面的MyOverlay是继承与 ItemizedOverlay<OverlayItem>的咯,这个类中继承了一些方法, 其中这个onTap方法就是点击了图标以后会执行的方法。
这个例子中的解析就不具体说了,毕竟每个网页对应的内容都不一样嘛。