mShiftShortcuts = new SparseArray<>();
private final Context mContext;
public ShortcutManager(Context context) {
mContext = context;
loadShortcuts();
}
/**
* Gets the shortcut intent for a given keycode+modifier. Make sure you
* strip whatever modifier is used for invoking shortcuts (for example,
* if 'Sym+A' should invoke a shortcut on 'A', you should strip the
* 'Sym' bit from the modifiers before calling this method.
*
* This will first try an exact match (with modifiers), and then try a
* match without modifiers (primary character on a key).
*
* @param kcm The key character map of the device on which the key was pressed.
* @param keyCode The key code.
* @param metaState The meta state, omitting any modifiers that were used
* to invoke the shortcut.
* @return The intent that matches the shortcut, or null if not found.
*/
public Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) {
ShortcutInfo shortcut = null;
// If the Shift key is pressed, then search for the shift shortcuts.
boolean isShiftOn = (metaState & KeyEvent.META_SHIFT_ON) == KeyEvent.META_SHIFT_ON;
SparseArray shortcutMap = isShiftOn ? mShiftShortcuts : mShortcuts;
// First try the exact keycode (with modifiers).
int shortcutChar = kcm.get(keyCode, metaState);
if (shortcutChar != 0) {
shortcut = shortcutMap.get(shortcutChar);
}
// Next try the primary character on that key.
if (shortcut == null) {
shortcutChar = Character.toLowerCase(kcm.getDisplayLabel(keyCode));
if (shortcutChar != 0) {
shortcut = shortcutMap.get(shortcutChar);
}
}
return (shortcut != null) ? shortcut.intent : null;
}
private void loadShortcuts() {
PackageManager packageManager = mContext.getPackageManager();
try {
XmlResourceParser parser = mContext.getResources().getXml(
com.android.internal.R.xml.bookmarks);
XmlUtils.beginDocument(parser, TAG_BOOKMARKS);
while (true) {
XmlUtils.nextElement(parser);
if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
break;
}
if (!TAG_BOOKMARK.equals(parser.getName())) {
break;
}
String packageName = parser.getAttributeValue(null, ATTRIBUTE_PACKAGE);
String className = parser.getAttributeValue(null, ATTRIBUTE_CLASS);
String shortcutName = parser.getAttributeValue(null, ATTRIBUTE_SHORTCUT);
String categoryName = parser.getAttributeValue(null, ATTRIBUTE_CATEGORY);
String shiftName = parser.getAttributeValue(null, ATTRIBUTE_SHIFT);
if (TextUtils.isEmpty(shortcutName)) {
Log.w(TAG, "Unable to get shortcut for: " + packageName + "/" + className);
continue;
}
final int shortcutChar = shortcutName.charAt(0);
final boolean isShiftShortcut = (shiftName != null && shiftName.equals("true"));
final Intent intent;
final String title;
if (packageName != null && className != null) {
ActivityInfo info = null;
ComponentName componentName = new ComponentName(packageName, className);
try {
info = packageManager.getActivityInfo(componentName,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (PackageManager.NameNotFoundException e) {
String[] packages = packageManager.canonicalToCurrentPackageNames(
new String[] { packageName });
componentName = new ComponentName(packages[0], className);
try {
info = packageManager.getActivityInfo(componentName,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_UNINSTALLED_PACKAGES);
} catch (PackageManager.NameNotFoundException e1) {
Log.w(TAG, "Unable to add bookmark: " + packageName
+ "/" + className, e);
continue;
}
}
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(componentName);
title = info.loadLabel(packageManager).toString();
} else if (categoryName != null) {
intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, categoryName);
title = "";
} else {
Log.w(TAG, "Unable to add bookmark for shortcut " + shortcutName
+ ": missing package/class or category attributes");
continue;
}
ShortcutInfo shortcut = new ShortcutInfo(title, intent);
if (isShiftShortcut) {
mShiftShortcuts.put(shortcutChar, shortcut);
} else {
mShortcuts.put(shortcutChar, shortcut);
}
}
} catch (XmlPullParserException e) {
Log.w(TAG, "Got exception parsing bookmarks.", e);
} catch (IOException e) {
Log.w(TAG, "Got exception parsing bookmarks.", e);
}
}
private static final class ShortcutInfo {
public final String title;
public final Intent intent;
public ShortcutInfo(String title, Intent intent) {
this.title = title;
this.intent = intent;
}
}
}