/* * Copyright (C) 2013 The SlimRoms Project * Copyright (C) 2017 Peter Gregus for GravityBox Project (C3C076@xda) * 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.wrbug.gravitybox.nougat.quicksettings; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckedTextView; import android.widget.ListView; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.wrbug.gravitybox.nougat.GravityBoxSettings; import com.wrbug.gravitybox.nougat.ModStatusBar; import com.wrbug.gravitybox.nougat.R; import com.wrbug.gravitybox.nougat.Utils; import com.wrbug.gravitybox.nougat.managers.SysUiManagers; import com.wrbug.gravitybox.nougat.managers.GpsStatusMonitor; import de.robv.android.xposed.XSharedPreferences; public class LocationTileSlimkat extends QsTile implements GpsStatusMonitor.Listener { private static final Intent LOCATION_SETTINGS_INTENT = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); public static final Integer[] LOCATION_SETTINGS = new Integer[] { Settings.Secure.LOCATION_MODE_BATTERY_SAVING, Settings.Secure.LOCATION_MODE_SENSORS_ONLY, Settings.Secure.LOCATION_MODE_HIGH_ACCURACY }; private int mLastActiveMode; private Object mDetailAdapter; private List<Integer> mLocationList = new ArrayList<Integer>(); private boolean mQuickMode; public LocationTileSlimkat(Object host, String key, XSharedPreferences prefs, QsTileEventDistributor eventDistributor) throws Throwable { super(host, key, prefs, eventDistributor); mLastActiveMode = getLocationMode(); if(mLastActiveMode == Settings.Secure.LOCATION_MODE_OFF) { mLastActiveMode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; } } @Override public void initPreferences() { mQuickMode = Utils.isOxygenOs35Rom() ? true : mPrefs.getBoolean(GravityBoxSettings.PREF_KEY_LOCATION_TILE_QUICK_MODE, false); super.initPreferences(); } @Override public void onBroadcastReceived(Context context, Intent intent) { if (intent.getAction().equals(GravityBoxSettings.ACTION_PREF_QUICKSETTINGS_CHANGED)) { if (intent.hasExtra(GravityBoxSettings.EXTRA_LOCATION_TILE_QUICK_MODE)) { mQuickMode = intent.getBooleanExtra(GravityBoxSettings.EXTRA_LOCATION_TILE_QUICK_MODE, false); } } super.onBroadcastReceived(context, intent); } private void registerListener() { if (SysUiManagers.GpsMonitor != null) { SysUiManagers.GpsMonitor.registerListener(this); if (DEBUG) log(getKey() + ": Location Status Listener registered"); } } private void unregisterListener() { if (SysUiManagers.GpsMonitor != null) { SysUiManagers.GpsMonitor.unregisterListener(this); if (DEBUG) log(getKey() + ": Location Status Listener unregistered"); } } @Override public void setListening(boolean listening) { if (listening && mEnabled) { registerListener(); } else { unregisterListener(); } } private boolean isLocationEnabled() { return (getLocationMode() != Settings.Secure.LOCATION_MODE_OFF); } private int getLocationMode() { return (SysUiManagers.GpsMonitor == null ? 0 : SysUiManagers.GpsMonitor.getLocationMode()); } private void setLocationMode(int mode) { if (SysUiManagers.GpsMonitor != null) { SysUiManagers.GpsMonitor.setLocationMode(mode); } } private void switchLocationMode() { int currentMode = getLocationMode(); switch (currentMode) { case Settings.Secure.LOCATION_MODE_OFF: setLocationMode(Settings.Secure.LOCATION_MODE_BATTERY_SAVING); break; case Settings.Secure.LOCATION_MODE_BATTERY_SAVING: setLocationMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY); break; case Settings.Secure.LOCATION_MODE_SENSORS_ONLY: setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY); break; case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY: setLocationMode(Settings.Secure.LOCATION_MODE_OFF); break; } } private void setLocationEnabled(boolean enabled) { if (SysUiManagers.GpsMonitor != null) { // Store last active mode if we are switching off // so we can restore it at the next enable if(!enabled) { mLastActiveMode = getLocationMode(); } final int mode = enabled ? mLastActiveMode : Settings.Secure.LOCATION_MODE_OFF; SysUiManagers.GpsMonitor.setLocationMode(mode); } } @Override public void onLocationModeChanged(int mode) { if (DEBUG) log(getKey() + ": onLocationModeChanged: mode=" + mode); refreshState(); } @Override public void onGpsEnabledChanged(boolean gpsEnabled) { } @Override public void onGpsFixChanged(boolean gpsFixed) { } @Override public void handleUpdateState(Object state, Object arg) { mState.booleanValue = true; mState.visible = true; int locationMode = getLocationMode(); switch (locationMode) { case Settings.Secure.LOCATION_MODE_SENSORS_ONLY: mState.icon = mGbContext.getDrawable(R.drawable.ic_qs_location_on); break; case Settings.Secure.LOCATION_MODE_BATTERY_SAVING: mState.icon = mGbContext.getDrawable(R.drawable.ic_qs_location_battery_saving); break; case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY: mState.icon = mGbContext.getDrawable(R.drawable.ic_qs_location_on); break; case Settings.Secure.LOCATION_MODE_OFF: mState.icon = mGbContext.getDrawable(R.drawable.ic_qs_location_off); mState.booleanValue = false; break; } mState.label = GpsStatusMonitor.getModeLabel(mContext, locationMode); super.handleUpdateState(state, arg); } @Override public void handleClick() { if (mQuickMode) { switchLocationMode(); } else if (supportsDualTargets()) { setLocationEnabled(!isLocationEnabled()); } else { showDetail(true); } super.handleClick(); } @Override public boolean handleLongClick() { if (supportsDualTargets() || Utils.isOxygenOs35Rom()) { startSettingsActivity(LOCATION_SETTINGS_INTENT); } else if (mQuickMode) { showDetail(true); } else { setLocationEnabled(!isLocationEnabled()); } return true; } @Override public boolean supportsHideOnChange() { return supportsDualTargets(); } @Override public boolean handleSecondaryClick() { showDetail(true); return true; } @Override public void handleDestroy() { mDetailAdapter = null; mLocationList.clear(); mLocationList = null; super.handleDestroy(); } @Override public Object getDetailAdapter() { if (mDetailAdapter == null) { mDetailAdapter = QsDetailAdapterProxy.createProxy( mContext.getClassLoader(), new LocationDetailAdapter()); } return mDetailAdapter; } private class AdvancedLocationAdapter extends ArrayAdapter<Integer> { public AdvancedLocationAdapter(Context context) { super(context, android.R.layout.simple_list_item_single_choice, mLocationList); } @SuppressLint("ViewHolder") @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(mContext); CheckedTextView label = (CheckedTextView) inflater.inflate( android.R.layout.simple_list_item_single_choice, parent, false); label.setText(GpsStatusMonitor.getModeLabel(mContext, getItem(position))); return label; } } private class LocationDetailAdapter implements QsDetailAdapterProxy.Callback, AdapterView.OnItemClickListener { private AdvancedLocationAdapter mAdapter; private QsDetailItemsList mDetails; @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { setLocationMode((Integer) parent.getItemAtPosition(position)); } @Override public int getTitle() { return mContext.getResources().getIdentifier("quick_settings_location_label", "string", ModStatusBar.PACKAGE_NAME); } @Override public Boolean getToggleState() { boolean state = isLocationEnabled(); rebuildLocationList(state); return state; } @Override public View createDetailView(Context context, View convertView, ViewGroup parent) throws Throwable { if (mDetails == null) { mDetails = QsDetailItemsList.create(context, parent); mDetails.setEmptyState(R.drawable.ic_qs_location_off, GpsStatusMonitor.getModeLabel(mContext, Settings.Secure.LOCATION_MODE_OFF)); mAdapter = new AdvancedLocationAdapter(context); mDetails.setAdapter(mAdapter); final ListView list = mDetails.getListView(); list.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); list.setOnItemClickListener(this); } return mDetails.getView(); } @Override public Intent getSettingsIntent() { return LOCATION_SETTINGS_INTENT; } @Override public void setToggleState(boolean state) { setLocationEnabled(state); rebuildLocationList(state); fireToggleStateChanged(state); if (!state) { showDetail(false); } } private void rebuildLocationList(boolean populate) { mLocationList.clear(); if (populate) { mLocationList.addAll(Arrays.asList(LOCATION_SETTINGS)); mDetails.getListView().setItemChecked(mAdapter.getPosition( getLocationMode()), true); } mAdapter.notifyDataSetChanged(); } } }