Today, due to work needs, I took out a GPS test program I wrote before and revised it. This program has a bit of history. I wrote it in 2011, not long after I learned Android development, and it was considered an experimental work. Now the work requires it, so I need to take it out again and repair it. At the same time, I found that I don’t know much about the GPS service of Android, so I read some information about the GPS service today and recorded the relevant knowledge points.
I have been working on GPS-related embedded software for several years, so when it comes to making a program to test the GPS positioning module, my first reaction is to read the data of the GPS module through the serial port, and then analyze the NMEA of the GPS. format data. NMEA is a standardized data format that is not only used in GPS, but also in other industrial communications. By parsing the relevant data and then displaying it, a basic GPS positioning test function is completed.
After checking, I found that to perform GPS-related positioning services on Android, there is no need to read NMEA data analysis. Android has already encapsulated the relevant services. All you have to do is call the API. I don’t know whether I should feel happy or confused about this. (Android also provides an interface for reading NMEA, which will be discussed below)
1. Android positioning service
Let’s first take a look at the support provided by Android for positioning services:
Android location services are all located under location. There are relevant instructions above, so I won’t analyze them in detail here. One thing that needs to be mentioned is: GpsStatus.NmeaListener. The official statement is that it can read NMEA data, but my test here found that no NMEA data was read. After consulting some information, it is said that Google does not implement the data feedback function at the bottom level. If you have time, you need to check the source code.
2. LocationManager positioning
//获取定位服务 LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); //判断是否已经打开GPS模块 if (locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) { //GPS模块打开,可以定位操作 }
// 通过GPS定位 String LocateType= locationManager.GPS_PROVIDER; Location location = locationManager.getLastKnownLocation(LocateType); // 设置监听器,设置自动更新间隔这里设置1000ms,移动距离:0米。 locationManager.requestLocationUpdates(provider, 1000, 0, locationListener); // 设置状态监听回调函数。statusListener是监听的回调函数。 locationManager.addGpsStatusListener(statusListener); //另外给出 通过network定位设置 String LocateType= locationManager.NETWORK_PROVIDER; Location location = locationManager.getLastKnownLocation(LocateType);
The initial setting steps of the positioning service are given above, but we all know that GPS satellites broadcast data regularly, that is, Said it would receive satellite GPS data regularly. We cannot actively request data from satellites and can only passively receive data. (China's Beidou 2 can send satellite messages to satellites) Therefore, we need to register a listener to process the data returned by the satellite.
private final GpsStatus.Listener statusListener = new GpsStatus.Listener() { public void onGpsStatusChanged(int event) { // GPS状态变化时的回调,获取当前状态 GpsStatus status = locationManager.getGpsStatus(null); //自己编写的方法,获取卫星状态相关数据 GetGPSStatus(event, status); } };
private void GetGPSStatus(int event, GpsStatus status) { Log.d(TAG, "enter the updateGpsStatus()"); if (status == null) { } else if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) { //获取最大的卫星数(这个只是一个预设值) int maxSatellites = status.getMaxSatellites(); Iterator<GpsSatellite> it = status.getSatellites().iterator(); numSatelliteList.clear(); //记录实际的卫星数目 int count = 0; while (it.hasNext() && count <= maxSatellites) { //保存卫星的数据到一个队列,用于刷新界面 GpsSatellite s = it.next(); numSatelliteList.add(s); count++; Log.d(TAG, "updateGpsStatus----count="+count); } mSatelliteNum = numSatelliteList.size(); } else if(event==GpsStatus.GPS_EVENT_STARTED) { //定位启动 } else if(event==GpsStatus.GPS_EVENT_STOPPED) { //定位结束 } }
saved into a queue for later refresh of the interface. The above is to obtain the GPS status listener. In addition to the GPS status, we also need to monitor a service,
is: LocationListener, positioning listener, and monitor location changes. This is very important for applications that provide location services.
5. LocationListener listener
private final LocationListener locationListener = new LocationListener() { public void onLocationChanged(Location location) { //当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发 updateToNewLocation(location); Log.d(TAG, "LocationListener onLocationChanged"); } public void onProviderDisabled(String provider) { //Provider被disable时触发此函数,比如GPS被关闭 Log.d(TAG, "LocationListener onProviderDisabled"); } public void onProviderEnabled(String provider) { // Provider被enable时触发此函数,比如GPS被打开 Log.d(TAG, "LocationListener onProviderEnabled"); } public void onStatusChanged(String provider, int status, Bundle extras) { Log.d(TAG, "LocationListener onStatusChanged"); // Provider的转态在可用、暂时不可用和无服务三个状态直接切换时触发此函数 if (status == LocationProvider.OUT_OF_SERVICE || status == LocationProvider.TEMPORARILY_UNAVAILABLE) { } } };
6. Obtain geographical location information (latitude and longitude, number of satellites, altitude, positioning status)
//location对象是从上面定位服务回调函数的参数获取。 mLatitude = location.getLatitude(); // 经度 mLongitude = location.getLongitude(); // 纬度 mAltitude = location.getAltitude(); //海拔 mSpeed = location.getSpeed(); //速度 mBearing = location.getBearing(); //方向
//temgGpsSatellite就是我们上面保存的搜索到的卫星 //方向角 float azimuth = temgGpsSatellite.getAzimuth(); //高度角 float elevation = temgGpsSatellite.getElevation(); //信噪比 float snr = temgGpsSatellite.getSnr();
The following is the rendering of the GPS test I made:
//根据方向角和高度角计算出,卫星显示的位置 Point point = new Point(); int x = mEarthHeartX; //左边地球圆形的圆心位置X坐标 int y = mEarthHeartY; //左边地球圆形的圆心位置Y坐标 int r = mEarthR; x+=(int)((r*elevation*Math.sin(Math.PI*azimuth/180)/90)); y-=(int)((r*elevation*Math.cos(Math.PI*azimuth/180)/90)); point.x = x; point.y = y; //point就是你需要绘画卫星图的起始坐标
Android provides us with very convenient location services, mainly through the GpsStatus, LocationManager, and GpsSatellite classes to implement related services and monitoring.
However, I personally think it would be very convenient if the NMEA data could be read directly. At least for some applications, more information can be obtained.