📄 gmapviewer.java
字号:
package org.sreid.j2me.gmapviewer;import java.util.*;import java.io.*;import javax.microedition.lcdui.*;import javax.microedition.io.*;import javax.microedition.midlet.*;import org.sreid.j2me.util.*;public class GMapViewer extends MIDlet { final boolean debug = false; /** This MIDlet's display. */ final Display display; /** User preferences (persistent). */ final Preferences prefs; /** Shared chunks of memory (byte array(s)), allocated before memory gets fragmented so as to avoid heap compaction later on. */ final ResourcePool sharedBuffers; /** Background worker thread(s) used for: downloading map tiles */ final AsyncProcessor async1; /** Background worker thread(s) used for: decoding map tiles, submitting searches */ final AsyncProcessor async2; final GMapCanvas canvas; final MapTileCache cache; final MapTileManager mtm; final MapPinManager mpm; final MainMenu mainMenu; final MapPinMenu mapPinMenu; final SearchMenu searchMenu; final PrefsEditor prefsEditor; final Vector log = new Vector(); private boolean hideErrors = false; private boolean clean; // if false, cleanup still needs to be run boolean online = true; public GMapViewer() { display = Display.getDisplay(this); prefs = new Preferences(this); prefs.loadPreferences(); boolean success = false; try { int dt = prefs.getInt("downloadThreads", 1); if (dt < 1) dt = 1; if (dt > 4) dt = 4; byte[][] sb = new byte[dt][]; for (int i = 0; i < dt; i++) { sb[i] = new byte[32000]; } sharedBuffers = new ResourcePool(sb); async1 = new AsyncProcessor(dt); async2 = new AsyncProcessor(1); canvas = new GMapCanvas(this); cache = new MapTileCache(this); mtm = new MapTileManager(this); // depends: cache mpm = new MapPinManager(this); mainMenu = new MainMenu(this); mapPinMenu = new MapPinMenu(this); searchMenu = new SearchMenu(this); prefsEditor = new PrefsEditor(this); // depends: prefs success = true; } finally { if (!success) { try { // Some kind of exception/error, probably user set downloadThreads too high. prefs.put("downloadThreads", "1"); prefs.savePreferences(); } catch (Throwable t) { } } } } public void startApp() { debug("startApp()"); clean = false; canvas.loadPosition(); cache.openRMS(); mpm.openRMS(); mapPinMenu.loadList(); display.setCurrent(mainMenu); canvas.repaint(); // Clean up obsolete preferences String[] unused = new String[] { "canvas.xpos", "canvas.xoff", "canvas.ypos", "canvas.yoff" }; for (int i = 0; i < unused.length; i++) { prefs.remove(unused[i]); } } public void pauseApp() { debug("pauseApp()"); cleanup(); } public void destroyApp(boolean unconditional) { debug("destroyApp()"); if (!clean) cleanup(); notifyDestroyed(); } void quit() { if (clean) destroyApp(false); Dialog dlg = Dialog.createConfirmationDialog("Closing GMapViewer", "Closing GMapViewer. This may take a while. Please wait...", "", ""); dlg.showOn(this, dlg); async2.enqueueJob(new Runnable() { public void run() { destroyApp(false); }}); } private void cleanup() { if (clean) return; cache.compact(); canvas.savePosition(); prefs.savePreferences(); cache.closeRMS(); mpm.closeRMS(); clean = true; debug("cleanup() done"); } void debug(Object info) { if (debug) { System.err.println(info); } } void exception(String message, Throwable exception) { try { if (debug) { System.err.println(message); exception.printStackTrace(); } log.addElement(message + "\n" + exception + "\n-----\n"); if (log.size() > 20) log.removeElementAt(0); if (!hideErrors && mainMenu != null) { final Dialog dlg = Dialog.createConfirmationDialog("Error", message + "\n\nSee the error log (from the main menu) for more details.", "OK", "Hide errors"); dlg.setCallback(new Runnable() { public void run() { if (dlg.getUserResponse() == null) { hideErrors = true; } }}); dlg.showSerially(this, mainMenu); } } catch (Throwable t) { // Exception while handling an exception. Very bad, but can't do much about it. t.printStackTrace(); } } void alert(final Alert alert) { display.setCurrent(alert, display.getCurrent()); } void alert(String title, String message) { Alert a = new Alert(title, message, null, null); //a.setTimeout(Alert.FOREVER); alert(a); } /** * Loads data from the server, checking our special 5-byte header. * @param action the action specifier * @param params URL parameters, must start with &. * @param buffer the buffer to load data in to. Must be large enough to contain all the data. * @param expectedHeader the expected header word. * @return the number of bytes actually read */ int getDataFromServer(String action, String params, byte[] buffer, String expectedHeader) throws IOException { ContentConnection conn = null; InputStream in = null; try { String url = prefs.getString("gatewayURL", "") + "?p=" + prefs.getString("gatewayAuth", "") + "&a=" + action + params; debug("Fetching URL: " + url); conn = (ContentConnection)Connector.open(url); in = conn.openInputStream(); // Get special 5-byte header StringBuffer sb = new StringBuffer(); for (;;) { int c = in.read(); if (c == -1 || c == (int)':') break; sb.append((char)c); } String header = sb.toString(); // Read data int count = 0; for (;;) { int c = in.read(buffer, count, buffer.length - count); if (c < 0) break; count += c; if (count >= buffer.length) break; } if (header.equals(expectedHeader)) { return count; } else if (header.equals("ERROR")) { throw new IOException("Server reported error: " + new String(buffer, 0, count)); } else { throw new IOException("Invalid response from server: " + Util.bytesToHex(buffer, 0, count)); } } finally { try { if (in != null) in.close(); } catch (Exception e) { } try { if (conn != null) conn.close(); } catch (Exception e) { } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -