Android - GPS的简单应用


前言

关于GPS卫星信息的获取,网上很多类似文章但都是只能用于安卓7.0以下的,在这里将安卓7.0以下的方法和安卓7.0以上的方法做个总结,安卓7.0以下用GpsStatus.Listener,安卓7.0及以上版本用GnssStatus.Callback


一、定位信息获取:LocationListener

1.创建位置信息监听器LocationListener

系统已经提供了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) {

    }


2.打开监听器开始监听

LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, (LocationListener) this);

3.关闭监听器停止监听

manager.removeUpdates(this);

二、卫星信息获取:GpsStatus.Listener

仅安卓7.0以下可用,安卓7.0以上的版本要用GnssStatus.Callback

1.创建GpsStatus.Listener监听器

同样系统已经提供了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;
        }
    }

2.打开监听器

manager.addGpsStatusListener(this::onGpsStatusChanged);

3.关闭监听器

manager.removeGpsStatusListener(this);

三、卫星信息获取:GnssStatus.Callback

1.注册GnssStatus.Listener监听器

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);      //卫星是否具有星历数据
                    }
                }
            }
        }
    };

2.打开监听器

 manager.registerGnssStatusCallback(gnsscallback, null);

3.关闭监听器

manager.unregisterGnssStatusCallback(gnsscallback);

四、两种卫星获取方式对比

1.卫星号不同

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

2. 信号值不同

GpsSatellite:信号值叫信噪比,单位是db
GnssStatus:信号值叫载噪比,单位是dB-Hz
信噪比和载噪比都是代表卫星信号强度,他们具体有什么区别自行探索

3. 对象中的数据对比

整体来说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"/>

总结

就这么点东西学习的时候硬是耗了我好几个日夜,学会之后发现其实很简单

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值