Android使用Service结合高德定位SDK实现定位,有需要的朋友可以参考下。
高德官方给出的定位实例都是基于Activity的,但是实际过程中会有需要不断定位的情况,特别是需要后台统计用户数据的。如果在Activity中绑定定位服务,那么定位就受Activity的生命周期限制,显然用Service实习定位是个不错的选择。然后结合BroadcastRecevier可以实现当数据需要更新的时候即使提醒提醒更新数据。
package cn.letsbook.running.service;import android.app.Service;import android.content.Intent;import android.location.Location;import android.os.Bundle;import android.os.IBinder;import android.util.Log;import cn.letsbook.running.model.FixedLengthList;import cn.letsbook.running.util.Constants;import com.amap.api.location.AMapLocation;import com.amap.api.location.AMapLocationListener;import com.amap.api.location.LocationManagerProxy;import com.amap.api.location.LocationProviderProxy;/** * 定位服务,基于高德的定位API V1.3.0实现 * * @author Jywang * @email jywangkeep@163.com * */public class LocationService extends Service implements AMapLocationListener { public static final long LOCATION_UPDATE_MIN_TIME = 10 * 1000; public static final float LOCATION_UPDATE_MIN_DISTANCE = 5; private FixedLengthList<AMapLocation> locationList = FixedLengthList .newInstance(); // 位置服务代理 private LocationManagerProxy locationManagerProxy; public LocationService() { } @Override public void onCreate() { super.onCreate(); //使用参数为Context的方法,Service也是Context实例, //是四大组件之一 locationManagerProxy = LocationManagerProxy.getInstance(this); // 定位方式设置为混合定位,包括网络定位和GPS定位 locationManagerProxy.requestLocationData( LocationProviderProxy.AMapNetwork, LOCATION_UPDATE_MIN_TIME, LOCATION_UPDATE_MIN_DISTANCE, this); // 如果定位方式包括GPS定位需要手动设置GPS可用 locationManagerProxy.setGpsEnable(true); Log.v("locationservice", "locationservicestart"); } @SuppressWarnings("deprecation") @Override public void onDestroy() { super.onDestroy(); // 在Service销毁的时候销毁定位资源 if (locationManagerProxy != null) { locationManagerProxy.removeUpdates(this); locationManagerProxy.destory(); } //设置为null是为了提醒垃圾回收器回收资源 locationManagerProxy = null; } @Override public void onLocationChanged(Location location) { //在较新的SDK版本中,这个方法在位置发生变化的时候不会被 //调用。这个方法默认是使用原生GPS服务的时候,当位置 //变化被调用的方法。 } @Override public void onStatusChanged(String provider, int status, Bundle extras) { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } //当位置发生变化的时候调用这个方法。 @Override public void onLocationChanged(AMapLocation aMapLocation) { // 如果位置获取错误则不作处理,退出本方法 // 返回错误码如果为0则表明定位成功,反之则定位失败 //在虚拟机测试的时候,返回错误码31,为未知错误 //如果使用虚拟机测试的时候遇到这个问题,建议使用真机测试。 if (aMapLocation == null || aMapLocation.getAMapException().getErrorCode() != 0) { Log.v("locationservice", aMapLocation == null ? "null" : "not null"); if (aMapLocation != null) { Log.v("locationservice", "errorcode" + aMapLocation.getAMapException().getErrorCode()); Log.v("locationservice", "errormessage" + aMapLocation.getAMapException().getErrorMessage()); } Log.v("locationservice", "request error"); return; } //locationList是一个自定义实现的泛型类, //用于实现定长固定列表的功能。 locationList.addElement(aMapLocation); Log.v("test", locationList.getLastElement().toString()); // 发送广播传送地点位置信息到地图显示界面 // 当数据正常获取的时候,把位置信息通过广播发送到接受方, // 也就是需要处理这些数据的组件。 Intent intent = new Intent(); intent.setAction(Constants.INTENT_ACTION_UPDATE_DATA); intent.putExtra(Constants.INTENT_ACTION_UPDATE_DATA_EXTRA_LATITUDE, aMapLocation.getLatitude()); intent.putExtra(Constants.INTENT_ACTION_UPDATE_DATA_EXTRA_LONGITUDE, aMapLocation.getLongitude()); this.sendBroadcast(intent); } @Override public IBinder onBind(Intent intent) { return null; }}
其中关于自定义泛型固定长度列表,可移步这篇文章Java实现泛型单例模式
然后就是需要自己在需要接收数据的地方写BroadcastReceiver实例就行了。为了便于更新控件显示的数据,个人建议把BroadcastRecevier当作内部类实现,如下面代码所示:
/** * 自定义广播接收者类 * * @author Jywang * @time 2014-11-4 * @email jywangkeep@163.com * */ public class Receiver extends BroadcastReceiver { /** * 空构造函数,用于初始化Recevier */ public Receiver() { } private void disposeUpdateDataAction(Intent intent) { //书写更新控件数据逻辑 } @Override public void onReceive(Context context, Intent intent) { if (intent == null) return; if (Constants.INTENT_ACTION_UPDATE_DATA.equals(intent.getAction())) disposeUpdateDataAction(intent); else if (Constants.INTENT_ACTION_UPDATE_TIME.equals(intent .getAction())) RunCustomActivity.this.updateTime(); } }// end receiver
然后在Activity(这个是我用于处理数据的逻辑,我要把位置信息绘制在地图上。)的onStart()中注册广播,如下所示:
@Override protected void onStart() { super.onStart(); initiazlieGPS(); // 每次重新回到界面的时候注册广播接收者 IntentFilter filter = new IntentFilter(); filter.addAction(Constants.INTENT_ACTION_UPDATE_DATA); filter.addAction(Constants.INTENT_ACTION_UPDATE_TIME); registerReceiver(receiver, filter); //其他需要处理的逻辑 }
然后在Activity的onStop()方法中解除对广播的注册,如一下代码所示:
@Override protected void onStop() { super.onStop(); if (receiver != null) unregisterReceiver(receiver); }
其中用到的receiver是我建立的一个Receiver这个自定义广播接收类的一个实例。
当你需要启动定位服务的时候,使用下面代码启动Service:
Intent startLocationServiceIntent = new Intent(this, LocationService.class); startService(startLocationServiceIntent);
需要停止定位服务的时候,使用下面代码停止Service:
Intent stopLocationServiceIntent = new Intent(this, LocationService.class); stopService(stopLocationServiceIntent);
对了,Service一定要在AndroidManifest.xml文件中声明,否则无法使用。如下所示:
<!-- 定位服务 --> <service android:name="cn.letsbook.running.service.LocationService" android:exported="false" />
这段代码放到application内部,跟Activity同一个层级。
以上就是全部。
联系客服