1.注册一个LBS的账号申请Key 点击打开链接
其中:Package以及SHA1的获取可见:这里
让楼主郁闷的是明明一样的key就是报错:INVALID_USER_SCODE
查找一些资料得出如下结论:
1、注册的sha1与应用签名的签名文件(包括debug.keystore)的sha1不一致。
2、Debug和release的签名文件不一样,所以最好对应注册两个不同的key,避免发布后INVALID_USER_KEY。
3、注册key时应用的包名填写不正确
4、manifest文件中mete-data标签在application标签之外。
楼主Debug跟Release的就没关注
下面上改后的代码:(需要把jks拷入app对应目录)
这样编译出来的debug版本直接用的是正式签名(release)噢
signingConfigs { release { storeFile file("key.story.jks") storePassword "123456" keyAlias "key" keyPassword "123456" } } buildTypes { debug { signingConfig signingConfigs.release } release { signingConfig signingConfigs.release minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
2.去官网下载jar...
点击打开链接
3.配置manifest
首先,请在application标签中声明service组件,每个app拥有自己单独的定位service。
1
|
<service android:name=
"com.amap.api.location.APSService"
></service>
|
接下来声明使用权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!--用于进行网络定位-->
<uses-permission android:name=
"android.permission.ACCESS_COARSE_LOCATION"
></uses-permission>
<!--用于访问GPS定位-->
<uses-permission android:name=
"android.permission.ACCESS_FINE_LOCATION"
></uses-permission>
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name=
"android.permission.ACCESS_NETWORK_STATE"
></uses-permission>
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name=
"android.permission.ACCESS_WIFI_STATE"
></uses-permission>
<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name=
"android.permission.CHANGE_WIFI_STATE"
></uses-permission>
<!--用于访问网络,网络定位需要上网-->
<uses-permission android:name=
"android.permission.INTERNET"
></uses-permission>
<!-- 用于读取手机当前的状态-->
<uses-permission android:name=
"android.permission.READ_PHONE_STATE"
></uses-permission>
<!-- 写入扩展存储,向扩展卡写入数据,用于写入缓存定位数据-->
<uses-permission android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
></uses-permission>
|
最后设置Key,在application标签中加入
1
2
3
|
<meta-data android:name=
"com.amap.api.v2.apikey"
android:value=
"key"
>
//开发者申请的key
</meta-data>
|
package tr.nuctech.com.tr0100.Activity; import android.graphics.Point; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.view.animation.BounceInterpolator; import android.view.animation.Interpolator; import android.widget.Toast; import com.amap.api.location.AMapLocation; import com.amap.api.location.AMapLocationClient; import com.amap.api.location.AMapLocationClientOption; import com.amap.api.location.AMapLocationListener; import com.amap.api.maps.AMap; import com.amap.api.maps.CameraUpdateFactory; import com.amap.api.maps.LocationSource; import com.amap.api.maps.MapView; import com.amap.api.maps.Projection; import com.amap.api.maps.model.BitmapDescriptor; import com.amap.api.maps.model.BitmapDescriptorFactory; import com.amap.api.maps.model.CameraPosition; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.Marker; import com.amap.api.maps.model.MarkerOptions; import java.util.ArrayList; import java.util.List; import tr.nuctech.com.tr0100.Bean.Constants; import tr.nuctech.com.tr0100.R; import tr.nuctech.com.tr0100.Util.LBSUtils; public class MapActivity extends AppCompatActivity implements LocationSource, AMapLocationListener, AMap.OnMarkerClickListener { private MapView mapView; private AMap aMap; // private OnLocationChangedListener mListener; //初始化定位对象 private AMapLocationClient locationClient = null; private AMapLocationClientOption locationOption = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_map); mapView = (MapView) findViewById(R.id.id_map); mapView.onCreate(savedInstanceState);// 此方法必须重写 init(); //初始化定位模块 locationClient = new AMapLocationClient(this); locationOption = new AMapLocationClientOption(); // 设置定位模式为 locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); // 设置定位监听 locationClient.setLocationListener(this); // //只有持续定位设置定位间隔才有效,单次定位无效 // layoutInterval.setVisibility(View.VISIBLE); //设置为不是单次定位 locationOption.setOnceLocation(true); // 设置定位参数 locationClient.setLocationOption(locationOption); new Thread(){ @Override public void run() { super.run(); // 启动定位 try { Thread.sleep(2000); locationClient.startLocation(); mHandler.sendEmptyMessage(LBSUtils.MSG_LOCATION_START); } catch (InterruptedException e) { e.printStackTrace(); } } }.start(); } /** * 初始化AMap对象 */ private void init() { if (aMap == null) { aMap = mapView.getMap(); aMap.setLocationSource(this);// 设置定位监听 aMap.getUiSettings().setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示 aMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false // 设置定位的类型为定位模式,参见类AMap。 aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE); //marker // aMap.setOnMarkerDragListener(this);// 设置marker可拖拽事件监听器 // aMap.setOnMapLoadedListener(this);// 设置amap加载成功事件监听器 aMap.setOnMarkerClickListener(this);// 设置点击marker事件监听器 // aMap.setOnInfoWindowClickListener(this);// 设置点击infoWindow事件监听器 // aMap.setInfoWindowAdapter(this);// 设置自定义InfoWindow样式 } } Handler mHandler = new Handler(){ public void dispatchMessage(android.os.Message msg) { switch (msg.what) { case LBSUtils.MSG_LOCATION_START: Toast.makeText(MapActivity.this,"正在定位...",Toast.LENGTH_SHORT).show(); break; //定位完成 case LBSUtils.MSG_LOCATION_FINISH: AMapLocation loc = (AMapLocation)msg.obj; String result = LBSUtils.getLocationStr(loc); Toast.makeText(MapActivity.this,result,Toast.LENGTH_SHORT).show(); // tvReult.setText(result); break; case LBSUtils.MSG_LOCATION_STOP: Toast.makeText(MapActivity.this,"定位停止",Toast.LENGTH_SHORT).show(); break; default: break; } }; }; @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override protected void onDestroy() { super.onDestroy(); if (null != locationClient) { /** * 如果AMapLocationClient是在当前Activity实例化的, * 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy */ locationClient.onDestroy(); locationClient = null; locationOption = null; } } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); } @Override protected void onStart() { super.onStart(); } @Override public void onLocationChanged(AMapLocation aMapLocation) { //定位回调 Toast.makeText(this,"onLocationChanged",Toast.LENGTH_SHORT).show(); if (this != null && aMapLocation != null) { if (aMapLocation != null && aMapLocation.getErrorCode() == 0) { // this.onLocationChanged(aMapLocation);// 显示系统小蓝点 LatLng postion=new LatLng(aMapLocation.getLatitude(),aMapLocation.getLongitude()); CameraPosition position=new CameraPosition(postion , 18, 0, 30); aMap.moveCamera(CameraUpdateFactory.newCameraPosition(position)); initMark(postion); } else { String errText = "定位失败," + aMapLocation.getErrorCode()+ ": " + aMapLocation.getErrorInfo(); Toast.makeText(this,"errText",Toast.LENGTH_SHORT).show(); } } // if (null != aMapLocation) { // Message msg = mHandler.obtainMessage(); // msg.obj = aMapLocation; // msg.what = LBSUtils.MSG_LOCATION_FINISH; // mHandler.sendMessage(msg); // } } @Override public void activate(OnLocationChangedListener onLocationChangedListener) { Toast.makeText(this,"activate",Toast.LENGTH_SHORT).show(); } @Override public void deactivate() { Toast.makeText(this,"deactivate",Toast.LENGTH_SHORT).show(); } private void initMark(LatLng latLng) { ArrayList<BitmapDescriptor> giflist = new ArrayList<BitmapDescriptor>(); giflist.add(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_BLUE)); giflist.add(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_RED)); giflist.add(BitmapDescriptorFactory .defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)); MarkerOptions markerOption1 = new MarkerOptions().anchor(0.5f, 0.5f) .position(latLng).title("同方威视") .snippet("Creating a safer world").icons(giflist) .draggable(true).period(50); ArrayList<MarkerOptions> markerOptionlst = new ArrayList<MarkerOptions>(); markerOptionlst.add(markerOption1); List<Marker> markerlst = aMap.addMarkers(markerOptionlst, true); } @Override public boolean onMarkerClick(Marker marker) { jumpPoint(marker); return false; } /** * marker点击时跳动一下 */ public void jumpPoint(final Marker marker) { final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); Projection proj = aMap.getProjection(); Point startPoint = proj.toScreenLocation(Constants.XIAN); startPoint.offset(0, -100); final LatLng startLatLng = proj.fromScreenLocation(startPoint); final long duration = 1500; final Interpolator interpolator = new BounceInterpolator(); handler.post(new Runnable() { @Override public void run() { long elapsed = SystemClock.uptimeMillis() - start; float t = interpolator.getInterpolation((float) elapsed / duration); double lng = t * Constants.XIAN.longitude + (1 - t) * startLatLng.longitude; double lat = t * Constants.XIAN.latitude + (1 - t) * startLatLng.latitude; // marker.setPosition(new LatLng(lat, lng)); marker.setPosition(marker.getPosition()); if (t < 1.0) { handler.postDelayed(this, 16); } } }); } }
高德定位服务包含GPS和网络定位(Wi-Fi和基站定位)两种能力。定位SDK将GPS、网络定位能力进行了封装,以三种定位模式对外开放
高精度定位模式:会同时使用网络定位和GPS定位,优先返回最高精度的定位结果;
低功耗定位模式:不会使用GPS,只会使用网络定位(Wi-Fi和基站定位);
仅用设备定位模式:不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位。
第一步,初始化定位客户端,设置监听
注:请在主线程中声明AMapLocationClient类对象,需要传Context类型的参数。推荐用getApplicationConext()方法获取全进程有效的context。
1
2
3
4
5
6
7
8
|
//声明AMapLocationClient类对象
public
AMapLocationClient mLocationClient =
null
;
//声明定位回调监听器
public
AMapLocationListener mLocationListener =
new
AMapLocationListener();
//初始化定位
mLocationClient =
new
AMapLocationClient(getApplicationContext());
//设置定位回调监听
mlocationClient.setLocationListener(mLocationListener);
|
第二步,配置定位参数,启动定位
设置定位参数包括:定位模式(高精度定位模式,低功耗定位模式和仅设备定位模式),是否返回地址信息等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//声明mLocationOption对象
public
AMapLocationClientOption mLocationOption =
null
;
//初始化定位参数
mLocationOption =
new
AMapLocationClientOption();
//设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
mLocationOption.setLocationMode(AMapLocationMode.Hight_Accuracy);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(
true
);
//设置是否只定位一次,默认为false
mLocationOption.setOnceLocation(
false
);
//设置是否强制刷新WIFI,默认为强制刷新
mLocationOption.setWifiActiveScan(
true
);
//设置是否允许模拟位置,默认为false,不允许模拟位置
mLocationOption.setMockEnable(
false
);
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(
2000
);
//给定位客户端对象设置定位参数
mlocationClient.setLocationOption(mLocationOption);
//启动定位
mlocationClient.startLocation();
|
第三步,实现AMapLocationListener接口,获取定位结果
AMapLocationListener接口只有onLocationChanged方法可以实现,用于接收异步返回的定位结果,参数是AMapLocation类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public
void
onLocationChanged(AMapLocation amapLocation) {
if
(amapLocation !=
null
) {
if
(amapLocation.getErrorCode() ==
0
) {
//定位成功回调信息,设置相关消息
amapLocation.getLocationType();
//获取当前定位结果来源,如网络定位结果,详见定位类型表
amapLocation.getLatitude();
//获取纬度
amapLocation.getLongitude();
//获取经度
amapLocation.getAccuracy();
//获取精度信息
SimpleDateFormat df =
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
);
Date date =
new
Date(amapLocation.getTime());
df.format(date);
//定位时间
amapLocation.getAddress();
//地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
amapLocation.getCountry();
//国家信息
amapLocation.getProvince();
//省信息
amapLocation.getCity();
//城市信息
amapLocation.getDistrict();
//城区信息
amapLocation.getStreet();
//街道信息
amapLocation.getStreetNum();
//街道门牌号信息
amapLocation.getCityCode();
//城市编码
amapLocation.getAdCode();
//地区编码
}
else
{
//显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
Log.e(
"AmapError"
,
"location Error, ErrCode:"
+ amapLocation.getErrorCode() +
", errInfo:"
+ amapLocation.getErrorInfo());
}
}
}
|
第四步,关于停止定位
停止定位:
1
|
mlocationClient.stopLocation();
//停止定位
|
销毁定位客户端:
销毁定位客户端之后,若要重新开启定位请重新New一个AMapLocationClient对象。
1
|
mlocationClient.onDestroy();
//销毁定位客户端。
|
地理围栏功能,是以一个圆形的地理边界作为虚拟围栏,当手机进入、离开该区域时,手机可以接收自动通知。
AMapLocationClient类的 addGeoFenceAlert(int fenceId,double latitude,double longitude, float radius, long expiration, PendingIntent intent) 方法可用于添加地理围栏,该方法的参数:
fenceId-围栏id
latitude-警戒区域中心点的纬度。
longitude-警戒区域中心点的经度。
radius-警戒区域的半径,单位为米。
expiration-警戒时间,单位为毫秒,设置为-1时表示没有时间限制。
intent-当检测到进入或离开警戒区域时将被激活的PendingIntent。该 intent 的 Bundle 的 status 字段值为0表示从区域中离开,1表示进入该区域。
说明:只在进入或离开警戒区域时给出一次警告信息,在警戒区域内活动或者在区域外活动无警告。
示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//实例化定位客户端
AMapLocationClient mlocationClient =
null
;
mlocationClient =
new
AMapLocationClient(getApplicationContext());
//注册Receiver,设置过滤器
IntentFilter fliter =
new
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
fliter.addAction(GEOFENCE_BROADCAST_ACTION);
//mGeoFenceReceiver为自定义的广播接收器
registerReceiver(mGeoFenceReceiver, fliter);
//声明对应的intent对象
Intent intent =
new
Intent(GEOFENCE_BROADCAST_ACTION);
//创建PendingIntent对象
PendingIntent mPendingIntent =
null
;
mPendingIntent = PendingIntent.getBroadcast(getApplicationContext(),
0
,intent,
0
);
//添加地理围栏
mlocationClient.addGeoFenceAlert(fenceId, latLng.latitude,latLng.longitude,
1000
,
1000
*
60
*
30
, mPendingIntent);
//自定义广播接收器
private
BroadcastReceiver mGeoFenceReceiver =
new
BroadcastReceiver() {
@Override
public
void
onReceive(Context context, Intent intent) {
// 接收广播内容,处理进出的具体操作。
}
};
//启动定位
mlocationClient.startLocation();
|
支持GPS/Mapbar/Baidu等多种类型坐标在高德地图上使用。参见类CoordinateConverter。
1
2
3
4
5
6
7
|
CoordinateConverter converter =
new
CoordinateConverter();
// CoordType.GPS 待转换坐标类型
converter.from(CoordType.GPS);
// sourceLatLng待转换坐标点 DPoint类型
converter.coord(sourceLatLng);
// 执行转换操作
DPoint desLatLng = converter.convert();
|
CoordinateConverter类提供的isAMapDataAvailable(double latitude,double longitude)接口可以用来判断指定位置是否在大陆以及港、澳地区。
自2.2版本isAMapDataAvailable(double latitude,double longitude)方法参数进行了调整,第一个参数传纬度,第二个参数传经度;
1
2
3
4
|
CoordinateConverter converter =
new
CoordinateConverter();
//返回true代表当前位置在大陆、港澳地区,反之不在。
boolean
isAMapDataAvailable = converter.isAMapDataAvailable(latitude,longitude);
//第一个参数为纬度,第二个为经度,纬度和经度均为高德坐标系。
|
● 目前手机设备在长时间黑屏或锁屏时CPU会休眠,这导致定位SDK不能正常进行位置更新。若您有锁屏状态下获取位置的需求,您可以应用alarmManager实现1个可叫醒CPU的Timer,定时请求定位。
● 使用定位SDK务必要注册GPS和网络的使用权限。
● 在使用定位SDK时,请尽量保证网络畅通,如获取网络定位,地址信息等都需要设备可以正常接入网络。
● 定位SDK在国内返回高德类型坐标,海外定位将返回GPS坐标。
● 仅设备定位(通过GPS定位)是设备本地定位行为,是不返回地址信息的,地址信息在网络定位时会返回。