关于定位的功能,开发,很早之前就有做过百度的定位功能。起初是有想法把百度的Loc V3.2的定位SDK整合进来用。但是终归是想法,但是知道昨天,我问技术群,里面的一位朋友就说起了百度地位SDK整合进来的实现方法。顿时,我就思考了一会,随后就是很激动地操作起来。根据朋友给的一个demo。做了两天,终于算是真正将功能实现了。至于界面的美观或者样式的显示这个就偷懒掉了。
http://developer.baidu.com/map/sdk-android.htm
这个是百度的SDK。帮助文档。
第一次看这个定位的实现的时候,觉得按步骤来就可以实现,把该设置的参数设置好就行了。其实,的确就行了。很简单!
我根据demo,也用了V2.2.1的版本的百度定位。我会把工程发在我的资源里面。有需要自行下载。这里讲些重点错误的地方。
1.构建路径(Build Path),如何把LocV2.2.1.jar导入Android Dependencies内呢?
在ADT17之前,如果要在Android项目中引入外部JAR包,只需在项目属性的Java Build Path中选择Add External JARs,然后选择相应JAR包即可。但是,在升级到ADT17之后,Android项目下多出了一个Android Dependencies目录,之前通过Add External JARs加入的jar包依然出现在Referenced Libraries目录之下,但是似乎已经被弃用,虽然没有提示任何错误,但是在运行时会抛出ClassNotFoundException。解决方法是将JAR包加入到Android Dependencies下,其中一个默认引入目录是libs,因此只要将JAR包复制该目录下。
所以,记得新建一个ArcGIS工程后,要记得导入LocV2.2.1.jar包。
2.配置清单里面一定需要添加百度定位的services:
<service android:name="com.baidu.location.f" android:enabled="true" android:permission="android.permission.BAIDU_LOCATION_SERVICE" android:process=":remote" > <intent-filter> <action android:name="com.baidu.location.service_v2.2" > </action> </intent-filter> </service>
<permission android:name="android.permission.BAIDU_LOCATION_SERVICE" > </permission> <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" > </uses-permission> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" > </uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" > </uses-permission> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" > </uses-permission> <uses-permission android:name="android.permission.READ_PHONE_STATE" > </uses-permission> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" > </uses-permission> <uses-permission android:name="android.permission.READ_LOGS" > </uses-permission>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" tools:context=".QueryTaskkkkkkActivity" > <com.esri.android.map.MapView android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" initExtent="1.2757645697558502E7 2576233.422813467 1.3480434236922514E7 3307582.9093442294" > </com.esri.android.map.MapView> <Button android:id="@+id/location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="定位" /> </RelativeLayout>
package com.esri.arcgis.query; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.esri.android.map.GraphicsLayer; import com.esri.android.map.MapView; import com.esri.android.map.ags.ArcGISTiledMapServiceLayer; import com.esri.android.map.event.OnLongPressListener; import com.esri.core.geometry.GeometryEngine; import com.esri.core.geometry.Point; import com.esri.core.geometry.Polygon; import com.esri.core.geometry.SpatialReference; import com.esri.core.map.Graphic; import com.esri.core.symbol.PictureMarkerSymbol; import com.esri.core.symbol.SimpleFillSymbol; import com.esri.core.symbol.SimpleLineSymbol; public class QueryTaskkkkkkActivity extends Activity { MapView mMapView; GraphicsLayer glLayer = null; Graphic gp = null; Button location; LocationClient locationClient = null; String TAG = null; MyLocationListenner myListener = new MyLocationListenner(); PictureMarkerSymbol locationPH; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mMapView = (MapView) findViewById(R.id.map); String url = "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"; ArcGISTiledMapServiceLayer tl = new ArcGISTiledMapServiceLayer(url); mMapView.addLayer(tl); glLayer = new GraphicsLayer(); mMapView.addLayer(glLayer); mMapView.setEsriLogoVisible(true); // 启动百度定位 locationClient = new LocationClient(this); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); option.setCoorType("gpj02");// 返回国测局经纬度坐标系 coor=gcj02 option.setProdName("定位Test"); option.setScanSpan(10000); option.setPriority(LocationClientOption.GpsFirst);// GPS定位优先 locationClient.setLocOption(option); locationClient.registerLocationListener(myListener);// 发起定位,异步获取当前位置。 mMapView.setOnLongPressListener(new OnLongPressListener() { private static final long serialVersionUID = 1L; @Override public void onLongPress(float x, float y) { // TODO Auto-generated method stub Point pt = mMapView.toMapPoint(x, y); Log.i(TAG, "" + pt.getX()); Log.i(TAG, "" + pt.getY()); } }); // 定位 location = (Button) findViewById(R.id.location); location.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if (locationClient == null) return; if (locationClient.isStarted()) { locationClient.stop(); location.setText("开启定位"); } else { locationClient.start(); location.setText("停止定位"); } } }); } public class MyLocationListenner implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { // TODO Auto-generated method stub if (location != null) { // 显示定位的结果 ShowLocation(location); } return; } } public void ShowLocation(BDLocation bdLocation) { // double locx = bdLocation.getLatitude();// 获得纬度 // double locy = bdLocation.getLongitude();// 获得经度 // Point wgsPoint = new Point(locx, locy); // Point rs4326 = (Point) GeometryEngine.project(wgsPoint, // SpatialReference.create(4326), mMapView.getSpatialReference()); // glLayer.removeAll();//这句话放在这个位置才是正确的啊!笨蛋 // gp = new Graphic(rs4326, locationPH); // glLayer = new GraphicsLayer();// init // glLayer.addGraphic(gp); // mMapView.addLayer(glLayer); // mMapView.centerAt(rs4326, true); // if (bdLocation.getLocType() == 61) { // Log.i(TAG, "GPS实现定位!"); // } PictureMarkerSymbol locationPH = new PictureMarkerSymbol( QueryTaskkkkkkActivity.this.getResources().getDrawable( R.drawable.location32)); double locy = bdLocation.getLatitude(); double locx = bdLocation.getLongitude(); Point wgspoint = new Point(locx, locy); Point mapPoint = (Point) GeometryEngine.project(wgspoint, SpatialReference.create(4326), mMapView.getSpatialReference()); // Polygon pg = GeometryEngine.buffer(wgspoint, // mMapView.getSpatialReference(), 0.11, null); // SimpleFillSymbol sfs = new SimpleFillSymbol(Color.BLACK); // sfs.setOutline(new SimpleLineSymbol(Color.RED, 1)); // sfs.setAlpha(0); glLayer.removeAll(); glLayer.addGraphic(new Graphic(mapPoint, locationPH)); // glLayer.addGraphic(new Graphic(pg, sfs)); mMapView.centerAt(mapPoint, true);// 漫游到当前位置 mMapView.addLayer(glLayer); if (bdLocation.getLocType() == BDLocation.TypeGpsLocation) { Log.v("locationType", "Gps"); } } @Override protected void onDestroy() { if (locationClient != null && locationClient.isStarted()) { locationClient.stop(); locationClient = null; } super.onDestroy(); } @Override protected void onPause() { super.onPause(); mMapView.pause(); } @Override protected void onResume() { super.onResume(); mMapView.unpause(); } }
接下来讲解一下其中的一些细节:
a.启动百度定位。
// 启动百度定位 locationClient = new LocationClient(this); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); option.setCoorType("gpj02");// 返回国测局经纬度坐标系 coor=gcj02 option.setProdName("定位Test"); option.setScanSpan(10000); option.setPriority(LocationClientOption.GpsFirst);// GPS定位优先 locationClient.setLocOption(option); locationClient.registerLocationListener(myListener);// 发起定位,异步获取当前位置。
就是,最后两句代码,要记得注意下,设置了那么多的参数,开心得半死,忘记了引用到软件上的话,那就只能郁闷了。选择异步操作,自然是有好处的啦,但是如果GPS和网络那会信号不好,软件会出现类似假死状态哦,为啥,异步在后面操作运算,自然前端就没有任何反应,建议大家做个进度条,增加和谐感!
b.接下来说个让我痛恨自己的地方,显示定位结果:
// double locx = bdLocation.getLatitude();// 获得纬度 // double locy = bdLocation.getLongitude();// 获得经度 // Point wgsPoint = new Point(locx, locy); // Point rs4326 = (Point) GeometryEngine.project(wgsPoint, // SpatialReference.create(4326), mMapView.getSpatialReference()); // glLayer.removeAll();//这句话放在这个位置才是正确的啊!笨蛋 // gp = new Graphic(rs4326, locationPH); // glLayer = new GraphicsLayer();// init // glLayer.addGraphic(gp); // mMapView.addLayer(glLayer); // mMapView.centerAt(rs4326, true); // if (bdLocation.getLocType() == 61) { // Log.i(TAG, "GPS实现定位!"); // } PictureMarkerSymbol locationPH = new PictureMarkerSymbol( QueryTaskkkkkkActivity.this.getResources().getDrawable( R.drawable.location32)); double locy = bdLocation.getLatitude(); double locx = bdLocation.getLongitude(); Point wgspoint = new Point(locx, locy); Point mapPoint = (Point) GeometryEngine.project(wgspoint, SpatialReference.create(4326), mMapView.getSpatialReference()); // Polygon pg = GeometryEngine.buffer(wgspoint, // mMapView.getSpatialReference(), 0.11, null); // SimpleFillSymbol sfs = new SimpleFillSymbol(Color.BLACK); // sfs.setOutline(new SimpleLineSymbol(Color.RED, 1)); // sfs.setAlpha(0); glLayer.removeAll(); glLayer.addGraphic(new Graphic(mapPoint, locationPH)); // glLayer.addGraphic(new Graphic(pg, sfs)); mMapView.centerAt(mapPoint, true);// 漫游到当前位置 mMapView.addLayer(glLayer); if (bdLocation.getLocType() == BDLocation.TypeGpsLocation) { Log.v("locationType", "Gps"); }
6.实现了定位,也成功定位了。突然有个想法,想实现以定位点为圆心向四周动画滴发散的动画效果的实现。首先我会想到去自定义一个动画,然后实现。这个理论上是肯定可行的。可是我是小白,哪里有那么高超技术呢?于是领导给了个到现在还觉得很棒的思路,可以去找一下有没有这样子动画的gif图片,然后用图片符号集把它添加进去,不是就OK了,而且还简单得要死。领导就是领导,想法都这么牛X!
综上所述:实现ArcGIS的定位功能其实是很简单的事情。不信你就研究下我说的,还有我的工程文件。“定位功能的实现.rar”