Автор неизвестен - Платформа J2Me
118 String formTitle = getResource ("title");
119 form = new HelloForm2(formTitle);
120
121 // Это приложение просто отображает одну.
122 // форму, созданную выше.
123 display = Display.getDisplay (this);
124 display.setCurrent(form);
125 }
126
127 /**
128 Загружает определенные пользователем ресурсы приложения
129 из указанного файла. Файл является частью файла JAR
130 приложения, расположенного на реальном устройстве.
131 J2MEWTK хранит файл в файле JAR приложения, расположенном
132 в директории приложения bin/.
133
134 @param file — имя определенного пользователем файла
135 ресурса приложения.
136 */
137 private int loadResources(String file)
138 {
139. Class с = getClass ();
140
141 if (file == null)
142 {
143 return -1;
144 }
145 InputStream is = null;
146 is = с. getResourceAsStream(file);
147 if (is == null)
148 {
149 return -1;
150 }
151 Reader reader = new InputStreamReader(is);
152 processStream(reader);
153 return 0;
154 }
155
156 /**
157
158 */
159 private void processStream(Reader stream)
160 {
161 if (stream == null)
162 {
163 return;
164 }
165 StringBuffer key = new StringBuffer();;
166 StringBuffer value = new StringBuffer ();;
167 while (true)
168 {
169 // Считываем строку. Предполагается, что каждая строка
170 // содержит ключ и значение,
171 // отделенные двоеточием. Если -1, значит
172 // мы достигли конца файла.
173 key.deletef(), key.length());
174 value.delete(0, value.length());
175 int status = readLine(key, value, stream);
176 if (status == -1)
177 {
178 break;
179 }
180
181 // Вставляем этот ресурс в хэшированную таблицу
182 // ресурсов приложения.
183 resources.put(key, value);
184 }
185 }
186
187 /**
188 Считывает и обрабатывает следующую не пустую строку
189 из потока. Формат строки ожидается следующий
190 <ключ>[t]*:[и]*<значение>, где
191 <ключ> and <значение> являются метками, состоящими
192 из буквенных символов или знаков пунктуации, но не
193 из пустых знаков пробела.
194 */
195 private int readLine(StringBuffer key,
196 StringBuffer value,
197 Reader stream)
198 {
199 if (key == null || value == null ||
200 stream == null)
201 {
202 return -1;
203 }
204
205 try
206 {
207 char c;
208 while (true)
209 {
210 // Пропускаем символы новой строки.
211 while (true)
212 {
213 с = (char) stream.read ();
214 if (c == rn')
215 {
216 continue;
217 }
218 break;
219 }
220
221 if (lisWhiteSpace(c) Si!isDelimeter(c))
222 {
223 key.append(c);
224 }
225
226 // Пропускаем впередиидущий пробел.
227 while (true)
228 {
229 с = (char) stream.read();
230 if (isWhiteSpace (c))
231 {
232 continue;
233 }
234 break;
235 }
236
237 if (lisWhiteSpace(c) S&!isDelimeter(c))
238 {
239 key.append (с);
240 }
241
242 // Считываем ключ.
243 while (true)
244 {
245 с = (char) stream.read();
246 if (isWhiteSpace(c) II isDeliraeter(c))
247 {
248 break;
249 }
250 else
251 {
252 key.append(c);
253 }
254 }
255
256 // Пропускаем пробел, идущий перед или
257 // после символа.
258 while (true)
259 {
260 с = (char) stream.read();
261 if (isWhiteSpace(c) II isDelimeter(c))
262 {
263 continue;
264 }
265 value.append(c);
266 break;
267 }
268
269 // Считываем остальную часть значения метки.
270 while (true)
271 {
272 с = (char) stream.read();
273 if (c == n')
274 {
275 break;
276 }
277 else
278 {
279 value.append(c);
280 }
281 }
282 break;
283 }
284 }
285 catch (lOException ioe)
286 {
287 ioe.printStackTrace();
288 return -1;
289 }
290 return 0;
291 }
292
293 /**
294
295 */
296 private boolean isWhiteSpace(char c)
297 {
298 if (c == И с == t')
299 {
300 return true;
301 }
302 else
303 {
304 return false;
305 }
306 }
307
308 /**
309
310 */
311 private boolean isDelimeter(char c)
312 {
313 if (c ==:)
314 {
315 return true;
316 }
317 return false;
318 }
319
320 /**
321 Выдает значение, связанное с указанным
322 ключом из пакета ресурсов приложения.
323
324 @param key — ключ пары «ключ-значение».
325
326 @выдает значение, связанное с
327 указанным ключом.
328 */
329 private String getResource(String key)
330 {
331 if (resources == null)
332 {
333 return null;
334 }
335 return (String) resources.get (-key);
336 }
337
338 /**
339 Прекращает выполнение. Запрашивает реализацию
340 на завершение данного MID-лета.
341 */
342 public void quit()
343 {
344 notifyDestroyed ();
345 }
346
347 public void destroyApp(boolean destroy)
348 {
349
350 }
351
352 public void pauseApp()
353 {
354
355 }
356 }
Листинг 9.6. Класс HelloForm2 теперь использует API I18Nderao2.getResource() для извлечения локализованных ресурсов
1 import javax.microedition.midlet.MIDlet;
2
3 import javax.microedition.Icdui.Alert;
4 import javax.microedition.Icdui.AlertType;
5 import javax.microedition.Icdui.Command;
6 import javax.microedition.Icdui.CommandListener;
7 import javax.mi'croedition. Icdui.Display;
8 import javax.microedition.Icdui.Displayable;
9 import javax.microedition.Icdui.Form;
10
11 /**
12 Данный класс определяет Form, которая отображает некоторый
13 простой текст и меню команд. Цель данного класса
14 продемонстрировать интернационализацию и локализацию
15 видимых пользователю атрибутов. Он работает с классом
16 I18NDemo2.
17 */
18 public class HelloForm2 extends Form
19 {
20 // Заголовок даннвй Form, устанавливаемый по умолчанию.
21 private static final String DEFAULTJTITLE =
22 "Hello, World";
23
24 // Блок прослушивания команд, который обрабатывает
25 // командные события в данной Form.
26 private MyCommandListener cl = new
27 MyCommandListener (1;
28
29 // Экземпляр дисплея, связанный с данным
30 // MID-летом.
31 Display display;
32
33 // Ссылка на связанный с данным объектом
34 // объект MID-лета.
35 IlSNDemo midlet;
36
37 // Уведомление, отображаемое в ответ на активацию
38 // некоторой из команд данной Form.
39 Alert alert;
40
41 private Command showAlert;
42 private Command sayHi;
43 private Command cancel;
44 private Command exit;
45 private Command help;
46 private Command item;
47 private Command ok;
48 private Command screen;
49 private Command stop;
50
51 /**
52 Конструктор No-arg. Устанавливает заголовок
53 по умолчанию данной формы.
54 */
55 HelloForm2()
56 {
57 this(DEFAULT_TITLE);
58 }
59
60 /**
61 Конструктор.
62
63 @param title — Заголовок данной Form.
64 */
65 KelloForm2(String title)
66 {
67 super (title);
68
69 midlet = IlSNDemo.getlnstance();
70
71 // Добавляет строковый элемент в форму.
72 String msg = midlet.getResource("greeting");
73 append (msg);
74
75 display = Display.getDisplay(midlet);
76
77 // Добавляет MyCommandListener в Form для прослушивания
78 // события нажатия клавиши «Back», которое должно
79 // создавать всплывающее уведомление Alert.
80 setCommandLiscener (cl);
81
82 showAiert = new
83 Command(midlet.getResource("alert"),
84 Command.SCREEN, 1);
85 addCommand(showAlert);
86
87 sayHi = new
88 Command(midlet.getResource("sayhi"),
89 Command.SCREEN, 1);
90 addCommand(sayHi);
91
92 cancel = new
93 Command(midlet.getResource("cancel"),
94 Command.SCREEN, 1);
95 addCommand(cancel);
96
97 exit = new
98 Command(midlet.getResource("exit"),
99 Command.SCREEN, 1);
100 addCommand(exit);
101
102 help = new
103 Command(midlet.getResource("help"),
104 Command.SCREEN, 1);
105 addCommand(help);
106
107 item = new
108 Command(midlet.getResource ("item"),
109 Command.SCREEN, 1);
110 addCommand(item);
111
112 ok = new
113 Command(midlet.getResource("ok"),
114 Command.SCREEN, 1);
115 addCommand(ok);
116
117 screen = new
118 Command(midlet.getResource("screen"),
119 Command.SCREEN, 1);
120 addCommand(screen);
121
122 stop = new
123 Command(midlet.getResource("stop"),
124 Command.SCREEN, 1);
125 addCommand(stop);
126 }
127
128 // Данный класс просто прослушивает активацию
129 // какой-либо команды. Экземпляр HelloForm
130 // устанавливает экземпляр данного класса как
131 // свой блок прослушивания команд. Экземпляр
132 // объекта не проверяет информацию команды,
133 // а просто отображает модальное Alert, показывающее,
134 // что экранная клавиша была активирована пользователем.
135 public class MyCommandListener
136 реализует CommandListener
137 {
138 public void commandAction(Command c,
139 Displayable d)
140 {
141 String title =
142 midlet.getResource("alert_title");
143 String msg = midlet.getResource("alert_text");
144
145 if (с == showAlert)
146 {
147 alert = new Alert(title,
148 msg,
149 null, AlertType.INFO);
150 alert.setTimeout(Alert.FOREVER);
151 display.setCurrent(alert, HelloForm2.this);
152 }
153 else if (c == sayHi)
154 {
155 alert = new Alert(title,
156 msg,
157 null, AlertType.INFO);
158 alert.setTimeout(Alert.FOREVER);
159 display.setCurrent(alert, HelloForm2.this);
160 }
161
162 if (c == exit)
163 {
164 I18NDemo.getInstance-(). destroyApp (true);
165 }
166 }
167 }
168 }
Наиболее проблематичным аспектом данного подхода является то, что вы, разработчик, должны создать инфраструктуру, которая позволит вашим приложениям считывать и анализировать файлы ресурсов. Также приложение должно создавать структуры внутренних данных, которые содержат локализованные ресурсы, считанные из файлов. Самым проблематичным аспектом создания этой инфраструктуры является предоставление адекватной обработки потоков, особенно обработки потоков для поддержки считывания значений строковых атрибутов. Метод MIDlet.getAppProperty(), использовавшийся в предыдущей схеме, основанной на файле JAD, извлекает информацию об обработке потоков. Но в данной схеме вы должны проделать всю эту работу самостоятельно.