我们在做Android平台GB28181的时候,其中实时位置(MobilePosition)订阅和上报这块,涉及到实时经纬度的获取,特别是执法记录、车载系统的那个等场景,几乎就是标配。
今天主要是分享一段实时获取位置的代码:
/* * CameraPublishActivity.java * CameraPublishActivity * * Github: https://github.com/daniulive/SmarterStreaming */ private void getLocation(Context context) { try { if ( context == null ) return; //1.获取位置管理器 if ( mLocationManager == null ) mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); if (mLocationManager == null) return; //2.获取位置提供器,GPS或是NetWork List<String> providers = mLocationManager.getProviders(true); if ( providers != null ) { if (providers.contains(LocationManager.NETWORK_PROVIDER)){ //如果是网络定位 mLocationProvider = LocationManager.NETWORK_PROVIDER; }else if (providers.contains(LocationManager.GPS_PROVIDER)){ //如果是GPS定位 mLocationProvider = LocationManager.GPS_PROVIDER; }else { Toast.makeText(this, "没有可用的位置提供器", Toast.LENGTH_SHORT).show(); return; } } if (mLocationProvider == null ) return; mLocationManager.removeUpdates(mLocationListener); mLocationManager.requestLocationUpdates(mLocationProvider, 500, 1.0f, mLocationListener); //3.获取上次的位置,一般第一次运行,此值为null Location location = mLocationManager.getLastKnownLocation(mLocationProvider); if (location!=null) { updateLocation(location); } }catch (Exception e) { Log.e(TAG, "getLocation exception:" + e.getMessage()); e.printStackTrace(); } } private void updateLocation(Location location){ //long utc_time = location.getTime(); //long local_time = utc_time + TimeZone.getDefault().getOffset(utc_time); //Date date = new Date(location.getTime()); Date date = new Date(System.currentTimeMillis()); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); String time_str = dateFormat.format(date); // String address = "纬度:"+location.getLatitude()+" 经度:"+location.getLongitude() + " 时间:" + time_str; //Log.i(TAG, "位置信息: " + address); mLocationTime = time_str; mLatitude = String.valueOf(location.getLatitude()); mLongitude = String.valueOf(location.getLongitude()); } LocationListener mLocationListener = new LocationListener() { @Override public void onStatusChanged(String provider, int { } @Override public void onProviderEnabled(String provider) { } @Override public void onProviderDisabled(String provider) { } // 如果位置发生变化,重新显示 @Override public void onLocationChanged(Location location)
国标平台开启位置订阅后,Android平台GB28181接入端根据平台侧发过来的时间间隔要求,周期性的更新实时位置信息,相关流程如下:
其中,SUBSCRIBE请求XML描述如下,除了常规信息外,还提供了Interval,供接入端使用。
<?xml versinotallow="1.0" encoding="GB2312" <Query> <CmdType>MobilePosition</CmdType> <SN>55674</SN> <DeviceID>31011500991320000099</DeviceID> <Interval>5</Interval> </Query>
Android国标接入端上报NOTIFY请求示例,请求体XML示例如下:
<?xml versinotallow="1.0" encoding="GB2312" <Notify> <CmdType>MobilePosition</CmdType> <SN>71339</SN> <TargetID>31011500991320000099</TargetID> <Time>2022-03-19T12:22:20</Time> <Longitude>143.507222</Longitude> <Latitude>33.99011311</Latitude> </Notify>
当底层有DevicePosition处理诉求时,可参考如下实现:
@Override public void ntsOnDevicePositionRequest(String deviceId, int { handler_.postDelayed(new Runnable() { @Override public void run() { getLocation(context_); Log.v(TAG, "ntsOnDevicePositionRequest, deviceId:" + this.device_id_ + ", Longitude:" + mLongitude + ", Latitude:" + mLatitude + ", Time:" + mLocationTime); if (mLongitude != null && mLatitude != null) { com.gb.ntsignalling.DevicePosition device_pos = new com.gb.ntsignalling.DevicePosition(); device_pos.setTime(mLocationTime); device_pos.setLongitude(mLongitude); device_pos.setLatitude(mLatitude); if (gb28181_agent_ != null ) { gb28181_agent_.updateDevicePosition(device_id_, device_pos); } } } private String device_id_; private int interval_; public Runnable set(String device_id, int { this.device_id_ = device_id; this.interval_ = interval; return this; } }.set(deviceId, interval),0); }
以下是大概的流程,感兴趣的开发者,可以酌情参考。