关于GPS卫星信息的获取,网上很多类似文章但都是只能用于安卓7.0以下的,在这里将安卓7.0以下的方法和安卓7.0以上的方法做个总结,安卓7.0以下用GpsStatus.Listener,安卓7.0及以上版本用GnssStatus.Callback
系统已经提供了LocationListener类,所以我们使用时直接实现它,重写下里面的几个方法就可以了,这里重点记录onLocationChanged()方法,这个方法有一个参数对象location,location里面记录了当前位置信息的所有数据,以下代码中在location中获取了经纬度和时间,location还有其他信息具体可参考API
//当位置发生变化时自动调用
@Override
public void onLocationChanged(@NonNull Location location) {
double longitude = location.getLongitude(); //获取当前位置信息的经度
double latitude = location.getLatitude(); //获取当前位置信息的纬度
//获取卫星时间
long SatelliteTime = location.getTime();
String time = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(SatelliteTime);
}
//当提供者状态改变时调用。 当提供者无法获取位置或提供者最近在不可用时段后变为可用时,将调用此方法。
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
//当提供者被用户启用时调用。
@Override
public void onProviderEnabled(String provider) {
}
//当提供者被用户禁用时调用。 如果在已禁用的提供程序上调用requestLocationUpdates,则立即调用此方法。
@Override
public void onProviderDisabled(String provider) {
}
LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, (LocationListener) this);
manager.removeUpdates(this);
仅安卓7.0以下可用,安卓7.0以上的版本要用GnssStatus.Callback
同样系统已经提供了GpsStatus.Listener,只需要实现它重写onGpsStatusChanged方法就可以了,GpsStatus.Listener监听器获取的数据存储在GpsSatellite对象中
@Override
public void onGpsStatusChanged(int event) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
GpsStatus ges = manager.getGpsStatus(null); //获取GPS状态
switch (event) {
case GpsStatus.GPS_EVENT_FIRST_FIX:
break;
//定期发送事件以报告 GPS 卫星状态。
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
Iterable<GpsSatellite> lis = ges.getSatellites(); //获取卫星信息迭代数组
Iterator it = lis.iterator();
while (it.hasNext()) {
GpsSatellite s = (GpsSatellite) it.next();
float id = s.getSnr(); //卫星id
float DBHz = s.getSnr(); //卫星信号强度
float azimuthDegrees = s.getAzimuth(); //卫星方位角
boolean infix = s.usedInFix(); //卫星是否可用于定位
float elevationDegrees = s.getElevation(); //卫星高程
boolean almanacData =s.hasAlmanac(); //卫星是否具有年历数据
boolean ephemerisData = s.hasEphemeris(); //卫星是否具有星历数据
}
break;
case GpsStatus.GPS_EVENT_STARTED:
break;
case GpsStatus.GPS_EVENT_STOPPED:
break;
default:
break;
}
}
manager.addGpsStatusListener(this::onGpsStatusChanged);
manager.removeGpsStatusListener(this);
GnssStatus.Listener监听器获取的卫星数据存储在GnssStatus对象中
GnssStatus.Callback gnsscallback = new GnssStatus.Callback() {
//定期调用以报告GNSS卫星状态
@Override
public void onSatelliteStatusChanged(GnssStatus status) {
//总数量
hhstar1 = status.getSatelliteCount();
//如果卫星总数大于0
if (status != null && status.getSatelliteCount() > 0) {
//循环遍历卫星
for (int i = 0; i < status.getSatelliteCount(); i++) {
int id = status.getSvid(i); //卫星id
float DBHz = status.getCn0DbHz(i); //卫星信号强度
int type = status.getConstellationType(i); //卫星星座类型
float azimuthDegrees = status.getAzimuthDegrees(i); //卫星方位角
boolean infix = status.usedInFix(i); //卫星是否可用于定位
float elevationDegrees = status.getElevationDegrees(i); //卫星高程
boolean almanacData =status.hasAlmanacData(i); //卫星是否具有年历数据
boolean ephemerisData = status.hasEphemerisData(i); //卫星是否具有星历数据
}
}
}
}
};
manager.registerGnssStatusCallback(gnsscallback, null);
manager.unregisterGnssStatusCallback(gnsscallback);
GpsSatellite:获取到的数据中,卫星号是PRN,每颗卫星都有一个唯一的PRN码,我们可以通过PRN码来确定它是什么类型的卫星,这里简单介绍一下:
1-32:GPS卫星
33-64:GPS的备用卫星和测试卫星
65-96:GLONASS卫星
193-200:QZSS卫星
201-261:北斗卫星
301-336:伽利略卫星
901-918:IRNSS卫星
GnssStatus:获取到的数据中没有PRN,但是它有一个Svid和ConstellationType,这个Svid不同的卫星有可能会重复,就是如果获取到两颗卫星,一颗GPS一颗北斗他们的Svid可能是一样的,所以无法判断它是哪种卫星,要通过获取数据中的ConstellationType来判断它是GPS还是北斗,下面介绍一下这个对象中北斗和GPS卫星的Svid范围和ConstellationType的常量
1-32:GPS卫星
1-37:北斗卫星
GnssStatus数据中,如果获取到的卫星号是1-32,那么它可能是GPS也有可能是北斗,所以还要获取ConstellationType数据也就是星座类型标识符
GPS: CONSTELLATION_GPS 常量值为1
北斗:CONSTELLATION_BEIDOU 常量值为5
GpsSatellite:信号值叫信噪比,单位是db
GnssStatus:信号值叫载噪比,单位是dB-Hz
信噪比和载噪比都是代表卫星信号强度,他们具体有什么区别自行探索
整体来说GnssStatus比GpsSatellite多了两个数据:
1.GnssStatus可以获取搜索到的卫星总数,GpsSatellite不行
2.GnssStatus多了一个区分卫星星座类型的参数,GpsSatellite没有
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.GnssStatus;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
public class MainActivity extends AppCompatActivity implements LocationListener, GpsStatus.Listener {
private LocationManager manager;
private GnssStatus.Callback gnsscallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//动态权限申请
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1: {
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "权限已打开!", Toast.LENGTH_SHORT).show();
}
}
}
}
}
/*
***************************************实现LocationListener重写的方法********************************
*/
//当位置发生变化时自动调用
@Override
public void onLocationChanged(@NonNull Location location) {
double longitude = location.getLongitude(); //获取当前位置信息的经度
double latitude = location.getLatitude(); //获取当前位置信息的纬度
//获取卫星时间
long SatelliteTime = location.getTime();
String time = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(SatelliteTime);
}
//当提供者状态改变时调用。 当提供者无法获取位置或提供者最近在不可用时段后变为可用时,将调用此方法。
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
//当提供者被用户启用时调用。
@Override
public void onProviderEnabled(String provider) {
}
//当提供者被用户禁用时调用。 如果在已禁用的提供程序上调用requestLocationUpdates,则立即调用此方法。
@Override
public void onProviderDisabled(String provider) {
}
/*
***************************************************实现GpsStatus.Listener重写的方法************************************************************
*/
@Override
public void onGpsStatusChanged(int event) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
GpsStatus ges = manager.getGpsStatus(null); //获取GPS状态
switch (event) {
//GPS系统自启动以来收到第一次修复时发送的事件
case GpsStatus.GPS_EVENT_FIRST_FIX:
break;
//定期发送事件以报告 GPS 卫星状态。
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
Iterable<GpsSatellite> lis = ges.getSatellites(); //获取卫星信息迭代数组
Iterator it = lis.iterator();
while (it.hasNext()) {
GpsSatellite s = (GpsSatellite) it.next();
float id = s.getSnr(); //卫星id
float DBHz = s.getSnr(); //卫星信号强度
float azimuthDegrees = s.getAzimuth(); //卫星方位角
boolean infix = s.usedInFix(); //卫星是否可用于定位
float elevationDegrees = s.getElevation(); //卫星高程
boolean almanacData =s.hasAlmanac(); //卫星是否具有年历数据
boolean ephemerisData = s.hasEphemeris(); //卫星是否具有星历数据
}
break;
//GPS系统启动时发送的事件
case GpsStatus.GPS_EVENT_STARTED:
break;
//GPS系统停止时发送的事件
case GpsStatus.GPS_EVENT_STOPPED:
break;
default:
break;
}
}
/*
*******************************************创建GnssStatus.Callback******************************************************************
*/
@RequiresApi(api = Build.VERSION_CODES.N)
public void createGnssStatusCallback() {
gnsscallback = new GnssStatus.Callback() {
//定期调用以报告GNSS卫星状态
@Override
public void onSatelliteStatusChanged(GnssStatus status) {
//卫星总数量
int number = status.getSatelliteCount();
Log.d("MainActivity", number + "颗");
//如果卫星总数大于0
if (status != null && status.getSatelliteCount() > 0) {
//循环遍历status提取卫星信息
for (int i = 0; i < status.getSatelliteCount(); i++) {
int id = status.getSvid(i); //卫星id
float DBHz = status.getCn0DbHz(i); //卫星信号强度
int type = status.getConstellationType(i); //卫星星座类型
float azimuthDegrees = status.getAzimuthDegrees(i); //卫星方位角
boolean infix = status.usedInFix(i); //卫星是否可用于定位
float elevationDegrees = status.getElevationDegrees(i); //卫星高程
boolean almanacData =status.hasAlmanacData(i); //卫星是否具有年历数据
boolean ephemerisData = status.hasEphemerisData(i); //卫星是否具有星历数据
}
}
}
};
}
@Override
protected void onResume() {
super.onResume();
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//判断权限是否已打开
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
//判断GPS是否已打开
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Settings.Secure.putInt(MainActivity.this.getContentResolver(), Settings.Secure.LOCATION_MODE, 3); //自动打开GPS开关
}
//添加GPS定位信息监听器
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
//获取卫星信息的方法在安卓7.0以前使用GpsStatus.Listener,安卓7.0及以后的版本只能用GnssStatus.Callback,在这里判断安卓SDK的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
createGnssStatusCallback();
manager.registerGnssStatusCallback(gnsscallback, null);
} else {
manager.addGpsStatusListener(this);
}
}
@Override
public void onPause() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
manager.unregisterGnssStatusCallback(gnsscallback);
} else {
manager.removeGpsStatusListener(this);
}
manager.removeUpdates(this);
super.onPause();
}
@Override
public void onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
manager.unregisterGnssStatusCallback(gnsscallback);
} else {
manager.removeGpsStatusListener(this);
}
manager.removeUpdates(this);
super.onDestroy();
}
}
最后不要忘了申请权限
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
就这么点东西学习的时候硬是耗了我好几个日夜,学会之后发现其实很简单