ArcGIS for Android 之定位功能开发

关于定位的功能,开发,很早之前就有做过百度的定位功能。起初是有想法把百度的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>

3.有了服务没有权限,我想您也觉得不行。所以我就来了一个大手笔:

 <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>

4.于是清单文件是没有问题滴啦,那么还有什么不是重点的周边问题要解决呢?right!布局文件嘛!很简单,加个button:

<?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>

5.接下来就直接把这个代码拷贝进来好了,里面的内容一会分行讲:

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");
		}

应该有看见很多注释掉的代码,其实注释掉的就是我之前自己写,语法句子上都是没问题的。问题就在有“笨蛋”的那个语句,呵呵,你或许会疑惑,这个语句这么简单。我也是这么认为的,于是就自以为滴放在了gp = new Graphic(rs4326, locationPH);后面。就也没有注意。于是苦逼的日子就开始了,没有错误却一点就异常。辛辛苦苦定位到的结果被清除了,这样子的逻辑错误。严重得很!

6.实现了定位,也成功定位了。突然有个想法,想实现以定位点为圆心向四周动画滴发散的动画效果的实现。首先我会想到去自定义一个动画,然后实现。这个理论上是肯定可行的。可是我是小白,哪里有那么高超技术呢?于是领导给了个到现在还觉得很棒的思路,可以去找一下有没有这样子动画的gif图片,然后用图片符号集把它添加进去,不是就OK了,而且还简单得要死。领导就是领导,想法都这么牛X!


综上所述:实现ArcGIS的定位功能其实是很简单的事情。不信你就研究下我说的,还有我的工程文件。“定位功能的实现.rar”

你可能感兴趣的:(android,for,定位,gps,arcgis)