diff --git a/res/values/cherish_arrays.xml b/res/values/cherish_arrays.xml index 7ac789a..f915c77 100644 --- a/res/values/cherish_arrays.xml +++ b/res/values/cherish_arrays.xml @@ -447,4 +447,25 @@ 2 3 + + + + @string/action_entry_default_action + @string/action_entry_custom_action + @string/action_entry_select_app + + + @string/action_value_default_action + @string/action_value_custom_action + @string/action_value_select_app + + + @string/action_entry_custom_action + @string/action_entry_select_app + + + @string/action_value_custom_action + @string/action_value_select_app + + diff --git a/res/values/cherish_strings.xml b/res/values/cherish_strings.xml index ff04c22..7180327 100644 --- a/res/values/cherish_strings.xml +++ b/res/values/cherish_strings.xml @@ -176,7 +176,38 @@ Jump to camera gesture is now disabled Long press power button - + + default + app + custom + task_back + task_home + task_assist + task_recents + task_voice_search + task_menu + Activities + Select custom app + Select custom activity + Applications + Choose action + Default settings + Select application + Select custom action + Volume rocker + Home button + Menu button + Search button + Overview button + Back button + Set double tap action + Set single tap action + Set long press action + Single tap action + Long press action + Double tap action + + 4G icon Display 4G icon in signal icon instead LTE diff --git a/res/xml/cherish_settings_button.xml b/res/xml/cherish_settings_button.xml index e14911d..2092b0b 100644 --- a/res/xml/cherish_settings_button.xml +++ b/res/xml/cherish_settings_button.xml @@ -39,6 +39,114 @@ android:title="@string/volume_steps_fragment_title" android:summary="@string/volume_steps_summary" android:fragment="com.cherish.settings.fragments.VolumeStepsFragment" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + mPrefHolder; + private String mHolderTag; + private Defaults mDefaults; + private ArrayList mButtons; + private ArrayList 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(); + } + + @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 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; + } +} \ No newline at end of file diff --git a/src/com/cherish/settings/preferences/ActionPreference.java b/src/com/cherish/settings/preferences/ActionPreference.java new file mode 100644 index 0000000..67c0a81 --- /dev/null +++ b/src/com/cherish/settings/preferences/ActionPreference.java @@ -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 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; + } +} diff --git a/src/com/cherish/settings/preferences/CustomActionListAdapter.java b/src/com/cherish/settings/preferences/CustomActionListAdapter.java new file mode 100644 index 0000000..dff16e1 --- /dev/null +++ b/src/com/cherish/settings/preferences/CustomActionListAdapter.java @@ -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 mCustomActions = new ArrayList(); + + 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; + } +} diff --git a/src/com/cherish/settings/preferences/ShortcutPickHelper.java b/src/com/cherish/settings/preferences/ShortcutPickHelper.java new file mode 100644 index 0000000..44eaf3e --- /dev/null +++ b/src/com/cherish/settings/preferences/ShortcutPickHelper.java @@ -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 shortcutNames = new ArrayList(); + 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 shortcutIcons = new ArrayList(); + 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 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 allList = new ArrayList(); + final int groupPadding; + + public class LabelCompare implements Comparator{ + @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 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; + } +}