【问题标题】:Is it possible to know my location came from gps or glonass?是否有可能知道我的位置来自 gps 或 glonass?
【发布时间】:2018-06-01 16:13:21
【问题描述】:

假设设备同时支持 gps 和 glonass(硬件级别的支持)。

现在当我通过 android.location API 获取位置时,是否可以知道该位置来自哪个硬件?


LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationListener());

class LocationListener implement LocationListener(){
    @Override
    public void onLocationChanged(Location location) {
        GPSStatus status=locationManager.getGpsStatus();
        //check the PRN of the satellites from the status
        //but how can be granted that the `status` object obtained here is exactly the same when it was used to calculate the location?
    }
}

如果我们像这样使用GPSStatus.Listener

class LocationListener implement LocationListener,GPSStatus.Listener(){
    private GPSStatus status;
    @Override
    public void onLocationChanged(Location location) {
        if(status!=null){
            //status should be the GPSStatus before get this location
            //check the PRN of the satellites from the status
            //How it can be granted that the `onGpsStatusChanged` will be called before the `onLocationChanged` by the Android System?
        }

    }
   public void onGpsStatusChanged(int event) {
        status = locationManager.getGpsStatus(null);    
    }
}

【问题讨论】:

    标签: android location


    【解决方案1】:

    获取位置的硬件是您手机中的 GPS/GLONASS 芯片。该芯片接收来自绕地球运行的卫星的信号。

    GPS 和 GLONASS 卫星在支持此功能的设备上结合使用。要确定是否使用 GLONASS 卫星来确定位置,您可以注册 GpsStatusListener 或致电 LocationManager.getGpsStatus()。在 GpsStatus 对象上调用 getSatellites() 并在返回列表中的每个 GpsSatellite 对象上调用 getPrn()。如果该值介于 65 和 88 之间,并且 usedInFix() 方法返回 true,则最后一个位置是使用 GLONASS 卫星计算的。

    http://developer.sonymobile.com/knowledge-base/technologies/glonass/

    【讨论】:

    • 那么这是否意味着监听器顺序的调用很重要? GPSStatus.Listener应该在LocationListener之前调用,那么您可以确定GLONASS卫星是否用于最后定位?顺便说一句,我想知道 GPSxxx 在 API 中是否合适,因为似乎 GPSProvider 不只使用 gps 卫星,而是使用所有可用的卫星,如 GLONASS?
    • 你注册了一个监听器。你不叫它。当它想告诉你一些事情时,它会打电话给你。当您收到一个新的 GPS 位置可用的回调时,您可以按照我描述的顺序进行呼叫。
    • 关于您对 API 命名的投诉,在创建此 API 时没有可用的 GLONASS 硬件。在某些时候,他们可能会更改它的名称,但我对此表示怀疑。一旦事物有了名字,它们通常会坚持下去——在名字有意义之后很久。你有没有想过为什么叫“软盘”?大多数 1970 年后出生的人一生中从未见过软盘“软盘”。然而,他们就是这么叫的。
    • 也许我没有让我足够清楚,如果可能,请检查我的更新。
    • @SiavashAbdoli 据我所知。您可以发布一个新问题,看看是否能得到更多合格的答案。
    【解决方案2】:

    正如@DavidWasser 所说,有可能知道这一点。除了@DavidWasser 的回答,我还想分享一些代码。

    你应该有 LocationManager 对象:

    private LocationManager locationManager; 
    

    然后你初始化它:

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    

    使用implements LocationListener, GpsStatus.Listener 类请求位置更新:

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
            new GPSLocationListener());
    

    GPSLocationListener类:

    private class GPSLocationListener implements LocationListener,
            GpsStatus.Listener {
        private boolean isGPSFix;
    
        public void onGpsStatusChanged(int event) {
            checkGlonassFeature(); // the method which checks if locations from GLONASS or GPS
            switch (event) {
            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                if (mLastLocation != null)
                    isGPSFix = (SystemClock.elapsedRealtime() - lastGPStime) < 3000;
                if (isGPSFix) { // A fix has been acquired.
                    Toast toast = Toast.makeText(GPSLocationService.this, "GPS has a fix.", Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                } else { // The fix has been lost.
                    Toast toast = Toast.makeText(GPSLocationService.this, "GPS DOES NOT have a fix.", Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                }
                break;
            case GpsStatus.GPS_EVENT_FIRST_FIX:
                Toast toast = Toast.makeText(GPSLocationService.this, "GPS got first fix.", Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                isGPSFix = true;
                break;
            }
        }
    
        @Override
        public void onLocationChanged(Location location) {
            //  Do works here
        }
    
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            String statusDescription = "unknown";
            switch (status) {
            case LocationProvider.OUT_OF_SERVICE:
                statusDescription = "OUT_OF_SERVICE";
                break;
            case LocationProvider.AVAILABLE:
                statusDescription = "AVAILABLE";
                break;
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                statusDescription = "TEMPORARILY_UNAVAILABLE";
                break;
            }
        }
    
        @Override
        public void onProviderEnabled(String provider) {
            Toast toast = Toast.makeText(GPSLocationService.this, "GPS feature is active", Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }
    
        @Override
        public void onProviderDisabled(String provider) {
            Toast toast = Toast.makeText(GPSLocationService.this, "GPS feature is passive", Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }
    }
    

    最后是你的控制方法:

    public void checkGlonassFeature() {
        boolean isGPSFromGlonass = false;
        final GpsStatus gs = this.locationManager.getGpsStatus(null);
        final Iterable<GpsSatellite> it = gs.getSatellites();
        for (GpsSatellite sat : it) {
            if(sat.usedInFix()){
                if(sat.getPrn() > 65 && sat.getPrn() < 88)
                    isGPSFromGlonass = true;
                else
                    isGPSFromGlonass = false;
            }
            else
                isGPSFromGlonass = false;
        }
        if(isGPSFromGlonass){
            Toast toast = Toast.makeText(getBaseContext(), "Location from GLONASS", Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }
        else{
            Toast toast = Toast.makeText(getBaseContext(), "Location from GPS", Toast.LENGTH_SHORT);
            toast.setGravity(Gravity.CENTER, 0, 0);
            toast.show();
        }
    }
    

    请注意,它只是对上述答案的补充。 祝你好运。

    【讨论】:

      【解决方案3】:

      通常,大多数同时支持 Glonass 和 GPS 的设备都会结合来自两个星座的测量结果来确定位置。你没有得到一个或另一个,你通常会得到两个。 GPS 与 Glonass 星座的组合将取决于您所在的位置以及可见的卫星。

      正如上面的 Batuhan 所示,判断使用了哪些卫星的方法是遍历报告的卫星列表,找到修复中使用的卫星,然后查看它们的 ID 号。 1 到 32 的 ID 值用于 GPS 卫星,65 到 88 是 Glonass。要记住的一件事是,标准 android 有一个名为 gps.h 的脑死头文件,它不了解 Glonass 等其他星座,它只喜欢 GPS。许多制造商在解析从 GPS 驱动程序中提取的数据时会做一个简单的调整来解决这个问题,但它需要在 App 处理器端和 GPS 驱动程序代码内部完成。你不能只在一侧调整这些东西而不在另一侧进行匹配的更改。希望您的设备能够进行此更改,以便您可以查看所有星座的卫星 ID 号。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        • 2020-04-27
        • 2013-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多