Hardware key: Customization support [2/2]
Based on DUI jhenrique09 edits: make it DUI independent Original commit message: Same robust action library as used on software navigation. Supports single tap, double tap, and long press. As a precautionary measure, single tap back and single tap home are fixed and can not be changed. Camera button actions are not supported at this time. We will bring in wake key support at a later time. Also includes: Change-Id: I29ff38678821ca80db36d49d3b10d8ac29a6b4de DUI: Initial checkin for Oreo [4/7] Signed-off-by: Shubham Singh <coolsks94@gmail.com> Signed-off-by: mhkjahromi <m.h.k.jahromi@gmail.com> Signed-off-by: SagarMakhar <sagarmakhar@gmail.com> Signed-off-by: Hưng Phan <phandinhhungvp2001@gmail.com>
This commit is contained in:
@@ -33,15 +33,20 @@ import androidx.preference.SwitchPreference;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Toast;
|
||||
import com.android.settings.R;
|
||||
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.cherish.settings.preferences.SystemSettingSwitchPreference;
|
||||
import com.cherish.settings.preferences.SecureSettingSwitchPreference;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.util.hwkeys.ActionConstants;
|
||||
import com.android.internal.util.hwkeys.ActionUtils;
|
||||
|
||||
import com.cherish.settings.preferences.CustomSeekBarPreference;
|
||||
import com.cherish.settings.preferences.ActionFragment;
|
||||
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -49,6 +54,24 @@ import java.util.List;
|
||||
public class ButtonSettings extends SettingsPreferenceFragment implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
|
||||
// category 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 static final String TORCH_POWER_BUTTON_GESTURE = "torch_power_button_gesture";
|
||||
|
||||
private ListPreference mTorchPowerButton;
|
||||
@@ -61,6 +84,49 @@ public class ButtonSettings extends SettingsPreferenceFragment implements
|
||||
final Resources res = getResources();
|
||||
final ContentResolver resolver = getActivity().getContentResolver();
|
||||
final PreferenceScreen prefScreen = getPreferenceScreen();
|
||||
// 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));
|
||||
|
||||
// screen off torch
|
||||
mTorchPowerButton = (ListPreference) findPreference(TORCH_POWER_BUTTON_GESTURE);
|
||||
|
||||
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