Cherish:Add some button settings
Hardware key: Customization support[2/2] Volume Rocker Wake [2/2] Volume key cursor control (2/2) Co-authored-by: jhenrique09 <jhsv09@gmail.com> Co-authored-by: Max <xyyx@mail.ru> Co-authored-by: bigrushdog <randall.rushing@gmail.com> Signed-off-by: Hưng Phan <phandinhhungvp2001@gmail.com>
This commit is contained in:
@@ -18,44 +18,76 @@
|
||||
package com.cherish.settings.fragments;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.res.Resources;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.os.Vibrator;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.internal.lineage.hardware.LineageHardwareManager;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.cherish.CherishUtils;
|
||||
import com.android.internal.util.hwkeys.ActionConstants;
|
||||
import com.android.internal.util.hwkeys.ActionUtils;
|
||||
import com.android.settings.R;
|
||||
|
||||
import com.cherish.settings.preferences.SystemSettingSwitchPreference;
|
||||
import com.cherish.settings.preferences.SecureSettingSwitchPreference;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
|
||||
import com.cherish.settings.preferences.CustomSeekBarPreference;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.cherish.settings.preferences.ActionFragment;
|
||||
import com.cherish.settings.preferences.SecureSettingSwitchPreference;
|
||||
import com.cherish.settings.preferences.SystemSettingSwitchPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
|
||||
public class ButtonSettings extends SettingsPreferenceFragment implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String KEY_NAVBAR_INVERSE = "navigation_bar_inverse";
|
||||
private static final String KEY_NAVIGATION_COMPACT_LAYOUT = "navigation_bar_compact_layout";
|
||||
|
||||
private SystemSettingSwitchPreference mNavbarInverse;
|
||||
private SystemSettingSwitchPreference mNavigationCompactLayout;
|
||||
|
||||
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
|
||||
public class ButtonSettings extends ActionFragment implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String HWKEY_DISABLE = "hardware_keys_disable";
|
||||
private static final String KEY_NAVBAR_INVERSE = "navigation_bar_inverse";
|
||||
private static final String KEY_NAVIGATION_COMPACT_LAYOUT = "navigation_bar_compact_layout";
|
||||
private static final String KEY_SWAP_CAPACITIVE_KEYS = "swap_capacitive_keys";
|
||||
|
||||
// category keys
|
||||
private static final String CATEGORY_HWKEY = "hardware_keys";
|
||||
private static final String CATEGORY_BACK = "back_key";
|
||||
private static final String CATEGORY_HOME = "home_key";
|
||||
private static final String CATEGORY_MENU = "menu_key";
|
||||
private static final String CATEGORY_ASSIST = "assist_key";
|
||||
private static final String CATEGORY_APPSWITCH = "app_switch_key";
|
||||
private static final String CATEGORY_VOLUME = "volume_keys";
|
||||
private static final String CATEGORY_POWER = "power_key";
|
||||
|
||||
// Masks for checking presence of hardware keys.
|
||||
// Must match values in frameworks/base/core/res/res/values/config.xml
|
||||
public static final int KEY_MASK_HOME = 0x01;
|
||||
public static final int KEY_MASK_BACK = 0x02;
|
||||
public static final int KEY_MASK_MENU = 0x04;
|
||||
public static final int KEY_MASK_ASSIST = 0x08;
|
||||
public static final int KEY_MASK_APP_SWITCH = 0x10;
|
||||
public static final int KEY_MASK_CAMERA = 0x20;
|
||||
public static final int KEY_MASK_VOLUME = 0x40;
|
||||
|
||||
private PreferenceCategory mButtonBackLightCategory;
|
||||
private PreferenceCategory mHwKeyCategory;
|
||||
private SecureSettingSwitchPreference mSwapCapacitiveKeys;
|
||||
private SwitchPreference mHwKeyDisable;
|
||||
private SystemSettingSwitchPreference mNavbarInverse;
|
||||
private SystemSettingSwitchPreference mNavigationCompactLayout;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
@@ -65,47 +97,133 @@ public class ButtonSettings extends SettingsPreferenceFragment implements
|
||||
final Resources res = getResources();
|
||||
final ContentResolver resolver = getActivity().getContentResolver();
|
||||
final PreferenceScreen prefScreen = getPreferenceScreen();
|
||||
|
||||
final boolean isThreeButtonNavbarEnabled = EvolutionUtils.isThemeEnabled("com.android.internal.systemui.navbar.threebutton");
|
||||
|
||||
mSwapCapacitiveKeys = findPreference(KEY_SWAP_CAPACITIVE_KEYS);
|
||||
if (mSwapCapacitiveKeys != null && !isKeySwapperSupported(getActivity())) {
|
||||
prefScreen.removePreference(mSwapCapacitiveKeys);
|
||||
mSwapCapacitiveKeys = null;
|
||||
}
|
||||
|
||||
final boolean needsNavbar = ActionUtils.hasNavbarByDefault(getActivity());
|
||||
mHwKeyCategory = (PreferenceCategory) prefScreen
|
||||
.findPreference(CATEGORY_HWKEY);
|
||||
int keysDisabled = 0;
|
||||
if (!needsNavbar) {
|
||||
mHwKeyDisable = (SwitchPreference) findPreference(HWKEY_DISABLE);
|
||||
keysDisabled = Settings.System.getIntForUser(getContentResolver(),
|
||||
Settings.System.HARDWARE_KEYS_DISABLE, 0,
|
||||
UserHandle.USER_CURRENT);
|
||||
mHwKeyDisable.setChecked(keysDisabled != 0);
|
||||
mHwKeyDisable.setOnPreferenceChangeListener(this);
|
||||
} else {
|
||||
prefScreen.removePreference(mHwKeyCategory);
|
||||
}
|
||||
|
||||
// bits for hardware keys present on device
|
||||
final int deviceKeys = getResources().getInteger(
|
||||
com.android.internal.R.integer.config_deviceHardwareKeys);
|
||||
// read bits for present hardware keys
|
||||
final boolean hasHomeKey = (deviceKeys & KEY_MASK_HOME) != 0;
|
||||
final boolean hasBackKey = (deviceKeys & KEY_MASK_BACK) != 0;
|
||||
final boolean hasMenuKey = (deviceKeys & KEY_MASK_MENU) != 0;
|
||||
final boolean hasAssistKey = (deviceKeys & KEY_MASK_ASSIST) != 0;
|
||||
final boolean hasAppSwitchKey = (deviceKeys & KEY_MASK_APP_SWITCH) != 0;
|
||||
// load categories and init/remove preferences based on device
|
||||
// configuration
|
||||
final PreferenceCategory backCategory = (PreferenceCategory) prefScreen
|
||||
.findPreference(CATEGORY_BACK);
|
||||
final PreferenceCategory homeCategory = (PreferenceCategory) prefScreen
|
||||
.findPreference(CATEGORY_HOME);
|
||||
final PreferenceCategory menuCategory = (PreferenceCategory) prefScreen
|
||||
.findPreference(CATEGORY_MENU);
|
||||
final PreferenceCategory assistCategory = (PreferenceCategory) prefScreen
|
||||
.findPreference(CATEGORY_ASSIST);
|
||||
final PreferenceCategory appSwitchCategory = (PreferenceCategory) prefScreen
|
||||
.findPreference(CATEGORY_APPSWITCH);
|
||||
// back key
|
||||
if (!hasBackKey) {
|
||||
prefScreen.removePreference(backCategory);
|
||||
}
|
||||
// home key
|
||||
if (!hasHomeKey) {
|
||||
prefScreen.removePreference(homeCategory);
|
||||
}
|
||||
// App switch key (recents)
|
||||
if (!hasAppSwitchKey) {
|
||||
prefScreen.removePreference(appSwitchCategory);
|
||||
}
|
||||
// menu key
|
||||
if (!hasMenuKey) {
|
||||
prefScreen.removePreference(menuCategory);
|
||||
}
|
||||
// search/assist key
|
||||
if (!hasAssistKey) {
|
||||
prefScreen.removePreference(assistCategory);
|
||||
}
|
||||
// let super know we can load ActionPreferences
|
||||
onPreferenceScreenLoaded(ActionConstants.getDefaults(ActionConstants.HWKEYS));
|
||||
|
||||
// load preferences first
|
||||
setActionPreferencesEnabled(keysDisabled == 0);
|
||||
|
||||
final boolean isThreeButtonNavbarEnabled = CherishUtils.isThemeEnabled("com.android.internal.systemui.navbar.threebutton");
|
||||
mNavbarInverse = (SystemSettingSwitchPreference) findPreference(KEY_NAVBAR_INVERSE);
|
||||
mNavbarInverse.setEnabled(isThreeButtonNavbarEnabled);
|
||||
mNavigationCompactLayout = (SystemSettingSwitchPreference) findPreference(KEY_NAVIGATION_COMPACT_LAYOUT);
|
||||
mNavigationCompactLayout.setEnabled(isThreeButtonNavbarEnabled);
|
||||
}
|
||||
|
||||
private static boolean isKeyDisablerSupported(Context context) {
|
||||
final LineageHardwareManager hardware = LineageHardwareManager.getInstance(context);
|
||||
return hardware.isSupported(LineageHardwareManager.FEATURE_KEY_DISABLE);
|
||||
}
|
||||
|
||||
private static boolean isKeySwapperSupported(Context context) {
|
||||
final LineageHardwareManager hardware = LineageHardwareManager.getInstance(context);
|
||||
return hardware.isSupported(LineageHardwareManager.FEATURE_KEY_SWAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
ContentResolver resolver = getActivity().getContentResolver();
|
||||
if (preference == mHwKeyDisable) {
|
||||
boolean value = (Boolean) newValue;
|
||||
Settings.System.putInt(getContentResolver(), Settings.System.HARDWARE_KEYS_DISABLE,
|
||||
value ? 1 : 0);
|
||||
setActionPreferencesEnabled(!value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.CHERISH_SETTINGS;
|
||||
return MetricsEvent.CHERISH_SETTINGS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
ArrayList<SearchIndexableResource> result =
|
||||
new ArrayList<SearchIndexableResource>();
|
||||
SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.cherish_settings_button;
|
||||
result.add(sir);
|
||||
return result;
|
||||
}
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.cherish_settings_button) {
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
List<String> keys = super.getNonIndexableKeys(context);
|
||||
|
||||
LineageHardwareManager mLineageHardware = LineageHardwareManager.getInstance(context);
|
||||
|
||||
if (!isKeyDisablerSupported(context)) {
|
||||
keys.add(HWKEY_DISABLE);
|
||||
keys.add(CATEGORY_HWKEY);
|
||||
keys.add(CATEGORY_BACK);
|
||||
keys.add(CATEGORY_HOME);
|
||||
keys.add(CATEGORY_MENU);
|
||||
keys.add(CATEGORY_ASSIST);
|
||||
keys.add(CATEGORY_APPSWITCH);
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,67 +1,194 @@
|
||||
package com.cherish.settings.fragments;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.PreferenceFragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
|
||||
public class VolumeRockerSettings extends SettingsPreferenceFragment implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
private static final String TAG = "VolumeSteps";
|
||||
private static final String VOLUME_STEP_DEFAULTS = "volume_step_defaults";
|
||||
private static final String FIRST_RUN_KEY = "first_run";
|
||||
|
||||
// base map of all preference keys and the associated stream
|
||||
private static final Map<String, Integer> volume_map = new HashMap<String, Integer>();
|
||||
static {
|
||||
volume_map.put("volume_steps_alarm", new Integer(AudioManager.STREAM_ALARM));
|
||||
volume_map.put("volume_steps_dtmf", new Integer(AudioManager.STREAM_DTMF));
|
||||
volume_map.put("volume_steps_music", new Integer(AudioManager.STREAM_MUSIC));
|
||||
volume_map.put("volume_steps_notification", new Integer(AudioManager.STREAM_NOTIFICATION));
|
||||
volume_map.put("volume_steps_ring", new Integer(AudioManager.STREAM_RING));
|
||||
volume_map.put("volume_steps_system", new Integer(AudioManager.STREAM_SYSTEM));
|
||||
volume_map.put("volume_steps_voice_call", new Integer(AudioManager.STREAM_VOICE_CALL));
|
||||
}
|
||||
|
||||
// entries to remove on non-telephony devices
|
||||
private static final Set<String> telephony_set = new HashSet<String>();
|
||||
static {
|
||||
telephony_set.add("volume_steps_dtmf");
|
||||
telephony_set.add("volume_steps_ring");
|
||||
telephony_set.add("volume_steps_voice_call");
|
||||
}
|
||||
|
||||
// set of available pref keys after device configuration filter
|
||||
private Set<String> mAvailableKeys = new HashSet<String>();
|
||||
private AudioManager mAudioManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.cherish_settings_volume);
|
||||
mAudioManager = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
final PreferenceScreen prefScreen = getPreferenceScreen();
|
||||
mAvailableKeys = volume_map.keySet();
|
||||
|
||||
// remove invalid audio stream prefs
|
||||
boolean isPhone = TelephonyManager.getDefault().getCurrentPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
|
||||
|
||||
if (!isPhone) {
|
||||
// remove telephony keys from available set
|
||||
mAvailableKeys.removeAll(telephony_set);
|
||||
for (String key : telephony_set) {
|
||||
Preference toRemove = prefScreen.findPreference(key);
|
||||
if (toRemove != null) {
|
||||
prefScreen.removePreference(toRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check prefs for initial run of this fragment
|
||||
final boolean firstRun = checkForFirstRun();
|
||||
|
||||
// entries array isn't translatable ugh
|
||||
final String defEntry = getString(R.string.volume_steps_reset);
|
||||
|
||||
// initialize prefs: set defaults if first run, set listeners and update values
|
||||
for (String key : mAvailableKeys) {
|
||||
Preference pref = prefScreen.findPreference(key);
|
||||
if (pref == null || !(pref instanceof ListPreference)) {
|
||||
continue;
|
||||
}
|
||||
final ListPreference listPref = (ListPreference) pref;
|
||||
int steps = mAudioManager.getStreamMaxVolume(volume_map.get(key));
|
||||
if (firstRun) {
|
||||
saveDefaultSteps(listPref, steps);
|
||||
}
|
||||
final int defSteps = getDefaultSteps(listPref);
|
||||
CharSequence[] entries = new CharSequence[listPref.getEntries().length + 1];
|
||||
CharSequence[] values = new CharSequence[listPref.getEntryValues().length + 1];
|
||||
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
if (i == 0) {
|
||||
entries[i] = defEntry;
|
||||
values[i] = String.valueOf(defSteps);
|
||||
continue;
|
||||
}
|
||||
entries[i] = listPref.getEntries()[i - 1];
|
||||
values[i] = listPref.getEntryValues()[i - 1];
|
||||
}
|
||||
listPref.setEntries(entries);
|
||||
listPref.setEntryValues(values);
|
||||
updateVolumeStepPrefs(listPref, steps);
|
||||
listPref.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
||||
public boolean onPreferenceChange(Preference preference, Object objValue) {
|
||||
if (preference.hasKey() && mAvailableKeys.contains(preference.getKey())) {
|
||||
commitVolumeSteps(preference, Integer.parseInt(objValue.toString()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private SharedPreferences getDefaultStepsPrefs() {
|
||||
return getActivity().getSharedPreferences(VOLUME_STEP_DEFAULTS,
|
||||
Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
// test for initial run of this fragment
|
||||
private boolean checkForFirstRun() {
|
||||
String isFirstRun = getDefaultStepsPrefs().getString(FIRST_RUN_KEY, null);
|
||||
if (isFirstRun == null) {
|
||||
getDefaultStepsPrefs().edit().putString(FIRST_RUN_KEY, "first_run_initialized").commit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getDefaultSteps(Preference pref) {
|
||||
if (pref == null || !(pref instanceof ListPreference)) {
|
||||
// unlikely
|
||||
return -1;
|
||||
}
|
||||
String key = pref.getKey();
|
||||
String value = getDefaultStepsPrefs().getString(key, null);
|
||||
if (value == null) {
|
||||
// unlikely
|
||||
return -1;
|
||||
}
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
// on the initial run, let's store true device defaults in sharedPrefs
|
||||
private void saveDefaultSteps(Preference volPref, int defaultSteps) {
|
||||
String key = volPref.getKey();
|
||||
getDefaultStepsPrefs().edit().putString(key, String.valueOf(defaultSteps)).commit();
|
||||
}
|
||||
|
||||
private void updateVolumeStepPrefs(Preference pref, int steps) {
|
||||
if (pref == null || !(pref instanceof ListPreference)) {
|
||||
return;
|
||||
}
|
||||
final ListPreference listPref = (ListPreference) pref;
|
||||
listPref.setSummary(String.valueOf(steps));
|
||||
listPref.setValue(String.valueOf(steps));
|
||||
}
|
||||
|
||||
private void commitVolumeSteps(Preference pref, int steps) {
|
||||
Settings.System.putInt(getActivity().getContentResolver(), pref.getKey(), steps);
|
||||
mAudioManager.setStreamMaxVolume(volume_map.get(pref.getKey()), steps);
|
||||
updateVolumeStepPrefs(pref, steps);
|
||||
Log.i(TAG, "Volume steps:" + pref.getKey() + "" + String.valueOf(steps));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.CHERISH_SETTINGS;
|
||||
return MetricsEvent.CHERISH_SETTINGS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
ArrayList<SearchIndexableResource> result =
|
||||
new ArrayList<SearchIndexableResource>();
|
||||
SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.cherish_settings_volume;
|
||||
result.add(sir);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
List<String> keys = super.getNonIndexableKeys(context);
|
||||
return keys;
|
||||
}
|
||||
};
|
||||
}
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.cherish_settings_volume);
|
||||
}
|
||||
261
src/com/cherish/settings/preferences/ActionFragment.java
Normal file
261
src/com/cherish/settings/preferences/ActionFragment.java
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright (C) 2015 TeamEos 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.
|
||||
*
|
||||
* Handle assignable action dialogs and instances of the ActionPreference
|
||||
* class that holds target widget state
|
||||
*/
|
||||
|
||||
package com.cherish.settings.preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.util.hwkeys.ActionConstants.Defaults;
|
||||
import com.android.internal.util.hwkeys.ActionHandler;
|
||||
import com.android.internal.util.hwkeys.Config;
|
||||
import com.android.internal.util.hwkeys.Config.ActionConfig;
|
||||
import com.android.internal.util.hwkeys.Config.ButtonConfig;
|
||||
|
||||
import com.cherish.settings.preferences.ShortcutPickHelper;
|
||||
import com.cherish.settings.preferences.ActionPreference;
|
||||
import com.cherish.settings.preferences.CustomActionListAdapter;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
|
||||
public class ActionFragment extends SettingsPreferenceFragment implements
|
||||
ShortcutPickHelper.OnPickListener {
|
||||
|
||||
private static final int DIALOG_CATEGORY = 69;
|
||||
private static final int DIALOG_CUSTOM_ACTIONS = 70;
|
||||
private static final String KEY_FOCUSED_PREFERENCE = "key_focused_preference";
|
||||
|
||||
private ShortcutPickHelper mPicker;
|
||||
protected ArrayList<ActionPreference> mPrefHolder;
|
||||
private String mHolderTag;
|
||||
private Defaults mDefaults;
|
||||
private ArrayList<ButtonConfig> mButtons;
|
||||
private ArrayList<ButtonConfig> mDefaultButtons;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
if (icicle != null) {
|
||||
String holderTag = icicle.getString(KEY_FOCUSED_PREFERENCE);
|
||||
if (holderTag != null) {
|
||||
mHolderTag = holderTag;
|
||||
}
|
||||
}
|
||||
mPicker = new ShortcutPickHelper(getActivity(), this);
|
||||
mPrefHolder = new ArrayList<ActionPreference>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
mPicker.onActivityResult(requestCode, resultCode, data);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shortcutPicked(String uri, String friendlyName, boolean isApplication) {
|
||||
// activity dialogs pass null here if they are dismissed
|
||||
// if null, do nothing, no harm
|
||||
if (uri == null) {
|
||||
return;
|
||||
}
|
||||
findAndUpdatePreference(new ActionConfig(getActivity(), uri), mHolderTag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
if (preference instanceof ActionPreference) {
|
||||
mHolderTag = ((ActionPreference)preference).getTag();
|
||||
showDialog(DIALOG_CATEGORY);
|
||||
return true;
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (mDefaults != null) {
|
||||
loadAndSetConfigs();
|
||||
onActionPolicyEnforced(mPrefHolder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (mHolderTag != null) {
|
||||
outState.putString(KEY_FOCUSED_PREFERENCE, mHolderTag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(int dialogId) {
|
||||
switch (dialogId) {
|
||||
case DIALOG_CATEGORY: {
|
||||
Dialog dialog;
|
||||
final DialogInterface.OnClickListener categoryClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int item) {
|
||||
onTargetChange(getResources().getStringArray(R.array.action_dialog_values)[item]);
|
||||
dialog.dismiss();
|
||||
}
|
||||
};
|
||||
dialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.choose_action_title)
|
||||
.setItems(getResources().getStringArray(R.array.action_dialog_entries),
|
||||
categoryClickListener)
|
||||
.setNegativeButton(getString(android.R.string.cancel), null)
|
||||
.create();
|
||||
return dialog;
|
||||
}
|
||||
case DIALOG_CUSTOM_ACTIONS: {
|
||||
Dialog dialog;
|
||||
final CustomActionListAdapter adapter = new CustomActionListAdapter(getActivity());
|
||||
if (!usesExtendedActionsList()) {
|
||||
adapter.removeAction(ActionHandler.SYSTEMUI_TASK_HOME);
|
||||
adapter.removeAction(ActionHandler.SYSTEMUI_TASK_BACK);
|
||||
}
|
||||
final DialogInterface.OnClickListener customActionClickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int item) {
|
||||
findAndUpdatePreference(adapter.getItem(item), mHolderTag);
|
||||
dialog.dismiss();
|
||||
}
|
||||
};
|
||||
dialog = new AlertDialog.Builder(getActivity())
|
||||
.setTitle(getString(R.string.action_entry_custom_action))
|
||||
.setAdapter(adapter, customActionClickListener)
|
||||
.setNegativeButton(getString(android.R.string.cancel), null)
|
||||
.create();
|
||||
return dialog;
|
||||
}
|
||||
}
|
||||
return super.onCreateDialog(dialogId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDialogMetricsCategory(int dialogId) {
|
||||
switch (dialogId) {
|
||||
case DIALOG_CATEGORY:
|
||||
case DIALOG_CUSTOM_ACTIONS:
|
||||
return MetricsEvent.CHERISH_SETTINGS;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// subclass overrides to include back and home actions
|
||||
protected boolean usesExtendedActionsList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void onActionPolicyEnforced(ArrayList<ActionPreference> prefs) {
|
||||
}
|
||||
|
||||
protected void setActionPreferencesEnabled(boolean enabled) {
|
||||
for (ActionPreference pref : mPrefHolder) {
|
||||
pref.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* load our button lists and ActionPreferences map button action targets from preference keys
|
||||
* and defaults config maps subclass is required to set desired Defaults interface int
|
||||
* ActionContants
|
||||
*/
|
||||
protected void onPreferenceScreenLoaded(Defaults defaults) {
|
||||
mDefaults = defaults;
|
||||
final PreferenceScreen prefScreen = getPreferenceScreen();
|
||||
for (int i = 0; i < prefScreen.getPreferenceCount(); i++) {
|
||||
Preference pref = prefScreen.getPreference(i);
|
||||
if (pref instanceof PreferenceCategory) {
|
||||
PreferenceCategory cat = (PreferenceCategory) pref;
|
||||
for (int j = 0; j < cat.getPreferenceCount(); j++) {
|
||||
Preference child = cat.getPreference(j);
|
||||
if (child instanceof ActionPreference) {
|
||||
mPrefHolder.add((ActionPreference) child);
|
||||
}
|
||||
}
|
||||
} else if (pref instanceof ActionPreference) {
|
||||
mPrefHolder.add((ActionPreference) pref);
|
||||
}
|
||||
}
|
||||
loadAndSetConfigs();
|
||||
}
|
||||
|
||||
protected void loadAndSetConfigs() {
|
||||
mButtons = Config.getConfig(getActivity(), mDefaults);
|
||||
mDefaultButtons = Config.getDefaultConfig(getActivity(), mDefaults);
|
||||
for (ActionPreference pref : mPrefHolder) {
|
||||
pref.setDefaults(mDefaults);
|
||||
ButtonConfig button = mButtons.get(pref.getConfigMap().button);
|
||||
ActionConfig action = button.getActionConfig(pref.getConfigMap().action);
|
||||
pref.setActionConfig(action);
|
||||
ButtonConfig defButton = mDefaultButtons.get(pref.getConfigMap().button);
|
||||
ActionConfig defAction = defButton.getActionConfig(pref.getConfigMap().action);
|
||||
pref.setDefaultActionConfig(defAction);
|
||||
}
|
||||
}
|
||||
|
||||
private void onTargetChange(String uri) {
|
||||
if (uri == null) {
|
||||
return;
|
||||
} else if (uri.equals(getString(R.string.action_value_default_action))) {
|
||||
findAndUpdatePreference(null, mHolderTag);
|
||||
} else if (uri.equals(getString(R.string.action_value_select_app))) {
|
||||
mPicker.pickShortcut(null, null, getId());
|
||||
} else if (uri.equals(getString(R.string.action_value_custom_action))) {
|
||||
showDialog(DIALOG_CUSTOM_ACTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
protected void findAndUpdatePreference(ActionConfig action, String tag) {
|
||||
for (ActionPreference pref : mPrefHolder) {
|
||||
if (pref.getTag().equals(mHolderTag)) {
|
||||
if (action == null) {
|
||||
action = pref.getDefaultActionConfig();
|
||||
}
|
||||
pref.setActionConfig(action);
|
||||
ButtonConfig button = mButtons.get(pref.getConfigMap().button);
|
||||
ActionConfig newAction = pref.getActionConfig();
|
||||
button.setActionConfig(newAction, pref.getConfigMap().action);
|
||||
mButtons = Config.replaceButtonAtPosition(mButtons, button, pref.getConfigMap());
|
||||
Config.setConfig(getActivity(), mDefaults, mButtons);
|
||||
onActionPolicyEnforced(mPrefHolder);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.CHERISH_SETTINGS;
|
||||
}
|
||||
}
|
||||
134
src/com/cherish/settings/preferences/ActionPreference.java
Normal file
134
src/com/cherish/settings/preferences/ActionPreference.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2015 TeamEos 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.
|
||||
*
|
||||
* Simple preference class implementing ActionHolder interface to assign
|
||||
* actions to buttons. It is ABSOLUTELY IMPERITIVE that the preference
|
||||
* key is identical to the target ConfigMap tag in ActionConstants
|
||||
*/
|
||||
|
||||
package com.cherish.settings.preferences;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.android.internal.util.hwkeys.ActionConstants.ConfigMap;
|
||||
import com.android.internal.util.hwkeys.ActionConstants.Defaults;
|
||||
import com.android.internal.util.hwkeys.ActionHolder;
|
||||
import com.android.internal.util.hwkeys.Config.ActionConfig;
|
||||
import com.android.internal.util.hwkeys.Config.ButtonConfig;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class ActionPreference extends Preference implements ActionHolder {
|
||||
private Defaults mDefaults;
|
||||
private ConfigMap mMap;
|
||||
private ActionConfig mAction;
|
||||
private ActionConfig mDefaultAction;
|
||||
|
||||
public ActionPreference(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionPreference(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ActionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public ActionPreference(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTag() {
|
||||
return this.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTag(String tag) {
|
||||
this.setKey(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Defaults getDefaults() {
|
||||
return mDefaults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaults(Defaults defaults) {
|
||||
mDefaults = defaults;
|
||||
final String tag = this.getKey();
|
||||
for (Map.Entry<String, ConfigMap> entry : defaults.getActionMap().entrySet()) {
|
||||
if (((String) entry.getKey()).equals(tag)) {
|
||||
mMap = entry.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigMap getConfigMap() {
|
||||
return mMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfigMap(ConfigMap map) {
|
||||
mMap = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ButtonConfig getButtonConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setButtonConfig(ButtonConfig button) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionConfig getActionConfig() {
|
||||
return mAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionConfig(ActionConfig action) {
|
||||
mAction = action;
|
||||
this.setSummary(action.getLabel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ButtonConfig getDefaultButtonConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultButtonConfig(ButtonConfig button) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionConfig getDefaultActionConfig() {
|
||||
return mDefaultAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultActionConfig(ActionConfig action) {
|
||||
mDefaultAction = action;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2015 TeamEos 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.
|
||||
*
|
||||
* Adapter for displaying custom actions in a list
|
||||
*/
|
||||
|
||||
package com.cherish.settings.preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.util.hwkeys.ActionHandler;
|
||||
import com.android.internal.util.hwkeys.Config.ActionConfig;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
public class CustomActionListAdapter extends BaseAdapter {
|
||||
private LayoutInflater mInflater;
|
||||
private Context mContext;
|
||||
private List<ActionConfig> mCustomActions = new ArrayList<ActionConfig>();
|
||||
|
||||
public CustomActionListAdapter(Context context) {
|
||||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
reloadActions();
|
||||
}
|
||||
|
||||
private void reloadActions() {
|
||||
mCustomActions.clear();
|
||||
mCustomActions.addAll(ActionHandler.getSystemActions(mContext));
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void removeAction(String action) {
|
||||
int index = -1;
|
||||
for (int i = 0; i < mCustomActions.size(); i++) {
|
||||
if (TextUtils.equals(mCustomActions.get(i).getAction(), action)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index > -1) {
|
||||
mCustomActions.remove(index);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mCustomActions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionConfig getItem(int position) {
|
||||
return mCustomActions.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder holder;
|
||||
final Context ctx = mContext;
|
||||
if (convertView != null) {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
} else {
|
||||
convertView = mInflater.inflate(R.layout.custom_action_item, null, false);
|
||||
holder = new ViewHolder();
|
||||
convertView.setTag(holder);
|
||||
holder.title = (TextView) convertView.findViewById(com.android.internal.R.id.title);
|
||||
holder.summary = (TextView) convertView
|
||||
.findViewById(com.android.internal.R.id.summary);
|
||||
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
|
||||
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) holder.icon.getLayoutParams();
|
||||
params.width = holder.icon.getMaxWidth();
|
||||
params.height = holder.icon.getMaxHeight();
|
||||
holder.icon.setLayoutParams(params);
|
||||
holder.icon.setScaleType(ScaleType.CENTER);
|
||||
holder.icon.setCropToPadding(true);
|
||||
}
|
||||
|
||||
ActionConfig config = getItem(position);
|
||||
holder.title.setText(config.getLabel());
|
||||
holder.icon.setBackgroundResource(R.drawable.fab_accent);
|
||||
holder.icon.setImageDrawable(config.getDefaultIcon(ctx));
|
||||
holder.summary.setVisibility(View.GONE);
|
||||
|
||||
return convertView;
|
||||
|
||||
}
|
||||
|
||||
private static class ViewHolder {
|
||||
TextView title;
|
||||
TextView summary;
|
||||
ImageView icon;
|
||||
}
|
||||
}
|
||||
327
src/com/cherish/settings/preferences/ShortcutPickHelper.java
Normal file
327
src/com/cherish/settings/preferences/ShortcutPickHelper.java
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The CyanogenMod 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.cherish.settings.preferences;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.Intent.ShortcutIconResource;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseExpandableListAdapter;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.cherish.settings.preferences.ShortcutPickHelper.AppExpandableAdapter.GroupInfo;
|
||||
|
||||
public class ShortcutPickHelper {
|
||||
|
||||
private FragmentActivity mParent;
|
||||
private AlertDialog mAlertDialog;
|
||||
private OnPickListener mListener;
|
||||
private PackageManager mPackageManager;
|
||||
private static final int REQUEST_PICK_SHORTCUT = 100;
|
||||
private static final int REQUEST_PICK_APPLICATION = 101;
|
||||
private static final int REQUEST_CREATE_SHORTCUT = 102;
|
||||
private int lastFragmentId;
|
||||
|
||||
public interface OnPickListener {
|
||||
void shortcutPicked(String uri, String friendlyName, boolean isApplication);
|
||||
}
|
||||
|
||||
public ShortcutPickHelper(FragmentActivity parent, OnPickListener listener) {
|
||||
mParent = parent;
|
||||
mPackageManager = mParent.getPackageManager();
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == FragmentActivity.RESULT_OK) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_PICK_APPLICATION:
|
||||
completeSetCustomApp(data);
|
||||
break;
|
||||
case REQUEST_CREATE_SHORTCUT:
|
||||
completeSetCustomShortcut(data);
|
||||
break;
|
||||
case REQUEST_PICK_SHORTCUT:
|
||||
processShortcut(data, REQUEST_PICK_APPLICATION, REQUEST_CREATE_SHORTCUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pickShortcut(String[] names, ShortcutIconResource[] icons, int fragmentId) {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
ArrayList<String> shortcutNames = new ArrayList<String>();
|
||||
if (names != null) {
|
||||
for (String s : names) {
|
||||
shortcutNames.add(s);
|
||||
}
|
||||
}
|
||||
shortcutNames.add(mParent.getString(R.string.profile_applist_title));
|
||||
shortcutNames.add(mParent.getString(R.string.picker_activities));
|
||||
bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);
|
||||
|
||||
ArrayList<ShortcutIconResource> shortcutIcons = new ArrayList<ShortcutIconResource>();
|
||||
if (icons != null) {
|
||||
for (ShortcutIconResource s : icons) {
|
||||
shortcutIcons.add(s);
|
||||
}
|
||||
}
|
||||
shortcutIcons.add(ShortcutIconResource.fromContext(mParent, android.R.drawable.sym_def_app_icon));
|
||||
shortcutIcons.add(ShortcutIconResource.fromContext(mParent, R.drawable.activities_icon));
|
||||
bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);
|
||||
|
||||
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
|
||||
pickIntent.putExtra(Intent.EXTRA_INTENT, new Intent(Intent.ACTION_CREATE_SHORTCUT));
|
||||
pickIntent.putExtra(Intent.EXTRA_TITLE, mParent.getText(R.string.select_custom_app_title));
|
||||
pickIntent.putExtras(bundle);
|
||||
lastFragmentId = fragmentId;
|
||||
startFragmentOrActivity(pickIntent, REQUEST_PICK_SHORTCUT);
|
||||
}
|
||||
|
||||
private void startFragmentOrActivity(Intent pickIntent, int requestCode) {
|
||||
if (lastFragmentId == 0) {
|
||||
mParent.startActivityForResult(pickIntent, requestCode);
|
||||
} else {
|
||||
Fragment cFrag = mParent.getSupportFragmentManager().findFragmentById(lastFragmentId);
|
||||
if (cFrag != null) {
|
||||
mParent.startActivityFromFragment(cFrag, pickIntent, requestCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processShortcut(final Intent intent, int requestCodeApplication, int requestCodeShortcut) {
|
||||
// Handle case where user selected "Applications"
|
||||
String applicationName = mParent.getString(R.string.profile_applist_title);
|
||||
String application2name = mParent.getString(R.string.picker_activities);
|
||||
String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
if (applicationName != null && applicationName.equals(shortcutName)) {
|
||||
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
|
||||
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
|
||||
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
|
||||
pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
|
||||
startFragmentOrActivity(pickIntent, requestCodeApplication);
|
||||
} else if (application2name != null && application2name.equals(shortcutName)){
|
||||
final List<PackageInfo> pInfos = mPackageManager.getInstalledPackages(PackageManager.GET_ACTIVITIES);
|
||||
ExpandableListView appListView = new ExpandableListView(mParent);
|
||||
AppExpandableAdapter appAdapter = new AppExpandableAdapter(pInfos, mParent);
|
||||
appListView.setAdapter(appAdapter);
|
||||
appListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
|
||||
@Override
|
||||
public boolean onChildClick(ExpandableListView parent, View v,
|
||||
int groupPosition, int childPosition, long id) {
|
||||
Intent shortIntent = new Intent(Intent.ACTION_MAIN);
|
||||
String pkgName = ((GroupInfo)parent.getExpandableListAdapter().getGroup(groupPosition))
|
||||
.info.packageName;
|
||||
String actName = ((GroupInfo)parent.getExpandableListAdapter().getGroup(groupPosition))
|
||||
.info.activities[childPosition].name;
|
||||
shortIntent.setClassName(pkgName, actName);
|
||||
completeSetCustomApp(shortIntent);
|
||||
mAlertDialog.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
Builder builder = new Builder(mParent);
|
||||
builder.setView(appListView);
|
||||
mAlertDialog = builder.create();
|
||||
mAlertDialog.setTitle(mParent.getString(R.string.select_custom_activity_title));
|
||||
mAlertDialog.show();
|
||||
mAlertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
mListener.shortcutPicked(null, null, false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
startFragmentOrActivity(intent, requestCodeShortcut);
|
||||
}
|
||||
}
|
||||
|
||||
public class AppExpandableAdapter extends BaseExpandableListAdapter {
|
||||
|
||||
ArrayList<GroupInfo> allList = new ArrayList<GroupInfo>();
|
||||
final int groupPadding;
|
||||
|
||||
public class LabelCompare implements Comparator<GroupInfo>{
|
||||
@Override
|
||||
public int compare(GroupInfo item1, GroupInfo item2) {
|
||||
String rank1 = item1.label.toLowerCase();
|
||||
String rank2 = item2.label.toLowerCase();
|
||||
int result = rank1.compareTo(rank2);
|
||||
if(result == 0) {
|
||||
return 0;
|
||||
} else if(result < 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GroupInfo {
|
||||
String label;
|
||||
PackageInfo info;
|
||||
GroupInfo (String l, PackageInfo p) {
|
||||
label = l;
|
||||
info = p;
|
||||
}
|
||||
}
|
||||
|
||||
public AppExpandableAdapter(List<PackageInfo> pInfos, Context context) {
|
||||
for (PackageInfo i : pInfos) {
|
||||
allList.add(new GroupInfo(i.applicationInfo.loadLabel(mPackageManager).toString(), i));
|
||||
}
|
||||
Collections.sort(allList, new LabelCompare());
|
||||
groupPadding = context.getResources().getDimensionPixelSize(R.dimen.shortcut_picker_left_padding);
|
||||
}
|
||||
|
||||
public String getChild(int groupPosition, int childPosition) {
|
||||
return allList.get(groupPosition).info.activities[childPosition].name;
|
||||
}
|
||||
|
||||
public long getChildId(int groupPosition, int childPosition) {
|
||||
return childPosition;
|
||||
}
|
||||
|
||||
public int getChildrenCount(int groupPosition) {
|
||||
if (allList.get(groupPosition).info.activities != null) {
|
||||
return allList.get(groupPosition).info.activities.length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
|
||||
View convertView, ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = View.inflate(mParent, android.R.layout.simple_list_item_1, null);
|
||||
convertView.setPadding(groupPadding, 0, 0, 0);
|
||||
|
||||
}
|
||||
TextView textView = (TextView)convertView.findViewById(android.R.id.text1);
|
||||
textView.setText(getChild(groupPosition, childPosition).replaceFirst(allList.get(groupPosition).info.packageName + ".", ""));
|
||||
return convertView;
|
||||
}
|
||||
|
||||
public GroupInfo getGroup(int groupPosition) {
|
||||
return allList.get(groupPosition);
|
||||
}
|
||||
|
||||
public int getGroupCount() {
|
||||
return allList.size();
|
||||
}
|
||||
|
||||
public long getGroupId(int groupPosition) {
|
||||
return groupPosition;
|
||||
}
|
||||
|
||||
public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
|
||||
ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = View.inflate(mParent, android.R.layout.simple_list_item_1, null);
|
||||
convertView.setPadding(70, 0, 0, 0);
|
||||
}
|
||||
TextView textView = (TextView)convertView.findViewById(android.R.id.text1);
|
||||
textView.setText(getGroup(groupPosition).label.toString());
|
||||
return convertView;
|
||||
}
|
||||
|
||||
public boolean isChildSelectable(int groupPosition, int childPosition) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasStableIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void completeSetCustomApp(Intent data) {
|
||||
mListener.shortcutPicked(data.toUri(0), getFriendlyActivityName(data, false), true);
|
||||
}
|
||||
|
||||
private void completeSetCustomShortcut(Intent data) {
|
||||
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
|
||||
if (intent == null) return;
|
||||
// preserve shortcut name, we want to restore it later
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
|
||||
// standardize the uri scheme to be sure we can launch it
|
||||
// TODO: add compatibility for apps that use ACTION_CONFIRM_PIN_SHORTCUT (drag widget on the home screen)
|
||||
String appUri = intent.toUri(Intent.URI_INTENT_SCHEME);
|
||||
appUri = appUri.replaceAll("com.android.contacts.action.QUICK_CONTACT", "android.intent.action.VIEW");
|
||||
mListener.shortcutPicked(appUri, getFriendlyShortcutName(intent), false);
|
||||
}
|
||||
|
||||
private String getFriendlyActivityName(Intent intent, boolean labelOnly) {
|
||||
ActivityInfo ai = intent.resolveActivityInfo(mPackageManager, PackageManager.GET_ACTIVITIES);
|
||||
String friendlyName = null;
|
||||
if (ai != null) {
|
||||
friendlyName = ai.loadLabel(mPackageManager).toString();
|
||||
if (friendlyName == null && !labelOnly) {
|
||||
friendlyName = ai.name;
|
||||
}
|
||||
}
|
||||
return friendlyName != null || labelOnly ? friendlyName : intent.toUri(0);
|
||||
}
|
||||
|
||||
private String getFriendlyShortcutName(Intent intent) {
|
||||
String activityName = getFriendlyActivityName(intent, true);
|
||||
String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
|
||||
if (activityName != null && name != null) {
|
||||
return activityName + ": " + name;
|
||||
}
|
||||
return name != null ? name : intent.toUri(0);
|
||||
}
|
||||
|
||||
public String getFriendlyNameForUri(String uri) {
|
||||
if (uri == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Intent intent = Intent.parseUri(uri, 0);
|
||||
if (Intent.ACTION_MAIN.equals(intent.getAction())) {
|
||||
return getFriendlyActivityName(intent, false);
|
||||
}
|
||||
return getFriendlyShortcutName(intent);
|
||||
} catch (URISyntaxException e) {
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user