Android Location开关过程分析

时间:2022-09-06 22:38:14

Android Location开关过程分析

有同事发现目前车机的location位置在刷机(线刷之后),每次的location初始值(在settings中看见的)都不一致.之前对这个是一点都没接触过,所以今天拿出来研究下,凑一篇博客.

location的三种工作模式?

从settings->location界面来看,location主要有三种工作模式:

high_accuracy battery_saving sensors_only

对应代码:

//packages/apps/Settings/src/com/android/settings/location/LocationMode.java
int mode = Settings.Secure.LOCATION_MODE_OFF;//其实还有一种off模式
        if (emiter == mHighAccuracy) {
            mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
        } else if (emiter == mBatterySaving) {
            mode = Settings.Secure.LOCATION_MODE_BATTERY_SAVING;
        } else if (emiter == mSensorsOnly) {
            mode = Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
        }
setLocationMode(mode);

迅速找到setLocationMode

//packages/apps/Settings/src/com/android/settings/location/LocationSettingsBase.java
public void setLocationMode(int mode) {
        if (isRestricted()) {
            // Location toggling disabled by user restriction. Read the current location mode to
            // update the location master switch.
            if (Log.isLoggable(TAG, Log.INFO)) {
                Log.i(TAG, "Restricted user, not setting location mode");
            }
            mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
                    Settings.Secure.LOCATION_MODE_OFF);
            if (mActive) {
                onModeChanged(mode, true);
            }
            return;
        }
        Intent intent = new Intent(MODE_CHANGING_ACTION);
        intent.putExtra(CURRENT_MODE_KEY, mCurrentMode);
        intent.putExtra(NEW_MODE_KEY, mode);
        getActivity().sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
        Settings.Secure.putInt(getContentResolver(), Settings.Secure.LOCATION_MODE, mode);
        refreshLocationMode();
    }

看上去就是操作Settings.Secure数据库嘛.直接去找到吧:

private static final boolean setLocationModeForUser(ContentResolver cr, int mode,
                                                    int userId) {
  ...
    switch (mode) {
                    case LOCATION_MODE_OFF:
                        break;
                    case LOCATION_MODE_SENSORS_ONLY:
                        gps = true;
                        break;
                    case LOCATION_MODE_BATTERY_SAVING:
                        network = true;
                        break;
                    case LOCATION_MODE_HIGH_ACCURACY:
                        gps = true;
                        network = true;
                        break;
                    default:
                        throw new IllegalArgumentException("Invalid location mode: " + mode);
                }
          // Note it's important that we set the NLP mode first. The Google implementation
                // of NLP clears its NLP consent setting any time it receives a
                // LocationManager.PROVIDERS_CHANGED_ACTION broadcast and NLP is disabled. Also,
                // it shows an NLP consent dialog any time it receives the broadcast, NLP is
                // enabled, and the NLP consent is not set. If 1) we were to enable GPS first,
                // 2) a setup wizard has its own NLP consent UI that sets the NLP consent setting,
                // and 3) the receiver happened to complete before we enabled NLP, then the Google
                // NLP would detect the attempt to enable NLP and show a redundant NLP consent
                // dialog. Then the people who wrote the setup wizard would be sad.
                boolean nlpSuccess = Settings.Secure.setLocationProviderEnabledForUser(
                        cr, LocationManager.NETWORK_PROVIDER, network, userId);
                boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser(
                        cr, LocationManager.GPS_PROVIDER, gps, userId);
                return gpsSuccess && nlpSuccess;
}

public static final boolean setLocationProviderEnabledForUser(ContentResolver cr,
                String provider, boolean enabled, int userId) {
            synchronized (mLocationSettingsLock) {
                // to ensure thread safety, we write the provider name with a '+' or '-'
                // and let the SettingsProvider handle it rather than reading and modifying
                // the list of enabled providers.
                if (enabled) {
                    provider = "+" + provider;
                } else {
                    provider = "-" + provider;
                }
                return putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
                        userId);
            }
        }

是的,字段就是它了:Settings.Secure.LOCATION_PROVIDERS_ALLOWED

再看看实际机器测试:

老规矩,一条命令搞定

adb shell settings get secure location_providers_allowed

1.关闭location:

结果空

2.开location,high_accuracy模式

network,gps

3.开location,battery_saving模式

network

4.开location,sensors_only模式

gps

就这样.也算科普学习了!