├── .gitignore ├── .idea └── libraries │ └── Patched_Classes.xml ├── KindleLauncher.iml ├── META-INF └── MANIFEST.MF ├── README └── src └── com └── yifanlu └── Kindle ├── Extension.java ├── ExtensionsLoader.java ├── JARClassLoader.java ├── JSONMenu.java ├── KindleLauncher.java ├── KindleLauncherResources.java ├── LauncherAction.java ├── LauncherMenu.java ├── LauncherScript.java ├── Menuable.java └── ReaderPluginLauncher.java /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | lib/ 3 | out/ 4 | -------------------------------------------------------------------------------- /.idea/libraries/Patched_Classes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /KindleLauncher.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | 3 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | More coming soon... 2 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/Extension.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | /** 22 | * This class represents the extension and is parsed by the config.xml file. 23 | * Currently, the only thing of use is the {@link Menuable}, which 24 | * holds the menu items. 25 | * 26 | * @author Yifan Lu 27 | * @version 1.0 28 | */ 29 | public class Extension { 30 | private String mName; 31 | private String mVersion; 32 | private String mAuthor; 33 | private String mId; 34 | private Menuable mMenu; 35 | 36 | /** 37 | * We want all the fields to be set by the parser, but we place default values in just in case. 38 | */ 39 | public Extension() { 40 | this.mName = "Plugin"; 41 | this.mVersion = "0.0"; 42 | this.mAuthor = "Author"; 43 | this.mId = super.toString(); 44 | } 45 | 46 | /** 47 | * Sets the name of the extension. 48 | * 49 | * @param name The name of the extension. 50 | */ 51 | public void setName(String name) { 52 | this.mName = name; 53 | } 54 | 55 | /** 56 | * Gets the name of the extension. 57 | * This is currently unused. 58 | * 59 | * @return The name of the extension. 60 | */ 61 | public String getName() { 62 | return this.mName; 63 | } 64 | 65 | /** 66 | * Sets the version of the extension. 67 | * 68 | * @param version The version of the extension. 69 | */ 70 | public void setVersion(String version) { 71 | this.mVersion = version; 72 | } 73 | 74 | /** 75 | * Gets the version of the extension. 76 | * This is currently unused. 77 | * 78 | * @return The version of the extension. 79 | */ 80 | public String getVersion() { 81 | return this.mVersion; 82 | } 83 | 84 | /** 85 | * Sets the author of the extension. 86 | * 87 | * @param author The author of the extension. 88 | */ 89 | public void setAuthor(String author) { 90 | this.mAuthor = author; 91 | } 92 | 93 | /** 94 | * Gets the author of the extension. 95 | * This is currently unused. 96 | * 97 | * @return The author of the extension. 98 | */ 99 | public String getAuthor() { 100 | return this.mAuthor; 101 | } 102 | 103 | /** 104 | * Sets the id of the extension. Must be unique. 105 | * 106 | * @param id The id of the extension. 107 | */ 108 | public void setId(String id) { 109 | this.mId = id; 110 | } 111 | 112 | /** 113 | * Gets the id of the extension. 114 | * This is currently unused. 115 | * 116 | * @return The id of the extension. 117 | */ 118 | public String getId() { 119 | return this.mId; 120 | } 121 | 122 | /** 123 | * Gets the menu options for this extension. 124 | * 125 | * @return The menu options for this extension. 126 | * @see com.yifanlu.Kindle.Menuable 127 | */ 128 | public Menuable getMenu() { 129 | return this.mMenu; 130 | } 131 | 132 | /** 133 | * Sets the menu options for this extension. 134 | * 135 | * @param menu The menu option for this extension. 136 | * @see com.yifanlu.Kindle.Menuable 137 | */ 138 | public void setMenu(Menuable menu) { 139 | this.mMenu = menu; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/ExtensionsLoader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import com.amazon.ebook.util.log.LogMessage; 22 | import org.json.simple.parser.ParseException; 23 | import org.kxml2.io.KXmlParser; 24 | import org.xmlpull.v1.XmlPullParser; 25 | import org.xmlpull.v1.XmlPullParserException; 26 | 27 | import java.io.*; 28 | import java.util.ArrayList; 29 | 30 | /** 31 | * This class holds the functions for loading and parsing the XML configs from extensions. 32 | * 33 | * @author Yifan Lu 34 | * @version 1.0 35 | */ 36 | public class ExtensionsLoader { 37 | private static final LogMessage LOADED_EXTENSION = new LogMessage("ExtensionLoad", new String[]{"name", "version", "author", "id"}); 38 | private static final LogMessage MENU_ATTRIBUTES = new LogMessage("MenuLoad", new String[]{"name", "value"}); 39 | private File mDirectory; 40 | 41 | /** 42 | * Create a new extension loader using "directory" as the base 43 | * 44 | * @param directory Where the extensions are located. Each extension must be in its own folder and contain config.xml. 45 | */ 46 | public ExtensionsLoader(File directory) { 47 | mDirectory = directory; 48 | } 49 | 50 | /** 51 | * This converts all the extensions into objects using information from their config.xml and returns an array. 52 | * 53 | * @return A list of extensions that are loaded or an empty list of no extension is loaded successfully. 54 | */ 55 | public ArrayList loadExtensions() { 56 | KXmlParser parser = new KXmlParser(); 57 | ArrayList extList = new ArrayList(); 58 | File[] extensions = mDirectory.listFiles(new FileFilter() { 59 | public boolean accept(File file) { 60 | return file.isDirectory(); 61 | } 62 | }); 63 | int i; 64 | try { 65 | for (i = 0; i < extensions.length; i++) { 66 | File ext = extensions[i]; 67 | KindleLauncher.LOG.info("Loading: " + ext.getAbsolutePath()); 68 | File config = new File(ext, "config.xml"); 69 | Extension extObj = new Extension(); 70 | parser.setInput(new InputStreamReader(new FileInputStream(config))); 71 | parser.nextTag(); 72 | parser.require(XmlPullParser.START_TAG, null, "extension"); 73 | while (parser.nextTag() != XmlPullParser.END_TAG) { 74 | parser.require(XmlPullParser.START_TAG, null, null); 75 | String name = parser.getName(); 76 | if (name.equals("information")) 77 | parseInformation(parser, extObj); 78 | else if (name.equals("menus")) 79 | parseMenus(parser, extObj, ext); 80 | else //skip 81 | while (parser.next() != XmlPullParser.END_TAG || !parser.getName().equals(name)) 82 | ; // this one line does magic to skip all unrelated events 83 | parser.require(XmlPullParser.END_TAG, null, name); 84 | } 85 | parser.require(XmlPullParser.END_TAG, null, "extension"); 86 | parser.next(); 87 | parser.require(XmlPullParser.END_DOCUMENT, null, null); 88 | extList.add(extObj); 89 | KindleLauncher.LOG.info(LOADED_EXTENSION, new String[]{extObj.getName(), extObj.getVersion(), extObj.getAuthor(), extObj.getId()}, ""); 90 | } 91 | } catch (IOException e) { 92 | KindleLauncher.LOG.error("Error reading extension config. " + e.getMessage()); 93 | e.printStackTrace(); 94 | } catch (XmlPullParserException e) { 95 | KindleLauncher.LOG.error("Error parsing extension config. " + e.getMessage()); 96 | e.printStackTrace(); 97 | } catch (NullPointerException e) { 98 | KindleLauncher.LOG.error("Error parsing extension menu. Required attribute not found. " + e.getMessage()); 99 | e.printStackTrace(); 100 | } catch (ClassNotFoundException e) { 101 | KindleLauncher.LOG.error("Error parsing extension menu. Cannot find menu Java class. " + e.getMessage()); 102 | e.printStackTrace(); 103 | } catch (ClassCastException e) { 104 | KindleLauncher.LOG.error("Error parsing extension menu. " + e.getMessage()); 105 | e.printStackTrace(); 106 | } catch (InstantiationException e) { 107 | KindleLauncher.LOG.error("Error parsing extension menu. Cannot create object from Java class. " + e.getMessage()); 108 | e.printStackTrace(); 109 | } catch (IllegalAccessException e) { 110 | KindleLauncher.LOG.error("Error parsing extension menu. Cannot create object from Java class. " + e.getMessage()); 111 | e.printStackTrace(); 112 | } catch (ParseException e) { 113 | KindleLauncher.LOG.error("Error parsing extension menu. Cannot parse JSON menu. " + e.getMessage()); 114 | e.printStackTrace(); 115 | } 116 | return extList; 117 | } 118 | 119 | /** 120 | * This parses the "information" section of the config.xml file. This section contains information about the 121 | * extension. This information is currently unused, but may be useful in the future so it is recommended that 122 | * all extensions contain it. The format is 123 | *

124 | *

125 |      *      <information>
126 |      *          <name>Name of the plugin</name>
127 |      *          <version>Version of the plugin</version>
128 |      *          <author>Author of the plugin</author>
129 |      *          <id>Unique id of the plugin</id>
130 |      *      </information>
131 |      * 
132 | * 133 | * @param parser {@link org.kxml2.io.KXmlParser} 134 | * @param extObj The {@link Extension} object to fill. 135 | * @throws IOException if the config cannot be read cannot be accessed 136 | * @throws XmlPullParserException if the config is malformed 137 | */ 138 | protected void parseInformation(KXmlParser parser, Extension extObj) throws IOException, XmlPullParserException { 139 | while (parser.nextTag() != XmlPullParser.END_TAG) { 140 | parser.require(XmlPullParser.START_TAG, null, null); 141 | String name = parser.getName(); 142 | String text = parser.nextText(); 143 | 144 | if (name.equals("name")) 145 | extObj.setName(text); 146 | else if (name.equals("version")) 147 | extObj.setVersion(text); 148 | else if (name.equals("author")) 149 | extObj.setAuthor(text); 150 | else if (name.equals("id")) 151 | extObj.setId(text); 152 | 153 | parser.require(XmlPullParser.END_TAG, null, name); 154 | } 155 | } 156 | 157 | /** 158 | * This parses the "menus" section of the config.xml file. The "menus" section can contain one or more list of 159 | * menu options that are loaded by either JSON or Java. All menu options from each list are added to the main menu. 160 | * The format of the entries in config.xml for the menus section is 161 | *

162 | *

163 |      *      <menus>
164 |      *          <menu type="VALUE" jar="VALUE" dynamic="VALUE">TEXT</menu>
165 |      *      </menus>
166 |      * 
167 | *

168 | * Where type is either "java" or "json", jar is required only for "java" types and is the path to the Jar file 169 | * containing the Menuable class relative to config.xml, dynamic is required only for JSON types and tells the 170 | * loader to re-read the JSON file each time the menu is opened, and the text of the element is either the path 171 | * to the JSON menu file or the Java class to load. 172 | * 173 | * @param parser {@link org.kxml2.io.KXmlParser} 174 | * @param extObj The {@link Extension} object to fill. 175 | * @param extDir The path to the extension's directory 176 | * @throws IOException if the config cannot be read or the extension directory cannot be accessed 177 | * @throws XmlPullParserException if the config is malformed 178 | * @throws ClassNotFoundException if the menu type is Java and the class specified cannot be loaded 179 | * @throws IllegalAccessException if the menu type is Java and the class specified cannot be accessed 180 | * @throws InstantiationException if the menu type is Java and the class specified cannot be instantiated 181 | * @throws ParseException if the config file cannot be parsed correctly 182 | */ 183 | protected void parseMenus(KXmlParser parser, Extension extObj, File extDir) throws IOException, XmlPullParserException, ClassNotFoundException, IllegalAccessException, InstantiationException, ParseException { 184 | while (parser.nextTag() != XmlPullParser.END_TAG) { 185 | parser.require(XmlPullParser.START_TAG, null, "menu"); 186 | 187 | Menuable menu; 188 | boolean isJava = false; 189 | boolean isDynamic = false; 190 | String jarFile = null; 191 | int i = parser.getAttributeCount(); 192 | KindleLauncher.LOG.debug("Attributes: " + parser.getAttributeCount()); 193 | while (i-- > 0) { 194 | String name = parser.getAttributeName(i); 195 | String value = parser.getAttributeValue(i); 196 | if (name.equals("type")) 197 | isJava = value.equals("java"); 198 | else if (name.equals("dynamic")) 199 | isDynamic = value.equals("true"); 200 | else if (name.equals("jar")) 201 | jarFile = value; 202 | KindleLauncher.LOG.debug(MENU_ATTRIBUTES, new String[]{name, value}, ""); 203 | } 204 | 205 | String text = parser.nextText(); 206 | 207 | if (isJava) { 208 | JARClassLoader classLoader = JARClassLoader.getInstance(); 209 | classLoader.addJar(new File(extDir, jarFile)); 210 | Class cls = classLoader.loadClass(text); 211 | menu = (Menuable) cls.newInstance(); 212 | KindleLauncher.LOG.debug("Loaded class: " + text); 213 | } else { 214 | File jsonFile = new File(extDir, text); 215 | JSONMenu jsonMenu = new JSONMenu(jsonFile); 216 | jsonMenu.setDynamic(isDynamic); 217 | jsonMenu.parseJSONMenu(); 218 | menu = jsonMenu; 219 | KindleLauncher.LOG.debug("Loaded menu: " + jsonFile.getAbsolutePath()); 220 | } 221 | 222 | extObj.setMenu(menu); 223 | 224 | parser.require(XmlPullParser.END_TAG, null, "menu"); 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/JARClassLoader.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import com.amazon.ebook.util.log.LogMessage; 22 | 23 | import java.io.File; 24 | import java.net.MalformedURLException; 25 | import java.net.URL; 26 | import java.net.URLClassLoader; 27 | 28 | /** 29 | * This classloader allows loading JARs from any URL and does not require the URL to be passed on initiation. 30 | * 31 | * @author Yifan Lu 32 | * @version 1.0 33 | */ 34 | public class JARClassLoader extends URLClassLoader { 35 | private static JARClassLoader myInstance; 36 | private static final LogMessage JAR_LOAD_ERROR = new LogMessage("JarLoad", new String[]{"jar file", "java error"}); 37 | 38 | private JARClassLoader() { 39 | super(new URL[]{}); 40 | } 41 | 42 | /** 43 | * Adds an URL to the class path. 44 | * 45 | * @param url The URL of the class path. 46 | */ 47 | public void addURL(URL url) { 48 | super.addURL(url); 49 | } 50 | 51 | /** 52 | * We are a singleton, this gets the single instance of this class. 53 | * 54 | * @return The single instance of this class loader. 55 | */ 56 | public static JARClassLoader getInstance() { 57 | if (myInstance == null) 58 | myInstance = new JARClassLoader(); 59 | return myInstance; 60 | } 61 | 62 | /** 63 | * Adds a JAR file to the class path. 64 | * 65 | * @param jarFile The {@link java.io.File} that contains the JAR to load. 66 | */ 67 | public void addJar(File jarFile) { 68 | try { 69 | URL jarURL = jarFile.toURI().toURL(); 70 | addURL(jarURL); 71 | } catch (MalformedURLException e) { 72 | KindleLauncher.LOG.error(JAR_LOAD_ERROR, new String[]{jarFile.getAbsolutePath(), e.toString()}, ""); 73 | e.printStackTrace(); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/JSONMenu.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import com.amazon.ebook.util.log.LogMessage; 22 | import org.json.simple.JSONArray; 23 | import org.json.simple.JSONObject; 24 | import org.json.simple.parser.JSONParser; 25 | import org.json.simple.parser.ParseException; 26 | 27 | import java.io.File; 28 | import java.io.FileReader; 29 | import java.io.IOException; 30 | import java.util.Iterator; 31 | 32 | /** 33 | * This class holds the menu options for a JSON menu. 34 | * 35 | * @author Yifan Lu 36 | * @version 1.0 37 | */ 38 | public class JSONMenu implements Menuable { 39 | private static final LogMessage JSON_MENU_ITEM = new LogMessage("JsonMenuItem", new String[]{"name", "action", "params"}); 40 | private File mJsonFile; 41 | private LauncherAction[] mMenuItems; 42 | private boolean mDynamic; 43 | 44 | /** 45 | * Create a new JSONMenu object with the JSON file. The format of the JSON menu is 46 | *

47 | *

 48 |      *     {
 49 |      *         "items": [
 50 |      *              {"name": "Main Menu, Item 1", "priority": 0, "action": "bin/action.sh", "params": "item1"},
 51 |      *              {
 52 |      *                  "name": "Main Menu, Submenu 1",
 53 |      *                  "priority": 1,
 54 |      *                  "items": [
 55 |      *                      {"name": "Submenu 1, Item 1", "priority": 0, "action": "/sbin/restart", "params": ""}
 56 |      *                  ]
 57 |      *              }
 58 |      *         ]
 59 |      *     }
 60 |      * 
61 | *

62 | * For each menu item, the "name" is the text that shows up and the "priority" is the order that they show up in 63 | * (if two items have the same priority, they are sorted in alphabetical order). If the item is an action, the 64 | * "action" contains the script to run and "params" contains the parameters. If the script name starts with a slash, 65 | * it is an absolute path, otherwise it is relative to the path of the JSON file. If the item is a submenu, it 66 | * will contain "items" instead of "action" and "params" and "items" is an array of menu items. 67 | * 68 | * @param jsonFile A text file that contains the JSON data. 69 | */ 70 | public JSONMenu(File jsonFile) { 71 | mJsonFile = jsonFile; 72 | mMenuItems = new LauncherAction[]{}; 73 | mDynamic = false; 74 | } 75 | 76 | /** 77 | * If the menu is dynamic as specified in config.xml, it will first call {@link JSONMenu#parseJSONMenu()}. Then it 78 | * adds the menu options specified by the JSON file to the menu of the caller. The caller will most likely be 79 | * the main Launcher menu. 80 | * 81 | * @param menu The menu of the caller. 82 | */ 83 | public void addItemsToMenu(LauncherMenu menu) { 84 | if (isDynamic()) { 85 | KindleLauncher.LOG.debug("Reloading the menu."); 86 | mJsonFile = new File(mJsonFile.getAbsolutePath()); 87 | try { 88 | parseJSONMenu(); 89 | } catch (IOException e) { 90 | KindleLauncher.LOG.error("Cannot create menu because file " + mJsonFile.getAbsolutePath() + " cannot be read."); 91 | e.printStackTrace(); 92 | } catch (ParseException e) { 93 | KindleLauncher.LOG.error("Cannot create menu because file " + mJsonFile.getAbsolutePath() + " cannot be parsed."); 94 | e.printStackTrace(); 95 | } 96 | } 97 | for (int i = 0; i < mMenuItems.length; i++) { 98 | if (mMenuItems[i] instanceof LauncherMenu) 99 | ((LauncherMenu) mMenuItems[i]).setParent(menu); 100 | menu.addMenuItem(mMenuItems[i]); 101 | } 102 | } 103 | 104 | /** 105 | * Sets the dynamic status of the menu 106 | * 107 | * @param dynamic Should the menu be dynamic? 108 | * @see com.yifanlu.Kindle.JSONMenu#isDynamic() 109 | */ 110 | public void setDynamic(boolean dynamic) { 111 | this.mDynamic = dynamic; 112 | } 113 | 114 | /** 115 | * If dynamic, the menu will be re-parsed from the JSON file each time it is rendered. This is useful if you have 116 | * a dynamic script that can alter the JSON menu when ran. 117 | * 118 | * @return The dynamic status of the menu 119 | */ 120 | public boolean isDynamic() { 121 | return mDynamic; 122 | } 123 | 124 | /** 125 | * Takes the JSON file stored in the object and converts it to menu item objects. 126 | * 127 | * @throws IOException if there is a problem reading the JSON text 128 | * @throws ParseException if there is a problem parsing the JSON text 129 | */ 130 | public void parseJSONMenu() throws IOException, ParseException { 131 | mMenuItems = new LauncherMenu[]{}; 132 | FileReader read = new FileReader(mJsonFile); 133 | JSONParser parse = new JSONParser(); 134 | JSONObject obj = (JSONObject) parse.parse(read); 135 | LauncherAction action = jsonToAction(obj, null); 136 | if (action instanceof LauncherMenu && action.getValue().equals("No Text")) { 137 | mMenuItems = ((LauncherMenu) action).getMenuItems(); 138 | } else { 139 | mMenuItems = new LauncherAction[]{action}; 140 | } 141 | } 142 | 143 | /** 144 | * Recursively reads the JSON data and converts it to a {@link LauncherAction} which contains either a 145 | * {@link LauncherScript} which executes a shell command when called or a {@link LauncherMenu} which contains 146 | * other {@link LauncherAction} items. 147 | * 148 | * @param json The JSON object to parse 149 | * @param parent The menu to add the items to 150 | * @return The {@link LauncherAction} that is defined by the JSON data 151 | * @throws IOException if there are problems reading the JSON file 152 | */ 153 | protected LauncherAction jsonToAction(JSONObject json, LauncherMenu parent) throws IOException { 154 | String name = (String) json.get("name"); 155 | Number priorityNum = (Number) json.get("priority"); 156 | int priority; 157 | String action = (String) json.get("action"); 158 | String params = (String) json.get("params"); 159 | JSONArray items = (JSONArray) json.get("items"); 160 | LauncherAction launcherAction; 161 | if (name == null) 162 | name = "No Text"; 163 | if (priorityNum == null) 164 | priority = 0; 165 | else 166 | priority = priorityNum.intValue(); 167 | if (items != null) { 168 | launcherAction = new LauncherMenu(name, priority, parent); 169 | KindleLauncher.LOG.debug(JSON_MENU_ITEM, new String[]{name, "submenu", ""}, ""); 170 | Iterator it = items.iterator(); 171 | while (it.hasNext()) { 172 | JSONObject itemObj = (JSONObject) it.next(); 173 | ((LauncherMenu) launcherAction).addMenuItem(jsonToAction(itemObj, (LauncherMenu) launcherAction)); 174 | } 175 | } else if (action != null) { 176 | if (params == null) 177 | params = ""; 178 | File script; 179 | if (action.startsWith("/")) 180 | script = new File(action); 181 | else 182 | script = new File(mJsonFile.getParentFile(), action); 183 | launcherAction = new LauncherScript(name, priority, script, params); 184 | KindleLauncher.LOG.debug(JSON_MENU_ITEM, new String[]{name, action, params}, ""); 185 | } else { 186 | throw new IOException("No valid action found for menu item: " + json.toJSONString()); 187 | } 188 | return launcherAction; 189 | 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/KindleLauncher.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import com.amazon.ebook.booklet.reader.sdk.ui.MenuInserter; 22 | import com.amazon.ebook.booklet.reader.sdk.ui.ReaderAction; 23 | import com.amazon.ebook.pl.SystemServices; 24 | import com.amazon.ebook.util.log.Log; 25 | import com.amazon.kindle.restricted.runtime.Framework; 26 | 27 | import javax.swing.*; 28 | import java.io.File; 29 | import java.util.ArrayList; 30 | import java.util.Iterator; 31 | import java.util.ResourceBundle; 32 | 33 | /** 34 | * The main class that is called when the Launcher menu is opened. 35 | * 36 | * @author Yifan Lu 37 | * @version 1.0 38 | */ 39 | public class KindleLauncher extends LauncherMenu implements MenuInserter { 40 | /** 41 | * Contains localized text for the menu items. 42 | */ 43 | public static final ResourceBundle RESOURCES = ResourceBundle.getBundle("com.yifanlu.Kindle.KindleLauncherResources"); 44 | 45 | /** 46 | * Contains Kindle services that can be used 47 | */ 48 | public static final SystemServices SERVICES = (SystemServices) Framework.getService(SystemServices.class); 49 | 50 | /** 51 | * The default {@link ExtensionsLoader} that reads from /mnt/us/extensions 52 | */ 53 | private static final ExtensionsLoader EXTENSIONS_LOADER = new ExtensionsLoader(new File("/mnt/us/extensions")); 54 | 55 | /** 56 | * The default logger that tags all logs with KindleLauncher 57 | */ 58 | public static final Log LOG = Log.getInstance("KindleLauncher"); 59 | 60 | 61 | private static KindleLauncher myInstance; 62 | private ArrayList mExtensions; 63 | 64 | private KindleLauncher() { 65 | super(RESOURCES.getString("menu.launcher.label"), 0); 66 | mExtensions = new ArrayList(); 67 | } 68 | 69 | /** 70 | * Gets the instance of the singleton. 71 | * 72 | * @return the single instance of this class as an {@link Action} 73 | */ 74 | public static Action getInstance() { 75 | LOG.debug("We are being called!"); 76 | if (myInstance == null) 77 | myInstance = new KindleLauncher(); 78 | return myInstance; 79 | } 80 | 81 | /** 82 | * Loads the extensions using {@link ExtensionsLoader} 83 | */ 84 | public void reloadExtensions() { 85 | LOG.debug("Loading extensions"); 86 | mExtensions = EXTENSIONS_LOADER.loadExtensions(); 87 | } 88 | 89 | /** 90 | * Creates the main menu for the Launcher using menu items from extensions. 91 | * We call {@link com.yifanlu.Kindle.KindleLauncher#reloadExtensions()} if the extensions have not been loaded. 92 | * Then, we tell each extensions' {@link Menuable} to {@link Menuable#addItemsToMenu(LauncherMenu)} with the main menu. 93 | */ 94 | public void createMenu() { 95 | if (mExtensions.isEmpty() || isMenuEmpty()) 96 | reloadExtensions(); 97 | clearMenu(); 98 | Iterator it = mExtensions.iterator(); 99 | while (it.hasNext()) { 100 | Extension ext = (Extension) it.next(); 101 | ext.getMenu().addItemsToMenu(this); 102 | } 103 | } 104 | 105 | /** 106 | * Called when user chooses the Launcher item from the Kindle menu. 107 | * This calls the menu creation method. 108 | * 109 | * @see com.yifanlu.Kindle.KindleLauncher#createMenu() 110 | */ 111 | public synchronized void doAction() { 112 | createMenu(); 113 | super.doAction(); 114 | } 115 | 116 | /** 117 | * The Kindle Reader SDK tells plugins to give a list of menu items to add to the Kindle menu. We will add ourselves 118 | * to it. 119 | * 120 | * @return an array containing this {@link KindleLauncher} object 121 | */ 122 | public ReaderAction[] getMenuActions() { 123 | return new ReaderAction[]{this}; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/KindleLauncherResources.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import java.util.ListResourceBundle; 22 | 23 | /** 24 | * Localization for the Launcher menu. 25 | * 26 | * @author Yifan Lu 27 | * @version 1.0 28 | */ 29 | public class KindleLauncherResources extends ListResourceBundle { 30 | /** 31 | * Labels and their associated text 32 | */ 33 | static final Object[][] RESOURCES = { 34 | {"menu.launcher.label", "Launcher"}, 35 | {"menu.launcher.next_page.label", "Next Page"}, 36 | {"menu.launcher.previous_page.label", "Previous Page"} 37 | }; 38 | 39 | /** 40 | * Gets the labels and their associated text 41 | * 42 | * @return localization strings 43 | */ 44 | protected Object[][] getContents() { 45 | return RESOURCES; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/LauncherAction.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import com.amazon.ebook.booklet.reader.sdk.ui.ReaderAction; 22 | import com.amazon.ebook.util.thread.ThreadPool; 23 | 24 | import javax.swing.*; 25 | import java.awt.event.ActionEvent; 26 | 27 | /** 28 | * A menu item for Launcher. Contains the item's text, its priority, and the task it should perform when called. 29 | * 30 | * @author Yifan Lu 31 | * @version 1.0 32 | */ 33 | public abstract class LauncherAction extends ReaderAction implements Runnable { 34 | private int mPriority; 35 | private String mName; 36 | private boolean mHasArrow; 37 | 38 | /** 39 | * Creates a new menu item with the text to show. 40 | * 41 | * @param name The text of the menu item. 42 | */ 43 | public LauncherAction(String name) { 44 | this(name, ReaderAction.PRIORITY_PLUGINS); 45 | } 46 | 47 | /** 48 | * Creates a new menu item with the text to show and the priority. 49 | * 50 | * @param name The text of the menu item. 51 | * @param priority The order to show the item. 52 | */ 53 | public LauncherAction(String name, int priority) { 54 | this(name, priority, null); 55 | } 56 | 57 | /** 58 | * Creates a new menu item with the text to show, the priority, and an icon. 59 | * 60 | * @param name The text of the menu item. 61 | * @param priority The order to show the item. 62 | * @param icon Unused. 63 | */ 64 | public LauncherAction(String name, int priority, Icon icon) { 65 | super(name, icon); 66 | this.mPriority = priority; 67 | this.mName = name; 68 | this.mHasArrow = false; 69 | this.setEnabled(true); 70 | } 71 | 72 | /** 73 | * Called when the menu item is tapped by the user. It creates a new thread and runs it. 74 | * 75 | * @param actionEvent The action performed 76 | */ 77 | public final void actionPerformed(ActionEvent actionEvent) { 78 | ThreadPool.getInstance().runIt(this, "Launcher"); 79 | } 80 | 81 | /** 82 | * Called when the new thread is ran. It wraps {@link com.yifanlu.Kindle.LauncherAction#doAction()} 83 | */ 84 | public final void run() { 85 | doAction(); 86 | } 87 | 88 | /** 89 | * The value is the text label of the item 90 | * 91 | * @return the text label of the item 92 | */ 93 | public String getValue() { 94 | return this.mName; 95 | } 96 | 97 | /** 98 | * This is the task the item performs when called. Overwritten by subclasses. 99 | */ 100 | public abstract void doAction(); 101 | 102 | /** 103 | * Compares this item to another one. They are compared first by priority and next by their text labels. 104 | * 105 | * @param other The other object. 106 | * @return The difference in priority between the two or {@link String#compareTo(Object)} if equal. 107 | */ 108 | public int compareTo(Object other) { 109 | if (!(other instanceof LauncherAction)) 110 | return -1; 111 | if (this.mPriority == ((LauncherAction) other).mPriority) 112 | return this.mName.compareTo(((LauncherAction) other).mName); 113 | return this.mPriority - ((LauncherAction) other).mPriority; 114 | } 115 | 116 | /** 117 | * Sets the visibility of the arrow 118 | * 119 | * @param hasArrow Does this item have an arrow? 120 | * @see com.yifanlu.Kindle.LauncherMenu#hasArrow() 121 | */ 122 | public void setHasArrow(boolean hasArrow) { 123 | mHasArrow = hasArrow; 124 | } 125 | 126 | /** 127 | * If true, the menu item will have a small arrow to the far right of the text. 128 | * 129 | * @return Does this item have an arrow? 130 | */ 131 | public boolean hasArrow() { 132 | return mHasArrow; 133 | } 134 | 135 | /** 136 | * The display order of this item as specified on creation. 137 | * 138 | * @return The priority of the item 139 | */ 140 | public int getPriority() { 141 | return mPriority; 142 | } 143 | 144 | /** 145 | * Tells the Kindle Reader SDK that this item should be enabled. 146 | * 147 | * @return The SDK type of the item 148 | */ 149 | public int getType() { 150 | return ReaderAction.TYPE_ALL; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/LauncherMenu.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import com.amazon.agui.swing.MenuDialog; 22 | import com.amazon.kindle.util.lipc.LipcException; 23 | import com.amazon.kindle.util.lipc.LipcService; 24 | import edu.emory.mathcs.backport.java.util.PriorityQueue; 25 | 26 | import javax.swing.*; 27 | 28 | /** 29 | * A menu item that contains a submenu. 30 | * 31 | * @author Yifan Lu 32 | * @version 1.0 33 | */ 34 | public class LauncherMenu extends LauncherAction { 35 | private MenuDialog mDialog; 36 | private PriorityQueue mItems; 37 | private LauncherMenu mParent; 38 | 39 | /** 40 | * Creates a new submenu with its text label and priority 41 | * 42 | * @param name The text to show 43 | * @param priority The order of this item in comparison to others 44 | */ 45 | public LauncherMenu(String name, int priority) { 46 | this(name, priority, null); 47 | } 48 | 49 | /** 50 | * Creates a new submenu with its text label, priority, and parent menu 51 | * 52 | * @param name The text to show 53 | * @param priority The order of this item in comparison to others 54 | * @param parent The menu to go to when the "Previous" item is selected 55 | */ 56 | public LauncherMenu(String name, int priority, LauncherMenu parent) { 57 | super(name, priority); 58 | mItems = new PriorityQueue(); 59 | mParent = parent; 60 | setHasArrow(true); 61 | } 62 | 63 | /** 64 | * Renders the dialog on screen. 65 | * 66 | * @see LauncherMenu#getMenu() 67 | */ 68 | public synchronized void doAction() { 69 | getMenu().postDialog(getCurrentAppId(), true); 70 | if (mParent != null) { 71 | mParent.putValue(Action.NAME, mParent.getValue()); 72 | } 73 | } 74 | 75 | /** 76 | * The menu must be displayed in context to the current booklet on screen, this method finds it. 77 | * 78 | * @return The current app that is displayed. 79 | */ 80 | private String getCurrentAppId() { 81 | try { 82 | return LipcService.getInstance().getDefaultSource().getTarget("com.lab126.appmgrd").getStringProperty("activeApp"); 83 | } catch (LipcException e) { 84 | KindleLauncher.LOG.error("Cannot get current running app from lipc."); 85 | e.printStackTrace(); 86 | } 87 | return "com.lab126.booklet.home"; 88 | } 89 | 90 | /** 91 | * Converts the list of menu items into a dialog containing the items. 92 | */ 93 | public void initMenu() { 94 | mDialog = new MenuDialog(getCurrentAppId()); 95 | mDialog.setTitle(this.getValue()); 96 | PriorityQueue copy = new PriorityQueue(); 97 | while (!mItems.isEmpty()) { 98 | LauncherAction item = (LauncherAction) mItems.remove(); 99 | if (item.hasArrow()) 100 | mDialog.addActionWithIndicator(item); 101 | else 102 | mDialog.addAction(item); 103 | copy.add(item); 104 | } 105 | if (mParent != null) { 106 | mParent.putValue(Action.NAME, "« Previous"); 107 | mDialog.addAction(mParent); 108 | } 109 | mItems = copy; 110 | } 111 | 112 | /** 113 | * Adds an item to the menu. 114 | * 115 | * @param item The item to add. 116 | */ 117 | public void addMenuItem(LauncherAction item) { 118 | mItems.add(item); 119 | mDialog = null; 120 | } 121 | 122 | /** 123 | * Removes an item from the menu. 124 | * 125 | * @param item The item to remove. 126 | */ 127 | public void removeMenuItem(LauncherAction item) { 128 | mItems.remove(item); 129 | mDialog = null; 130 | } 131 | 132 | /** 133 | * All the menu items added. 134 | * 135 | * @return An array containing all the menu items added. 136 | */ 137 | public LauncherAction[] getMenuItems() { 138 | return (LauncherAction[]) mItems.toArray(new LauncherAction[0]); 139 | } 140 | 141 | /** 142 | * Is the menu empty? 143 | * 144 | * @return The emptiness of the menu. 145 | */ 146 | public boolean isMenuEmpty() { 147 | return mItems.isEmpty(); 148 | } 149 | 150 | /** 151 | * Empty the menu. 152 | */ 153 | public void clearMenu() { 154 | mItems.clear(); 155 | } 156 | 157 | /** 158 | * Gets the dialog generated by {@link com.yifanlu.Kindle.LauncherMenu#initMenu()} and calls it if the dialog 159 | * has not been generated yet. 160 | * 161 | * @return A dialog containing the menu items. 162 | * @see com.yifanlu.Kindle.LauncherMenu#initMenu() 163 | */ 164 | public MenuDialog getMenu() { 165 | if (mDialog == null) { 166 | this.initMenu(); 167 | } 168 | return mDialog; 169 | } 170 | 171 | /** 172 | * Sets the parent menu so an option to go to the previous menu is added. 173 | * 174 | * @param parent The menu to go back to. 175 | */ 176 | public void setParent(LauncherMenu parent) { 177 | this.mParent = parent; 178 | } 179 | 180 | /** 181 | * Gets the parent menu. 182 | * 183 | * @return The parent menu 184 | * @see LauncherMenu#setParent(LauncherMenu) 185 | */ 186 | public LauncherMenu getParent() { 187 | return this.mParent; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/LauncherScript.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import java.io.File; 22 | 23 | /** 24 | * A menu item that executes a shell command. 25 | * 26 | * @author Yifan Lu 27 | * @version 1.0 28 | * @see JSONMenu 29 | */ 30 | public class LauncherScript extends LauncherAction { 31 | private File mScript; 32 | private String mArgs; 33 | 34 | /** 35 | * Creates a new launch script menu item. 36 | * 37 | * @param name The text to show 38 | * @param priority The order of this item in comparison to others 39 | * @param script The shell script or command to run 40 | * @param args The arguments of the script 41 | */ 42 | public LauncherScript(String name, int priority, File script, String args) { 43 | super(name, priority); 44 | this.mScript = script; 45 | this.mArgs = args; 46 | } 47 | 48 | /** 49 | * Executes the shell command with parameters 50 | */ 51 | public synchronized void doAction() { 52 | StringBuffer out = new StringBuffer(); 53 | StringBuffer err = new StringBuffer(); 54 | KindleLauncher.SERVICES.getDeviceService().exec(mScript.getAbsolutePath() + " " + mArgs, out, err); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/Menuable.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | /** 22 | * Represents an object that stores menu items. All Java menu extensions must implement this. 23 | * 24 | * @author Yifan Lu 25 | * @version 1.0 26 | * @see ExtensionsLoader 27 | */ 28 | public interface Menuable { 29 | /** 30 | * Adds menu items to the parent menu. The parent is usually the main Launcher menu. 31 | * 32 | * @param menu The parent menu. 33 | */ 34 | public void addItemsToMenu(LauncherMenu menu); 35 | } 36 | -------------------------------------------------------------------------------- /src/com/yifanlu/Kindle/ReaderPluginLauncher.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Kindle Launcher 3 | * GUI menu launcher for Kindle Touch 4 | * Copyright (C) 2011 Yifan Lu 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | package com.yifanlu.Kindle; 20 | 21 | import com.amazon.ebook.booklet.reader.sdk.BookException; 22 | import com.amazon.ebook.booklet.reader.sdk.ReaderPlugin; 23 | import com.amazon.ebook.booklet.reader.sdk.ReaderSDK; 24 | import com.amazon.ebook.booklet.reader.sdk.ui.MenuInserter; 25 | 26 | /** 27 | * A Kindle Reader SDK plugin that adds the Launcher menu item to the main Kindle menu. 28 | * 29 | * @author Yifan Lu 30 | * @version 1.0 31 | * @see KindleLauncher 32 | */ 33 | public class ReaderPluginLauncher extends ReaderPlugin { 34 | private ReaderSDK mSdk; 35 | 36 | /** 37 | * Called by the plugin loader. Adds the Launcher menu item to the main menu. 38 | * 39 | * @param readerSDK The SDK object 40 | * @throws BookException if there is a problem creating the plugin 41 | */ 42 | public void pluginLoad(ReaderSDK readerSDK) throws BookException { 43 | mSdk = readerSDK; 44 | mSdk.getRegistry().registerMenuInserter((MenuInserter) KindleLauncher.getInstance()); 45 | } 46 | 47 | /** 48 | * Called by the plugin unloader. Removes the Launcher menu item to the main menu. 49 | */ 50 | public void pluginUnload() { 51 | mSdk.getRegistry().deregisterMenuInserter((MenuInserter) KindleLauncher.getInstance()); 52 | } 53 | 54 | /** 55 | * The name of the plugin. 56 | * 57 | * @return The name of the plugin. 58 | */ 59 | public String getName() { 60 | return "Launcher"; 61 | } 62 | } 63 | --------------------------------------------------------------------------------