首先进入百度地图开发者中心,找到鹰眼轨迹。按照开发指南首先申请密钥,即获取百度要求的sha1值,在Android studio控制台G:\android2016\LBSdemo>下输入keytool -list -v -keystore D:\key\lbsdemo.jks提示'keytool' 不是内部或外部命令,也不是可运行的程序。可能是我打开方式不对,于是我到命令行窗口在Java的安装目录下找到keytool命令,
那么按照提示输入
其中命令-keystore后的目录是Android Studio在打包时开发者设置的key的路径,接着会让你输入当时设置的密码,密码输入时不显示,回车即可。http://lbsyun.baidu.com/index.php?title=android-yingyan/guide/key此处有官方图文引导。
下一步配置工程,下载库文件解压后将库粘到libs文件夹下,并在app的build gradle 添加
sourceSets { main { jniLibs.srcDir 'libs' } }
接下来配置清单文件:(直接从官网上粘)
1、在Application标签中声明SERVICE组件,每个APP拥有自己独立的鹰眼追踪service
<service android:name="com.baidu.trace.LBSTraceService" android:enabled="true" android:process=":remote"> </service>
2、声明使用权限:
<!-- 这个权限用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission> <!-- 这个权限用于访问GPS定位--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission> <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位--> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission> <!-- 获取运营商信息,用于支持提供运营商信息相关的接口--> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission> <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位--> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission> <!-- 用于读取手机当前的状态--> <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> <!-- 写入扩展存储,向扩展卡写入数据,用于写入对象存储BOS数据--> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <!-- 访问网络,网络定位需要上网--> <uses-permission android:name="android.permission.INTERNET" /> <!-- SD卡读取权限,用于写入对象存储BOS数据--> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission> <!-- 用于加快GPS首次定位--> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission> <!-- 用于Android M及以上系统,申请加入忽略电池优化白名单--> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"></uses-permission>
在Mainfest.xml正确设置AccessKey(ak),如果设置错误将会导致鹰眼服务无法正常使用。需在Application标签中加入以下代码,并填入开发者自己的 Android 类型 ak。meta-data与activity同一级。
AK就是刚刚拿SHA1申请的那个字符串。
<meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="AK" /> //key:开发者申请的Key
import相关类:
import com.baidu.trace.Trace; import com.baidu.trace.LBSTraceClient; import com.baidu.trace.model.OnCustomAttributeListener;import com.baidu.trace.model.OnTraceListener;import com.baidu.trace.api.track.OnTrackListener; import com.baidu.trace.api.fence.OnFenceListener; import com.baidu.trace.api.entity.OnEntityListener;import com.baidu.trace.api.analysis.OnAnalysisListener;import com.baidu.trace.api.bos.OnBosListener;
以上就是官网上配置工程一节的介绍。
结果,震惊的是,官方demo竟然调不起来,看Log
看了论坛的帖子,才意识到我上面获取的是发布版本的SHA1,而调试的时候应该用debug的SHA1,那我想的对不对试试就知道了
deblug的SHA1:B2:31:7E:C6:53:FE:4A:1B:E6:C8:B0:24:F5:0A:F5:E4:07:60:A6:BA
release的SHA1:02:D4:70:1E:FD:31:AA:C0:E9:8B:05:E7:DF:0C:DC:99:5D:84:4A:0A
那拿着这个字符串再去百度申请ak,结果,我沉默了,又走了弯路,还是没调起来。
我真是醉了,我在命令行拿到的SHA1竟然和论坛下载的工具获得的SHA1不一样。日狗了。换了SHA1重新设置一下调起来了。接下来就是分析demo移植了。
第二天咱们来分析demo中是如何获得 手机位置信息并绘制轨迹曲线的。
在TrackApplication中的OnCreate(),
1 @Override 2 public void onCreate() { 3 super.onCreate(); 4 mContext = getApplicationContext(); 5 entityName = CommonUtil.getImei(this); 6 // 若为创建独立进程,则不初始化成员变量 7 if ("com.baidu.track:remote".equals(CommonUtil.getCurProcessName(mContext))) { 8 return; 9 }10 SDKInitializer.initialize(mContext);11 initView();12 initNotification();13 mClient = new LBSTraceClient(mContext);14 mTrace = new Trace(serviceId, entityName);15 mTrace.setNotification(notification);16 trackConf = getSharedPreferences("track_conf", MODE_PRIVATE);17 locRequest = new LocRequest(serviceId);18 mClient.setOnCustomAttributeListener(new OnCustomAttributeListener() {19 @Override20 public Map<String, String> onTrackAttributeCallback() {21 Map<String, String> map = new HashMap<>();22 map.put("key1", "value1");23 map.put("key2", "value2");24 return map;25 }26 });27 clearTraceStatus();28 }
做了一部分初始化的工作:entityName是设备的IMEI号,在通知栏添加了应用通知Notification告知用户服务正在运行,实例化轨迹客户端LBSTraceClient、轨迹服务Trace,Trace有多个构造方法,并且给轨迹服务设置Notification。创建SharedPreference来存储轨迹服务的配置信息。实例化定位请求LocRequest,mClient.setOnCustomAttributeListener()是为了自定义参数,官方解释是:
为实现自定义属性数据上传,开发者须重写OnCustomAttributeListener监听器中的onTrackAttributeCallback()接口,调用 LBSTraceClient.setOnCustomAttributeListener()方法设置自定义属性监听器,并按照设置的定位周期更新onTrackAttributeCallback()的返回值。SDK每采集一次轨迹,便会自动回调onTrackAttributeCallback()接口,获取属性值并写入当前轨迹点的属性字段中。自定义属性监听器需通过LBSTraceClient.setOnCustomAttributeListener()进行设置,LBSTraceService只回调最新设置的自定义监听器。onTrackAttributeCallback()的返回值是Map<String, String>类型,每个对象都是一个<key,value>对,其中key为entity的自定义字段名称,value为值。
clearTraceStatus():
/** * 清除Trace状态:初始化app时,判断上次是正常停止服务还是强制杀死进程,根据trackConf中是否有is_trace_started字段进行判断。 * <p> * 停止服务成功后,会将该字段清除;若未清除,表明为非正常停止服务。 */ private void clearTraceStatus() { if (trackConf.contains("is_trace_started") || trackConf.contains("is_gather_started")) { SharedPreferences.Editor editor = trackConf.edit(); editor.remove("is_trace_started"); editor.remove("is_gather_started"); editor.apply(); } }
在TracingActivity如图,这个布局就是com.baidu.mapapi.map.MapView和下方两个按钮。在OnCreate()的init()初始化三个监听器和地图绘制的一些工具类,主要关注点击两个按钮后事件的逻辑。
1 private void init() { 2 initListener(); 3 trackApp = (TrackApplication) getApplicationContext(); 4 viewUtil = new ViewUtil(); 5 mapUtil = MapUtil.getInstance(); 6 mapUtil.init((MapView) findViewById(R.id.tracing_mapView)); 7 mapUtil.setCenter(trackApp); 8 startRealTimeLoc(Constants.LOC_INTERVAL); 9 powerManager = (PowerManager) trackApp.getSystemService(Context.POWER_SERVICE);10 11 traceBtn = (Button) findViewById(R.id.btn_trace);12 gatherBtn = (Button) findViewById(R.id.btn_gather);13 traceBtn.setOnClickListener(this);14 gatherBtn.setOnClickListener(this);15 setTraceBtnStyle();16 setGatherBtnStyle();17 notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);18 }
第8行startRealTimeLoc()看方法名开启实时定位,传入实时定位间隔单位是秒,方法实例化了一个内部类runnable,并把这个runnable对象发送到handler处理。这个runnable的子线程调用了TrackApplication的getCurrentLocation()获取当前位置。
public void startRealTimeLoc(int interval) { realTimeLocRunnable = new RealTimeLocRunnable(interval); realTimeHandler.post(realTimeLocRunnable); }
getCurrentLocation(OnEntityListener entityListener, OnTrackListener trackListener)需要传入两个监听器,在这个方法中,
1 /** 2 * 获取当前位置 3 */ 4 public void getCurrentLocation(OnEntityListener entityListener, OnTrackListener trackListener) { 5 // 网络连接正常,开启服务及采集,则查询纠偏后实时位置;否则进行实时定位 6 if (NetUtil.isNetworkAvailable(mContext) 7 && trackConf.contains("is_trace_started") 8 && trackConf.contains("is_gather_started") 9 && trackConf.getBoolean("is_trace_started", false)10 && trackConf.getBoolean("is_gather_started", false)) {11 LatestPointRequest request = new LatestPointRequest(getTag(), serviceId, entityName);12 ProcessOption processOption = new ProcessOption();13 processOption.setNeedDenoise(true);14 processOption.setRadiusThreshold(100);15 request.setProcessOption(processOption);16 mClient.queryLatestPoint(request, trackListener);17 } else {18 mClient.queryRealTimeLoc(locRequest, entityListener);19 }20 }
判断是否开启了轨迹服务和轨迹采集和网络连接确定查询纠偏后实时位置或者进行实时定位。构造请求参数和选项请求位置。
回到刚才的startRealTimeLoc(int interval),传入的interval间隔也是handler发送消息的间隔。而这个handler在demo中只是简单的继承Handler并没有自定义handlerMessage()的逻辑。这就是个循环。轮询设备的位置。
在初始化监听时,OnTrackListener()重写了onLatestPointCallback(LatestPointResponse response)方法,其中判断response的返回码以及返回的点不是原点后将点转化为地图上的点并调用mapUtil.updateStatus(currentLatLng,true)绘制点。OnEntityListener()重写了onReceiveLocation(TraceLocation location),与上面类似。OnTraceListener()中重写了开启轨迹服务和采集服务成功失败的回调,
其中上图的开启采集是建立在开启服务的基础之上的。例如在开启服务的回调中,成功的话将TrackApplication中的服务开启标志位置为true,并在SharedPreference中持久化,注册广播。停止服务的回调中,成功停掉的话把TrackApplication的两个标记位都置为false,并且移除SP的两个key,解除广播。
public void onStartTraceCallback(int errorNo, String message) { if (StatusCodes.SUCCESS == errorNo || StatusCodes.START_TRACE_NETWORK_CONNECT_FAILED <= errorNo) { trackApp.isTraceStarted = true; SharedPreferences.Editor editor = trackApp.trackConf.edit(); editor.putBoolean("is_trace_started", true); editor.apply(); setTraceBtnStyle(); registerReceiver(); } viewUtil.showToast(TracingActivity.this, String.format("onStartTraceCallback, errorNo:%d, message:%s ", errorNo, message)); }
if (StatusCodes.SUCCESS == errorNo || StatusCodes.CACHE_TRACK_NOT_UPLOAD == errorNo) { trackApp.isTraceStarted = false; http://www.cnblogs.com/henu529/p/7127774.html