diff --git a/res/values/strings.xml b/res/values/strings.xml index 1d2ba3843cc..1bdef29aece 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -684,7 +684,7 @@ Profile info - Location access + Location Security @@ -2354,6 +2354,27 @@ My Location + + Mode + + High accuracy + + Battery saving + + Device sensors only + + Recent location requests + + Location services + + Location mode + + Use GPS, Wi\u2011Fi and mobile networks to estimate location + + Use Wi\u2011Fi and mobile networks to estimate location + + Use GPS to pinpoint your location + Wi\u2011Fi & mobile network location @@ -4579,7 +4600,7 @@ Allow data exchange when the phone touches another device - Location access + Location Let apps use your location information diff --git a/res/xml/location_mode.xml b/res/xml/location_mode.xml new file mode 100644 index 00000000000..3627f119b01 --- /dev/null +++ b/res/xml/location_mode.xml @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml index 9af36dadbb7..293b7722d28 100644 --- a/res/xml/location_settings.xml +++ b/res/xml/location_settings.xml @@ -16,38 +16,20 @@ - - + + + android:key="recent_location_requests" + android:title="@string/location_category_recent_location_requests" /> - - - - - + diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 54f64c8988d..5d9349171d1 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -482,6 +482,7 @@ public class Settings extends PreferenceActivity WifiDisplaySettings.class.getName().equals(fragmentName) || BluetoothSettings.class.getName().equals(fragmentName) || DreamSettings.class.getName().equals(fragmentName) || + LocationSettings.class.getName().equals(fragmentName) || ToggleAccessibilityServicePreferenceFragment.class.getName().equals(fragmentName)) { intent.putExtra(EXTRA_UI_OPTIONS, ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW); } diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java new file mode 100644 index 00000000000..61816a136e9 --- /dev/null +++ b/src/com/android/settings/location/LocationEnabler.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.location; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.widget.CompoundButton; +import android.widget.Switch; + +/** + * LocationEnabler is a helper to manage the Location on/off master switch + * preference. It turns on/off Location master switch and ensures the summary + * of the preference reflects the current state. + */ +public final class LocationEnabler implements CompoundButton.OnCheckedChangeListener { + private final Context mContext; + private Switch mSwitch; + private boolean mValidListener; + + // TODO(lifu): listens to the system configuration change, and modify the switch state whenever + // necessary. + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + } + }; + + public LocationEnabler(Context context, Switch switch_) { + mContext = context; + mSwitch = switch_; + mValidListener = false; + } + + public void resume() { + mSwitch.setOnCheckedChangeListener(this); + mValidListener = true; + } + + public void pause() { + mSwitch.setOnCheckedChangeListener(null); + mValidListener = false; + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + // TODO(lifu): modify the actual location settings when the user flip the master switch. + } + + private void setChecked(boolean isChecked) { + if (isChecked != mSwitch.isChecked()) { + // set listener to null so that that code below doesn't trigger onCheckedChanged() + if (mValidListener) { + mSwitch.setOnCheckedChangeListener(null); + } + mSwitch.setChecked(isChecked); + if (mValidListener) { + mSwitch.setOnCheckedChangeListener(this); + } + } + } +} diff --git a/src/com/android/settings/location/LocationMode.java b/src/com/android/settings/location/LocationMode.java new file mode 100644 index 00000000000..3422b1a2ed4 --- /dev/null +++ b/src/com/android/settings/location/LocationMode.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.location; + +import android.content.Intent; +import android.preference.Preference; +import android.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; + +/** + * A page with 3 radio buttons to choose the location mode. + * + * There are 3 location modes when location access is enabled: + * + * High accuracy: use both GPS and network location. + * + * Battery saving: use network location only to reduce the power consumption. + * + * Sensors only: use GPS location only. + */ +public class LocationMode extends SettingsPreferenceFragment + implements Preference.OnPreferenceChangeListener { + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + createPreferenceHierarchy(); + } + + @Override + public void onResume() { + super.onResume(); + + // Make sure we reload the preference hierarchy since some of these settings + // depend on others... + createPreferenceHierarchy(); + } + + private PreferenceScreen createPreferenceHierarchy() { + PreferenceScreen root = getPreferenceScreen(); + if (root != null) { + root.removeAll(); + } + addPreferencesFromResource(R.xml.location_mode); + root = getPreferenceScreen(); + + return root; + } + + @Override + public int getHelpResource() { + return R.string.help_url_location_access; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + return true; + } +} diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java index 8ddde566133..8d0baae30d1 100644 --- a/src/com/android/settings/location/LocationSettings.java +++ b/src/com/android/settings/location/LocationSettings.java @@ -16,71 +16,43 @@ package com.android.settings.location; - -import android.content.ContentQueryMap; -import android.content.ContentResolver; -import android.content.Context; +import android.app.ActionBar; +import android.app.Activity; import android.content.Intent; -import android.database.Cursor; -import android.location.LocationManager; -import android.os.UserManager; -import android.preference.CheckBoxPreference; import android.preference.Preference; +import android.preference.PreferenceActivity; import android.preference.PreferenceScreen; -import android.preference.SwitchPreference; -import android.provider.Settings; -import android.util.AttributeSet; -import android.view.View; -import android.widget.TextView; +import android.util.Log; +import android.view.Gravity; +import android.widget.Switch; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; -import java.util.Observable; -import java.util.Observer; - /** * Location access settings. */ public class LocationSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { + private static final String TAG = LocationSettings.class.getSimpleName(); + private static final String KEY_LOCATION_MODE = "location_mode"; - // Location Settings - private static final String KEY_LOCATION_TOGGLE = "location_toggle"; - private static final String KEY_LOCATION_NETWORK = "location_network"; - private static final String KEY_LOCATION_GPS = "location_gps"; - private static final String KEY_ASSISTED_GPS = "assisted_gps"; - - private CheckBoxPreference mNetwork; - private CheckBoxPreference mGps; - private CheckBoxPreference mAssistedGps; - private SwitchPreference mLocationAccess; - - // These provide support for receiving notification when Location Manager settings change. - // This is necessary because the Network Location Provider can change settings - // if the user does not confirm enabling the provider. - private ContentQueryMap mContentQueryMap; - - private Observer mSettingsObserver; + private PreferenceScreen mLocationMode; + private LocationEnabler mLocationEnabler; @Override - public void onStart() { - super.onStart(); - // listen for Location Manager settings changes - Cursor settingsCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, null, - "(" + Settings.System.NAME + "=?)", - new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED}, - null); - mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null); + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + createPreferenceHierarchy(); } @Override - public void onStop() { - super.onStop(); - if (mSettingsObserver != null) { - mContentQueryMap.deleteObserver(mSettingsObserver); - } - mContentQueryMap.close(); + public void onResume() { + super.onResume(); + + // Make sure we reload the preference hierarchy since some of these settings + // depend on others... + createPreferenceHierarchy(); } private PreferenceScreen createPreferenceHierarchy() { @@ -91,148 +63,56 @@ public class LocationSettings extends SettingsPreferenceFragment addPreferencesFromResource(R.xml.location_settings); root = getPreferenceScreen(); - mLocationAccess = (SwitchPreference) root.findPreference(KEY_LOCATION_TOGGLE); - mNetwork = (CheckBoxPreference) root.findPreference(KEY_LOCATION_NETWORK); - mGps = (CheckBoxPreference) root.findPreference(KEY_LOCATION_GPS); - mAssistedGps = (CheckBoxPreference) root.findPreference(KEY_ASSISTED_GPS); + mLocationMode = (PreferenceScreen) root.findPreference((KEY_LOCATION_MODE)); + mLocationMode.setOnPreferenceClickListener( + new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + PreferenceActivity preferenceActivity = + (PreferenceActivity) getActivity(); + preferenceActivity.startPreferencePanel( + LocationMode.class.getName(), null, + R.string.location_mode_screen_title, null, LocationSettings.this, + 0); + return true; + } + }); - // Only enable these controls if this user is allowed to change location - // sharing settings. - final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); - boolean isToggleAllowed = !um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION); - if (mLocationAccess != null) mLocationAccess.setEnabled(isToggleAllowed); - if (mNetwork != null) mNetwork.setEnabled(isToggleAllowed); - if (mGps != null) mGps.setEnabled(isToggleAllowed); - if (mAssistedGps != null) mAssistedGps.setEnabled(isToggleAllowed); + Activity activity = getActivity(); + Switch actionBarSwitch = new Switch(activity); - mLocationAccess.setOnPreferenceChangeListener(this); - return root; - } - - @Override - public void onResume() { - super.onResume(); - - // Make sure we reload the preference hierarchy since some of these settings - // depend on others... - createPreferenceHierarchy(); - updateLocationToggles(); - - if (mSettingsObserver == null) { - mSettingsObserver = new Observer() { - @Override - public void update(Observable o, Object arg) { - updateLocationToggles(); - } - }; - } - - mContentQueryMap.addObserver(mSettingsObserver); - } - - @Override - public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { - final ContentResolver cr = getContentResolver(); - final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); - if (preference == mNetwork) { - if (!um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) { - Settings.Secure.setLocationProviderEnabled(cr, - LocationManager.NETWORK_PROVIDER, mNetwork.isChecked()); + if (activity instanceof PreferenceActivity) { + PreferenceActivity preferenceActivity = (PreferenceActivity) activity; + // Only show the master switch when we're not in multi-pane mode, and not being used as + // Setup Wizard. + if (preferenceActivity.onIsHidingHeaders() || !preferenceActivity.onIsMultiPane()) { + final int padding = activity.getResources().getDimensionPixelSize( + R.dimen.action_bar_switch_padding); + actionBarSwitch.setPaddingRelative(0, 0, padding, 0); + activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, + ActionBar.DISPLAY_SHOW_CUSTOM); + activity.getActionBar().setCustomView(actionBarSwitch, new ActionBar.LayoutParams( + ActionBar.LayoutParams.WRAP_CONTENT, + ActionBar.LayoutParams.WRAP_CONTENT, + Gravity.CENTER_VERTICAL | Gravity.END)); } - } else if (preference == mGps) { - boolean enabled = mGps.isChecked(); - if (!um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) { - Settings.Secure.setLocationProviderEnabled(cr, - LocationManager.GPS_PROVIDER, enabled); - if (mAssistedGps != null) { - mAssistedGps.setEnabled(enabled); - } - } - } else if (preference == mAssistedGps) { - Settings.Global.putInt(cr, Settings.Global.ASSISTED_GPS_ENABLED, - mAssistedGps.isChecked() ? 1 : 0); } else { - // If we didn't handle it, let preferences handle it. - return super.onPreferenceTreeClick(preferenceScreen, preference); + Log.wtf(TAG, "Current activity is not an instance of PreferenceActivity!"); } - return true; - } + mLocationEnabler = new LocationEnabler(activity, actionBarSwitch); + setHasOptionsMenu(true); - /* - * Creates toggles for each available location provider - */ - private void updateLocationToggles() { - ContentResolver res = getContentResolver(); - boolean gpsEnabled = Settings.Secure.isLocationProviderEnabled( - res, LocationManager.GPS_PROVIDER); - boolean networkEnabled = Settings.Secure.isLocationProviderEnabled( - res, LocationManager.NETWORK_PROVIDER); - mGps.setChecked(gpsEnabled); - mNetwork.setChecked(networkEnabled); - mLocationAccess.setChecked(gpsEnabled || networkEnabled); - if (mAssistedGps != null) { - mAssistedGps.setChecked(Settings.Global.getInt(res, - Settings.Global.ASSISTED_GPS_ENABLED, 2) == 1); - mAssistedGps.setEnabled(gpsEnabled); - } - } - - /** - * see confirmPatternThenDisableAndClear - */ - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - createPreferenceHierarchy(); - } - - /** Enable or disable all providers when the master toggle is changed. */ - private void onToggleLocationAccess(boolean checked) { - final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); - if (um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) { - return; - } - final ContentResolver cr = getContentResolver(); - Settings.Secure.setLocationProviderEnabled(cr, - LocationManager.GPS_PROVIDER, checked); - Settings.Secure.setLocationProviderEnabled(cr, - LocationManager.NETWORK_PROVIDER, checked); - updateLocationToggles(); - } - - @Override - public boolean onPreferenceChange(Preference pref, Object newValue) { - if (pref.getKey().equals(KEY_LOCATION_TOGGLE)) { - onToggleLocationAccess((Boolean) newValue); - } - return true; + return root; } @Override public int getHelpResource() { return R.string.help_url_location_access; } -} - -class WrappingSwitchPreference extends SwitchPreference { - - public WrappingSwitchPreference(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public WrappingSwitchPreference(Context context, AttributeSet attrs) { - super(context, attrs); - } @Override - protected void onBindView(View view) { - super.onBindView(view); - - TextView title = (TextView) view.findViewById(android.R.id.title); - if (title != null) { - title.setSingleLine(false); - title.setMaxLines(3); - } + public boolean onPreferenceChange(Preference preference, Object newValue) { + return true; } }