253 72 5MB
English Pages 464 [465] Year 2003
Programming Wireless Devices with the JavaÔ 2 Platform, Micro Edition Second Edition
The Java™ Series Lisa Friendly, Series Editor Tim Lindholm, Technical Editor Ken Arnold, Technical Editor of The JiniTM Technology Series Jim Inscore, Technical Editor of The JavaTM Series, Enterprise Edition Eric Armstrong, Stephanie Bodoff, Debbie Carson, Maydene Fisher, Dale Green, Kim Haase The Java™ Web Services Tutorial Ken Arnold, James Gosling, David Holmes The Java™ Programming Language, Third Edition Cindy Bloch, Annette Wagner MIDP 2.0 Style Guide Joshua Bloch Effective Java™ Programming Language Guide Mary Campione, Kathy Walrath, Alison Huml The Java™ Tutorial, Third Edition: A Short Course on the Basics Mary Campione, Kathy Walrath, Alison Huml,Tutorial Team The Java™ Tutorial Continued: The Rest of the JDK™ Patrick Chan The Java™ Developers Almanac 1.4, Volume 1 Patrick Chan The Java™ Developers Almanac 1.4, Volume 2 Patrick Chan, Rosanna Lee The Java™ Class Libraries, Second Edition, Volume 2: java.applet, java.awt, java.beans Patrick Chan, Rosanna Lee, Doug Kramer The Java™ Class Libraries, Second Edition, Volume 1: java.io, java.lang, java.math, java.net, java.text, java.util Patrick Chan, Rosanna Lee, Doug Kramer The Java Class Libraries, Second Edition, Volume 1: Supplement for the Java™ 2 Platform, Standard Edition, v1.2 Kirk Chen, Li Gong Programming Open Service Gateways with Java™ Embedded Server Zhiqun Chen Java Card™ Technology for Smart Cards: Architecture and Programmer’s Guide Maydene Fisher, Jon Ellis, Jonathan Bruce JDBC™ API Tutorial and Reference, Third Edition Li Gong, Gary Ellison, Mary Dageforde Inside Java™ 2 Platform Security, Second Edition: Architecture, API Design, and Implementation James Gosling, Bill Joy, Guy Steele, Gilad Bracha The Java™ Language Specification, Second Edition Doug Lea Concurrent Programming in Java™, Second Edition: Design Principles and Patterns Rosanna Lee, Scott Seligman JNDI API Tutorial and Reference: Building DirectoryEnabled Java™ Applications Sheng Liang The Java™ Native Interface: Programmer’s Guide and Specification ™
http://www.javaseries.com
Tim Lindholm, Frank Yellin The Java™ Virtual Machine Specification, Second Edition Roger Riggs, Antero Taivalsaari, Jim Van Peursem, Jyri Huopaniemi, Mark Patel, Aleksi Uotila Programming Wireless Devices with the Java™ 2 Platform, Micro Edition, Second Edition Henry Sowizral, Kevin Rushforth, Michael Deering The Java 3D™ API Specification, Second Edition Sun Microsystems, Inc. Java™ Look and Feel Design Guidelines: Advanced Topics Kathy Walrath, Mary Campione The JFC Swing Tutorial: A Guide to Constructing GUIs Seth White, Maydene Fisher, Rick Cattell, Graham Hamilton, Mark Hapner JDBC™ API Tutorial and Reference, Second Edition: Universal Data Access for the Java™ 2 Platform Steve Wilson, Jeff Kesselman Java™ Platform Performance: Strategies and Tactics
The Jini™ Technology Series Eric Freeman, Susanne Hupfer, Ken Arnold JavaSpaces™ Principles, Patterns, and Practice
The Java™ Series, Enterprise Edition Stephanie Bodoff, Dale Green, Kim Haase, Eric Jendrock, Monica Pawlan, Beth Stearns The J2EE™ Tutorial Rick Cattell, Jim Inscore, Enterprise Partners J2EE™ Technology in Practice: Building Business Applications with the Java™ 2 Platform, Enterprise Edition Mark Hapner, Rich Burridge, Rahul Sharma, Joseph Fialli, Kim Haase Java™ Message Service API Tutorial and Reference: Messaging for the J2EE™ Platform Inderjeet Singh, Beth Stearns, Mark Johnson, Enterprise Team Designing Enterprise Applications with the Java™ 2 Platform, Enterprise Edition Vlada Matena, Sanjeev Krishnan, Linda DeMichiel, Beth Stearns Applying Enterprise JavaBeans™ 2.1, Second Edition: Component-Based Development for the J2EE™ Platform Bill Shannon, Mark Hapner, Vlada Matena, James Davidson, Eduardo Pelegri-Llopart, Larry Cable, Enterprise Team Java™ 2 Platform, Enterprise Edition: Platform and Component Specifications Rahul Sharma, Beth Stearns, Tony Ng J2EE™ Connector Architecture and Enterprise Application Integration
Programming Wireless Devices with the Java 2 Platform, Micro Edition Second Edition
J2ME Connected Limited Device Configuration (CLDC) 1.1 Mobile Information Device Profile (MIDP) 2.0
Roger Riggs Antero Taivalsaari Jim Van Peursem Jyri Huopaniemi Mark Patel Aleksi Uotila Jim Holliday, Editor
Boston • San Francisco • New York • Toronto • Montreal London • Munich • Paris • Madrid Capetown • Sydney • Tokyo • Singapore • Mexico City
Copyright © 2003 Sun Microsystems, Inc. 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved. Sun Microsystems, Inc. has intellectual property rights relating to implementations of the technology described in this publication. In particular, and without limitation, these intellectual property rights may include one or more U.S. patents, foreign patents, or pending applications. Sun, Sun Microsystems, the Sun logo, J2ME, Java Card, and all Sun and Java based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc., in the United States and other countries. UNIX is a registered trademark in the United States and other countries, exclusively licensed through X/Open Company, Ltd. THIS PUBLICATION IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NONINFRINGEMENT. THIS PUBLICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION HEREIN; THESE CHANGES WILL BE INCORPORATED IN NEW EDITIONS OF THE PUBLICATION. SUN MICROSYSTEMS, INC. MAY MAKE IMPROVEMENTS AND/OR CHANGES IN THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THIS PUBLICATION AT ANY TIME. The publisher offers discounts on this book when ordered in quantity for bulk purchases and special sales. For more information, please contact U.S. Corporate and Government Sales, (800) 382-3419, [email protected]. For sales outside of the U.S., please contact International Sales, (317) 581-3793, [email protected]. Visit Addison-Wesley on the Web: www.awprofessional.com Library of Congress Cataloging-in-Publication Data Programming wireless devices with the Java 2 Platform : micro edition / Roger Riggs ... [et al.] p. cm. ISBN 0-321-19798-4 (alk. paper) 1. Wireless communication systems. 2. Java (Computer program language) I. Riggs, Roger. TK5103.2.P75 2003 005.2'762—dc21 2003010117 All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. Printed in the United States of America. Published simultaneously in Canada. For information on obtaining permission for use of material from this work, please submit a written request to Pearson Education, Inc., Rights and Contracts Department, 75 Arlington Street, Suite 300, Boston, MA 02116, Fax: (617) 848-7047. ISBN 0-321-19798-4 Text printed on recycled paper 1 2 3 4 5 6 7 8 9 10—CRS—0706050403 First printing, June 2003
“If a program is useful, it will have to be changed.” — ACM SIGPLAN Notices (vol 2, no. 2), 1965
“To attain knowledge, add things every day; to obtain wisdom, remove things every day.” — Lao-tsu, Tao Te Ching
“One must learn by doing the thing; For though you think you know it, you have no certainty until you try.” — Sophocles, Trachiniae
This page intentionally left blank
Contents
1
Figures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xvii Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxvii Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.1 1.2 1.3 1.4
2
Overview of Java 2 Platform, Micro Edition (J2ME™) . . . . . . . . 7 2.1 2.2 2.3
2.4
3
The Wireless Internet Revolution. . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Why Java™ Technology for Wireless Devices? . . . . . . . . . . . . . . . . 2 A Bit of History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 J2ME™ Standardization Efforts . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Java 2 Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Java 2 Platform, Micro Edition (J2ME) . . . . . . . . . . . . . . . . . . . . . . . 9 Key Concepts of the J2ME Architecture . . . . . . . . . . . . . . . . . . . . . 10 2.3.1 Profiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3.2 Configurations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.3.3 Optional Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Evolution of the J2ME Platform. . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.4.1 Core J2ME Standardization Efforts . . . . . . . . . . . . . . . . . . . 18 2.4.2 Optional Packages for the Wireless Market. . . . . . . . . . . . . 19
Goals, Requirements, and Scope. . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.1
3.2
High-Level Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 3.1.1 Dynamic Delivery of Java Applications and Content . . . . . 24 3.1.2 Third-Party Application Development . . . . . . . . . . . . . . . . 24 3.1.3 Independence of Network Technology Standards . . . . . . . . 25 3.1.4 Compatibility with Other Wireless Application Standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Target Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
vii
viii
CONTENTS
3.3 3.4
3.5
4
Connected Limited Device Configuration . . . . . . . . . . . . . . . . . . . 39 4.1
4.2
4.3
4.4
4.5
5
General Notes on Consumer Devices and Embedded Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.4.1 Hardware Requirements of CLDC . . . . . . . . . . . . . . . . . . . 31 3.4.2 Hardware Requirements of MIDP . . . . . . . . . . . . . . . . . . . . 32 3.4.3 Software Requirements of CLDC . . . . . . . . . . . . . . . . . . . . 32 3.4.4 Software Requirements of MIDP . . . . . . . . . . . . . . . . . . . . 33 3.4.5 J2ME Requirements. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Scope of the CLDC and MIDP Standards . . . . . . . . . . . . . . . . . . . . 35 3.5.1 Scope of CLDC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.5.2 Scope of MIDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 CLDC Expert Groups. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.1.1 CLDC 1.0 Expert Group . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.1.2 CLDC 1.1 Expert Group . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 CLDC Architecture, Application Model, and Security . . . . . . . . . . 41 4.2.1 Architectural Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.2.2 The Concept of a Java Application . . . . . . . . . . . . . . . . . . . 42 4.2.3 Application Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 4.2.4 Application Management. . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Java Language Specification Compatibility. . . . . . . . . . . . . . . . . . . 46 4.3.1 No Finalization of Class Instances . . . . . . . . . . . . . . . . . . . 47 4.3.2 Error-Handling Limitations . . . . . . . . . . . . . . . . . . . . . . . . . 47 Java Virtual Machine Specification Compatibility . . . . . . . . . . . . . 48 4.4.1 Features Eliminated from the Virtual Machine . . . . . . . . . . 48 4.4.2 Class File Verification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 4.4.3 Class File Format and Class Loading . . . . . . . . . . . . . . . . . 52 New for CLDC 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
CLDC Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.1 5.2
Background and Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Classes Derived from Java 2 Standard Edition . . . . . . . . . . . . . . . . 58 5.2.1 System Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 5.2.2 Data Type Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 5.2.3 Collection Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 5.2.4 Input/Output Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 5.2.5 Calendar and Time Classes . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.2.6 Additional Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.2.7 Exception and Error Classes . . . . . . . . . . . . . . . . . . . . . . . . 60
CONTENTS
5.3
5.4
6
Mobile Information Device Profile . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.1
6.2
7
MIDP Expert Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 6.1.1 MIDP 1.0 Expert Group. . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 6.1.2 MIDP 2.0 Expert Group. . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Areas Covered by the MIDP Specification . . . . . . . . . . . . . . . . . . . 76
MIDP Application Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 7.1
7.2 7.3
8
5.2.8 Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 5.2.9 Internationalization Support. . . . . . . . . . . . . . . . . . . . . . . . . 62 5.2.10 Property Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 CLDC-Specific Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 5.3.1 Background and Motivation . . . . . . . . . . . . . . . . . . . . . . . . 64 5.3.2 The Generic Connection Framework. . . . . . . . . . . . . . . . . . 65 5.3.3 No Network Protocol Implementations Defined in CLDC. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 5.3.4 Summary of the Generic Connection Interfaces . . . . . . . . . 67 New for CLDC 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
MIDlets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 7.1.1 MIDlet States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 7.1.2 Using the startApp, pauseApp, and destroyApp Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 7.1.3 Application Lifecycle and the User Interface API. . . . . . . . 87 MIDlet Suites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
MIDP User Interface Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 8.1 8.2
8.3
8.4 8.5
MIDP UI Compared to Desktop AWT. . . . . . . . . . . . . . . . . . . . . . . 90 Structure of the MIDP User Interface API . . . . . . . . . . . . . . . . . . . . 90 8.2.1 Displayable Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 8.2.2 Low-Level User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . 93 8.2.3 High-Level User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95 8.3.1 Current Displayable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 8.3.2 Screen Backlight and Device Vibrator . . . . . . . . . . . . . . . . 97 Displayables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 8.4.1 Ticker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 8.5.1 Command Mapping to Device User Interface . . . . . . . . . . 100 8.5.2 Command Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
ix
x
CONTENTS
8.6
8.7
9
8.5.3 Command Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 8.5.4 Command Listeners . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 Advanced Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 8.6.1 System Screens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 8.6.2 Adaptation to Device-Specific User Interface Style . . . . . 106 8.6.3 Device-Provided Operations . . . . . . . . . . . . . . . . . . . . . . . 107 8.6.4 A Note on Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
MIDP High-Level User Interface – Screen . . . . . . . . . . . . . . . . . 111 9.1
9.2
9.3
9.4 9.5
List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 9.1.1 Implicit List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 9.1.2 Exclusive Choice List . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 9.1.3 Multiple Choice List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 9.1.4 Long List Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 9.1.5 List Element Fonts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 TextBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 9.2.1 Input Constraints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 9.2.2 Input Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Alert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 9.3.1 Commands in Alert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 9.3.2 Activity Indicator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
10 MIDP High-Level User Interface – Form . . . . . . . . . . . . . . . . . . 129 10.1 Item. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 10.1.1 ItemStateListener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 10.1.2 Item Commands. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 10.2 StringItem. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 10.2.1 Appearance Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 10.3 ImageItem. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 10.4 TextField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 10.5 DateField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 10.6 ChoiceGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 10.7 Gauge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 10.8 CustomItem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 10.8.1 Interaction Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 10.8.2 Traversal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
CONTENTS
10.9 Form Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 10.9.1 Row Breaks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140 10.9.2 Label Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 10.9.3 Current Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 10.9.4 Item Sizing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 10.9.5 Row Filling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 10.9.6 Spacer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 10.10 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
11 MIDP Low-Level User Interface Libraries . . . . . . . . . . . . . . . . . 149 11.1 The Canvas API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 11.1.1 Canvas Dimensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 11.1.2 Redrawing Mechanism . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 11.1.3 Drawing Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 11.1.4 Canvas Visibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 11.2 Low-Level API for Events in Canvases . . . . . . . . . . . . . . . . . . . . . 152 11.2.1 Key Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 11.2.2 Action Keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 11.2.3 Pointer Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 11.3 Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 11.3.1 Coordinate System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 11.3.2 Clipping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 11.3.3 Translation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 11.3.4 Color Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 11.3.5 Line Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 11.3.6 Fonts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 11.4 Creating and Using Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 11.4.1 Immutable Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 11.4.2 Mutable Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 11.4.3 Transparency and Alpha Blending. . . . . . . . . . . . . . . . . . . 157 11.4.4 Getting RGB Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 11.4.5 Anchor Points. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 11.5 Drawing Primitives. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 11.5.1 Drawing Lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 11.5.2 Drawing and Filling Arcs. . . . . . . . . . . . . . . . . . . . . . . . . . 161 11.5.3 Drawing and Filling Rectangles. . . . . . . . . . . . . . . . . . . . . 162 11.5.4 Drawing and Filling Rounded Rectangles . . . . . . . . . . . . . 164 11.5.5 Filling Triangles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 11.5.6 Drawing Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 11.5.7 Drawing Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
xi
xii
CONTENTS
11.5.8 Drawing RGB Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168 11.5.9 Copying an Area of Pixels . . . . . . . . . . . . . . . . . . . . . . . . . 169 11.6 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
12 MIDP Game API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 12.1 The GameCanvas API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 12.1.1 Key Polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 12.1.2 Screen Buffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 12.2 Layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 12.3 Sprites. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 12.3.1 Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 12.3.2 Frame Sequence. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 12.3.3 Reference Pixel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 12.3.4 Transforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 12.4 TiledLayer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 12.4.1 Tiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 12.4.2 Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 12.5 LayerManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 12.6 Collision Detection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 12.6.1 Collision Rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 12.6.2 Pixel-Level Detection . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 12.7 Sample Code: A Simple Game. . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 12.8 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
13 MIDP Sound API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 13.1 Overview of the MIDP 2.0 Sound API . . . . . . . . . . . . . . . . . . . . . 197 13.1.1 MIDP Media Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 13.1.2 Design Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 13.1.3 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 13.1.4 MIDP Sound Architecture . . . . . . . . . . . . . . . . . . . . . . . . . 200 13.2 Player Creation and Management . . . . . . . . . . . . . . . . . . . . . . . . . 202 13.2.1 Managing a Media Framework . . . . . . . . . . . . . . . . . . . . . 202 13.2.2 Creating Players for Media Data . . . . . . . . . . . . . . . . . . . . 203 13.2.3 Tone Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 13.2.4 Sample Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 13.3 Media Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 13.3.1 ToneControl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 13.3.2 VolumeControl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 13.3.3 Custom Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
CONTENTS
13.3.4 Sample Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 13.4 Enhanced Media Support Using the Mobile Media API . . . . . . . . 217 13.4.1 DataSource. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 13.4.2 Advanced Controls. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 13.5 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
14 MIDP Persistence Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 14.1 The Record Management System. . . . . . . . . . . . . . . . . . . . . . . . . . 221 14.2 Manipulating Record Stores and Records . . . . . . . . . . . . . . . . . . . 223 14.2.1 Manipulating a Record Store . . . . . . . . . . . . . . . . . . . . . . . 223 14.2.2 Shared Record Stores. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 14.2.3 Manipulating Records in a Record Store . . . . . . . . . . . . . . 226 14.2.4 Converting Record Data to and from Byte Arrays . . . . . . 226 14.2.5 Filtering, Comparing, Listening, and Enumerating Records. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 14.3 Sample Code (RMSMIDlet.java) . . . . . . . . . . . . . . . . . . . . . . . . . 231 14.4 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
15 MIDP Networking and Serial Communications . . . . . . . . . . . . . 243 15.1 Characteristics of Wireless Data Networks . . . . . . . . . . . . . . . . . . 243 15.2 Network Interface Considerations . . . . . . . . . . . . . . . . . . . . . . . . . 244 15.3 The HttpConnection Interface. . . . . . . . . . . . . . . . . . . . . . . . . . . 245 15.3.1 States of an HTTP Connection . . . . . . . . . . . . . . . . . . . . . 245 15.3.2 Security of HTTP. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 15.3.3 Establishing a Connection . . . . . . . . . . . . . . . . . . . . . . . . . 246 15.3.4 Parsing URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247 15.3.5 HTTP Request Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . 248 15.3.6 Using an HTTP Connection. . . . . . . . . . . . . . . . . . . . . . . . 250 15.3.7 HTTP Response Headers . . . . . . . . . . . . . . . . . . . . . . . . . . 252 15.3.8 Closing an HTTP Connection . . . . . . . . . . . . . . . . . . . . . . 253 15.4 Sample Code (NetClientMIDlet.java) . . . . . . . . . . . . . . . . . . . 253 15.5 SocketConnection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 15.5.1 Getting the Local Address and Port Number. . . . . . . . . . . 264 15.5.2 Getting the Remote Host Address and Port . . . . . . . . . . . . 265 15.5.3 Getting and Setting Socket Options. . . . . . . . . . . . . . . . . . 265 15.5.4 Closing Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 15.5.5 Security of SocketConnection . . . . . . . . . . . . . . . . . . . . 266 15.5.6 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266 15.6 ServerSocketConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
xiii
xiv
CONTENTS
15.6.1 Getting the Local Address and Port Number. . . . . . . . . . . 267 15.6.2 Security of ServerSocketConnection . . . . . . . . . . . . . . 268 15.6.3 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 15.7 UDPDatagramConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 15.7.1 Getting the Local Address and Port Number. . . . . . . . . . . 269 15.7.2 Datagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 15.7.3 Closing Connections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 15.7.4 Security of UDPDatagramConnection . . . . . . . . . . . . . . . 271 15.7.5 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 15.8 CommConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272 15.8.1 Getting and Setting the Serial Port Speed . . . . . . . . . . . . . 273 15.8.2 Security for CommConnection . . . . . . . . . . . . . . . . . . . . . 274 15.8.3 Recommended Convention for Naming Ports . . . . . . . . . . 274 15.8.4 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 15.9 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
16 Secure Networking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 16.1 Checking the Security Properties of a Connection. . . . . . . . . . . . . 278 16.1.1 Server Certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 16.1.2 Printable Representation for X.509 Distinguished Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 16.2 HttpsConnection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281 16.2.1 Security of HttpsConnection . . . . . . . . . . . . . . . . . . . . . . . 281 16.2.2 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282 16.3 SecureConnection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283 16.3.1 Security of SecureConnection . . . . . . . . . . . . . . . . . . . . . . 284 16.3.2 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 16.4 MIDP X.509 Certificate Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 16.4.1 Certificate Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 16.4.2 Certificate Size. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 16.4.3 Algorithm Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286 16.4.4 Certificate Processing for HTTPS . . . . . . . . . . . . . . . . . . . 286 16.5 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
17 Event-Driven Application Launch . . . . . . . . . . . . . . . . . . . . . . . . . 289 17.1 Alarm-Based MIDlet Launch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 17.2 Network-Based MIDlet Launch . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 17.2.1 Registering a MIDlet to Be Launched . . . . . . . . . . . . . . . . 291 17.2.2 Mechanics of Static Push Registration . . . . . . . . . . . . . . . 292 17.2.3 Mechanics of Dynamic Push Registration. . . . . . . . . . . . . 294
CONTENTS
17.3 17.4 17.5 17.6
Listening and Launching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 Handling Connections after Launch . . . . . . . . . . . . . . . . . . . . . . . . 296 Security of the Push Registry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 Sample Usage Scenarios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 17.6.1 Sample Chat Application . . . . . . . . . . . . . . . . . . . . . . . . . . 298 17.6.2 Sample Ping Application . . . . . . . . . . . . . . . . . . . . . . . . . . 300 17.7 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
18 Security for MIDlet Suites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305 18.1 Assumptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 18.2 Sandbox for Untrusted MIDlet Suites . . . . . . . . . . . . . . . . . . . . . . 307 18.3 Trusted MIDlet Suite Security Model . . . . . . . . . . . . . . . . . . . . . . 308 18.3.1 Permissions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308 18.3.2 Requesting Permissions for a MIDlet Suite. . . . . . . . . . . . 310 18.3.3 Protection Domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 18.3.4 Interaction Modes for User Permissions . . . . . . . . . . . . . . 311 18.3.5 Granting Permissions to Trusted MIDlet Suites . . . . . . . . 312 18.4 APIs That Are Not Security Sensitive . . . . . . . . . . . . . . . . . . . . . . 313 18.5 Establishing Trust for MIDlet Suites by Using X.509 PKI . . . . . . 313 18.5.1 Signing a MIDlet Suite . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 18.5.2 Authenticating a MIDlet Suite . . . . . . . . . . . . . . . . . . . . . . 317 18.5.3 Caching of Authentication and Authorization Results . . . 320 18.5.4 X.509 Certificate Profile for Trusted MIDlet Suites . . . . . 320 18.6 Recommended Security Policy for GSM/UMTS Devices . . . . . . . 321 18.7 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
19 MIDlet Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 19.1 MIDlet Suites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323 19.1.1 MIDlet Suite Packaging. . . . . . . . . . . . . . . . . . . . . . . . . . . 324 19.1.2 Application Descriptor. . . . . . . . . . . . . . . . . . . . . . . . . . . . 324 19.1.3 MIDlet Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325 19.1.4 MIDlet Suite Execution Environment . . . . . . . . . . . . . . . . 330 19.2 MIDP System Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 19.3 Over-the-Air User-Initiated Provisioning. . . . . . . . . . . . . . . . . . . . 332 19.3.1 MIDlet Suite Updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 19.3.2 MIDlet Suite Removal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 19.3.3 Installation and Deletion Status Reports . . . . . . . . . . . . . . 335 19.3.4 Installation Status Codes and Messages . . . . . . . . . . . . . . 336 19.4 New for MIDP 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337
xv
xvi
CONTENTS
20 Additional MIDP APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 20.1 Timer Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 20.1.1 Using One-Shot Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 20.1.2 Using Repeating Timers . . . . . . . . . . . . . . . . . . . . . . . . . . 341 20.1.3 Sample Code (TimerMIDlet.java) . . . . . . . . . . . . . . . . . . . 342 20.2 System Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 20.3 Application Resource Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 20.4 Exiting a MIDlet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
21 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 Appendix A: CLDC Application Programming Interface . . . . . . . .355 Almanac Legend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .356 CLDC Almanac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .359 Appendix B: MIDP Application Programming Interface . . . . . . . . 391 MIDP Almanac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .393 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
Figures
Figure 2.1 Figure 2.2 Figure 2.3 Figure 3.1 Figure 3.2 Figure 3.3 Figure 4.1 Figure 4.2 Figure 5.1 Figure 7.1 Figure 8.1 Figure 10.1 Figure 10.2 Figure 10.3 Figure 11.1 Figure 11.2 Figure 11.3 Figure 11.4 Figure 11.5 Figure 11.6 Figure 11.7 Figure 11.8 Figure 11.9 Figure 11.10 Figure 11.11 Figure 11.12 Figure 11.13 Figure 11.14 Figure 11.15 Figure 11.16 Figure 11.17
Java 2 Platform editions and their target markets . . . . . . . . . . . . . . . . . . 8 Software layers in a J2ME device . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Relationship between J2ME configurations and Java 2 Standard Edition 16 Downloading customized services . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 CLDC and MIDP target devices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 One-handed, two-handed, and stylus-operated mobile information devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 Architecture overview of a CLDC target device . . . . . . . . . . . . . . . . . 42 Two-phase class file verification in CLDC . . . . . . . . . . . . . . . . . . . . . 51 Connection interface hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 MIDlet states and state transitions . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 MIDP user interface class hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . 92 General principle of Form layout . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Item layout policy dictated by the device implementation . . . . . . . . . 142 Applying vertical and horizontal layout directives . . . . . . . . . . . . . . . 145 Pixel coordinate system showing the pixel at (4,3) . . . . . . . . . . . . . 154 Example of the getRGB method . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 The anchor points for image rendering . . . . . . . . . . . . . . . . . . . . . . . 159 The anchor points for text rendering . . . . . . . . . . . . . . . . . . . . . . . . . 160 Example of the drawLine method . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Example of the drawArc method . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 Example of the fillArc method . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Example of the drawRect method . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Example of the fillRect method . . . . . . . . . . . . . . . . . . . . . . . . . . 163 Example of the drawRoundRect method . . . . . . . . . . . . . . . . . . . . . 164 Example of the fillRoundRect method . . . . . . . . . . . . . . . . . . . . . 165 Example of the fillTriangle method . . . . . . . . . . . . . . . . . . . . . . 165 Example of the drawImage method . . . . . . . . . . . . . . . . . . . . . . . . . 167 Transforms for drawing Images . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167 Example of the drawRegion method . . . . . . . . . . . . . . . . . . . . . . . . 168 Example of the drawRGB method . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 Example of the copyArea method . . . . . . . . . . . . . . . . . . . . . . . . . . 170
xvii
xviii
FIGURES
Figure 12.1 Figure 12.2 Figure 12.3 Figure 12.4 Figure 12.5 Figure 12.6 Figure 12.7 Figure 12.8 Figure 12.9 Figure 12.10 Figure 12.11 Figure 12.12 Figure 12.13 Figure 12.14 Figure 12.15 Figure 12.16 Figure 13.1 Figure 13.2 Figure 13.3 Figure 14.1 Figure 14.2 Figure 19.1 Figure 19.2
Game loop flowchart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Frames can be arranged in various ways within an Image . . . . . . . . . Each frame in the Image is assigned an index . . . . . . . . . . . . . . . . . . Example of a special frame sequence . . . . . . . . . . . . . . . . . . . . . . . . The reference pixel with a pushpin in its center . . . . . . . . . . . . . . . . . The reference pixel acts as the center for transforms applied to a Sprite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A TiledLayer’s static tile set is obtained from an Image . . . . . . . . . The TiledLayer’s cells filled with the desired tile indices . . . . . . . . Appearance of the TiledLayer . . . . . . . . . . . . . . . . . . . . . . . . . . . . An update to an animated tile is reflected in all cells that reference it . Setting the view window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The contents of the view window drawn at a specific location . . . . . . Setting a collision rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Boundary-level collision detection . . . . . . . . . . . . . . . . . . . . . . . . . . Pixel-level collision detection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A screen shot from the simple game . . . . . . . . . . . . . . . . . . . . . . . . . Overview of MIDP Sound API Architecture . . . . . . . . . . . . . . . . . . . Class diagram of the MIDP Sound API . . . . . . . . . . . . . . . . . . . . . . MIDP Sound API Player state diagram . . . . . . . . . . . . . . . . . . . . . . Structure of a record store . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Separation of RMS name spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . MIDlet suite name spaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . OTA download sequence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
174 176 177 178 179 181 181 183 183 184 185 186 187 188 188 189 201 202 205 222 223 330 333
Foreword
With the delivery of the Java™ 2 Platform, Micro Edition (J2ME™), Java technology has come full circle. The Java technology we know today originally sprang from a project whose goal was to investigate the potential impact of digital technologies outside the mainstream of the computer industry. It was clear that this big expanse of interesting territory was the space close to everyday people. Consumer electronics, telephony, and embedded systems were increasingly becoming a part of the fabric of everyday life. Being a group with a very hands-on engineering background, we decided to build an artifact as a way to lead our understanding into the details. We built a small (for its day!) handheld device, not unlike today’s PDAs. As we considered the implications of this new world, we encountered serious issues with the underlying tools we were using to build the software: • Heterogeneity was a fact of life. The consumer world has many different CPU and system architectures. In the desktop world, these differences (“WinTel” versus Macintosh) partition the market based on low-level details that most people know little about. In the consumer/embedded world, there are many more architectures than the two of the desktop world. The fragmented chaos that would ensue would cause serious problems. Heterogeneity becomes an even more urgent issue when these devices are connected in a network and then start sharing software. • Reliability is a huge issue. Non-technophiles have a justifiably low tolerance for systems that malfunction. There are a number of areas where low-level issues in the programming language design (memory integrity being one) have a large impact. • Security must be addressed. There is no bigger threat to a network than a “teenage guy” out to have fun. (I know, I was one!) Security is not something that can be painted on afterwards—it has to be built in from the beginning.
xix
xx
FOREWORD
• Consumer devices have a long life span. They live within a world that evolves. This drives a lot of issues in system construction, versioning, and modularity. • These systems were becoming distributed and needed to run on more than one machine. They needed to span many machines that would work together to provide a cohesive experience—from small systems such as cell phones, at the edge of the network, to large systems such as the switches that connect them. These pressures came together and caused a problem. My job on the project was to tackle this, and the result was the Java programming language. The early implementations were targeted at low-end devices. We released the language to the world in 1995, and it experienced phenomenal popularity. One of the side effects of that popularity was that it quickly moved upscale and was very heavily used in large industrial-strength applications. The smaller-scale fringes of the network got left behind in the enthusiasm. J2ME brings the technology back to its roots. Programming for these smaller devices can be much more challenging than for large-scale systems because of the constraints in size and speed, but it is generally more rewarding because they have a more personal interaction with their users. With this book you will learn how J2ME is applied in the wireless world. Wireless applications are a major milestone in making this technology accessible to a much wider community of software developers. The most important opportunities are those that are unexpected, that come from curious people experimenting. Read. Enjoy. Join in the fun.
James Gosling Mountain View, California, USA
Preface
I
n the past five years, Sun has collaborated with major consumer device manufacturers and other companies to create a highly portable, secure, small-footprint Java™ application development environment for resource-constrained, wireless consumer devices such as cellular telephones, two-way pagers, and personal organizers. This work started with the development of a new, small-footprint Java virtual machine called the K Virtual Machine (KVM). Two Java Community Process (JCP) standardization efforts, Connected, Limited Device Configuration (CLDC) and Mobile Information Device Profile (MIDP), were then carried out to standardize the Java libraries and the associated Java language and virtual machine features across a wide variety of consumer devices. The first round of the CLDC and MIDP standardization efforts took place during the fall of 1999 and spring of 2000. Twenty-four companies participated in the CLDC 1.0 and MIDP 1.0 standardization efforts directly, and more than five hundred companies and individuals participated indirectly by sending feedback while the standardization efforts were in progress. Major consumer device companies such as Motorola, Nokia, NTT DoCoMo, Palm Computing, Research In Motion (RIM), and Siemens played a key role in these efforts. After their first release, the CLDC 1.0 and MIDP 1.0 standards have become very popular. The deployment of real-world, Java-enabled wireless devices began in 2000, and the deployments accelerated rapidly in 2001 and 2002, approaching exponential growth. It has been estimated that over 50 million devices supporting the CLDC and MIDP standards were shipped in 2002, and the number is likely to be at least twice as large in 2003. As a result of the widespread acceptance of these standards, major business opportunities are now emerging for Java application developers in the wireless device space. The second round of the CLDC and MIDP standardization efforts was started in the fall of 2001. The goal of the CLDC 1.1 and MIDP 2.0 efforts was to expand on the success of the original standards, refine the existing feature set, and introduce additional APIs, while keeping a close eye on the strict memory limitations
xxi
xxii
PREFACE
that still constrain the design of wireless devices. More than 60 companies were directly involved in the development of the CLDC 1.1 and MIDP 2.0 specifications, reflecting the broad acceptance and adoption of these standards in the wireless industry. This book intends to make the results of the standardization work in the wireless Java technology area available to the wider software development community. At the high level, this book combines two Java Community Process Specifications, CLDC 1.1 (JSR 139) and MIDP 2.0 (JSR 118), and presents them as a single monograph in a way that the corresponding Java Community Process (JCP) Specifications cannot accomplish by themselves. We have added a general introduction to the Java 2 Platform, Micro Edition (J2ME™), provided more background material, and included a number of small applications to illustrate the use of CLDC and MIDP in the real world. We also provide some guidelines and instructions for getting started with Java 2 Platform, Micro Edition. A reference implementation of the software discussed in this book is available from Sun Microsystems under the Sun Community Source License (SCSL).
Intended Audience The book is intended for software developers, content providers, and other professionals who want to develop Java™ software for resource-constrained, connected devices. The book is also targeted to consumer device manufacturers who want to build small Java Powered™ devices and would like to integrate a compact Java application development platform in their products.
Objectives of This Book This book is the definitive statement, “from the source,” about the key specifications for Java Powered™ wireless devices. As such, this book intends to • provide an overview of Java™ 2 Platform, Micro Edition (J2ME™), • provide a general introduction to the application development platforms defined by the J2ME standardization efforts, • explain the technical aspects of the J2ME Connected, Limited Device Configuration version 1.1 (CLDC 1.1),
PREFACE
• explain the technical aspects of the J2ME Mobile Information Device Profile version 2.0 (MIDP 2.0), • provide sample programs to illustrate the use of CLDC and MIDP, and • help you get started in writing your own J2ME applications.
How This Book Is Organized The topics in this book are organized as follows: • Chapter 1, “Introduction,” provides a context for Java 2 Micro Edition and the CLDC and MIDP specifications. • Chapter 2, “Overview of Java 2 Platform, Micro Edition (J2ME™),” provides an overview of Java 2 Micro Edition, its key concepts and components. • Chapter 3, “Goals, Requirements, and Scope,” defines the goals, requirements, and scope of the CLDC and MIDP standardization efforts. • Chapter 4, “Connected Limited Device Configuration,” introduces the CLDC standardization effort and summarizes the supported Java programming language and virtual machine features compared to the Java 2 Platform, Standard Edition. • Chapter 5, “CLDC Libraries,” introduces the Java class libraries defined by the CLDC Specification. • Chapter 6, “Mobile Information Device Profile,” introduces the MIDP standardization effort. • Chapter 7, “MIDP Application Model,” introduces the MIDlet application model defined by the MIDP Specification. • Chapter 8, “MIDP User Interface Libraries,” introduces the user interface libraries defined by the MIDP Specification. • Chapter 9, “MIDP High-Level User Interface – Screen,” introduces the part of the MIDP high-level user interface revolving around the Screen class. • Chapter 10, “MIDP High-Level User Interface – Form,” introduces the part of the MIDP high-level user interface revolving around the Form class.
xxiii
xxiv
PREFACE
• Chapter 11, “MIDP Low-Level User Interface Libraries,” introduces the low-level user interface libraries defined by the MIDP Specification. • Chapter 12, “MIDP Game API,” introduces the game API defined by the MIDP Specification. • Chapter 13, “MIDP Sound API,” introduces the sound API defined by the MIDP Specification. • Chapter 14, “MIDP Persistence Libraries,” introduces the record management system (RMS) defined by the MIDP Specification. • Chapter 15, “MIDP Networking and Serial Communications,” introduces the libraries for networking and serial communications defined by the MIDP Specification. • Chapter 16, “Secure Networking,” introduces the protocols for secure networking defined by the MIDP Specification. • Chapter 17, “Event-Driven Application Launch,” introduces the protocols for launching MIDlets defined by the MIDP Specification. • Chapter 18, “Security for MIDlet Suites,” introduces the security protocols for MIDlet suites defined by the MIDP Specification. • Chapter 19, “MIDlet Deployment,” introduces the mechanisms for transferring a MIDlet to a wireless device. • Chapter 20, “Additional MIDP APIs,” introduces some additional MIDP application programming interfaces (APIs), such as Timers. • Chapter 21, “Summary,” summarizes the messages of this book. • “References” provides bibliographic references. • Appendix A, “CLDC Application Programming Interface,” contains the application programming interface documentation in Almanac format for CLDC. • Appendix B, “MIDP Application Programming Interface,” contains the application programming interface documentation in Almanac format for MIDP.
PREFACE
Related Literature and Helpful Web Pages The JavaÔ Language Specification, Second Edition, by James Gosling, Bill Joy, Guy Steele and Gilad Bracha. Addison-Wesley, 2000, ISBN 0-201-31008-2 The JavaÔ Virtual Machine Specification, Second Edition, by Tim Lindholm and Frank Yellin. Addison-Wesley, 1999, ISBN 0-201-43294-3 Programming Wireless Devices with the Java 2 Platform, Micro Edition, First Edition, by Roger Riggs, Antero Taivalsaari, and Mark VandenBrink. Addison-Wesley, 2001, ISBN 0-201-74627-1 MIDP 2.0 Style Guide by Cynthia Bloch and Annette Wagner. AddisonWesley, 2003, ISBN 0-321-19801-8 Connected, Limited Device Configuration Specification, version 1.0 http://jcp.org/en/jsr/detail?id=30
Connected, Limited Device Configuration Specification, version 1.1 http://jcp.org/en/jsr/detail?id=139
Mobile Information Device Profile Specification, version 1.0 http://jcp.org/en/jsr/detail?id=37
Mobile Information Device Profile Specification, version 2.0 http://jcp.org/en/jsr/detail?id=118
Java 2 Micro Edition Product Web Page http://java.sun.com/products/j2me/
Connected, Limited Device Configuration (CLDC) Product Web Page http://java.sun.com/products/cldc/
Mobile Information Device Profile (MIDP) Product Web Page http://java.sun.com/products/midp/
J2ME Wireless Toolkit Product Web Page http://java.sun.com/products/j2mewtoolkit/
Web Pages for This Book Addison-Wesley Page www.awprofessional.com/titles/0321197984
Sun Microsystems Page http://java.sun.com/docs/books/j2mewireless-2ndEd/index.html
xxv
This page intentionally left blank
Acknowledgments
L
ike most books, this book represents the work of many people. In this case, however, an unusually large number of people around the world have worked to make the Java 2 Platform, Micro Edition—and also this book—a reality. In five short years, a humble, two-person research project at Sun Labs grew rapidly into a highly collaborative product development and standardization effort involving hundreds of companies and thousands of people all over the world. The summary that follows is an attempt to give a glimpse into the different groups of people who participated in this journey. To these and many others too numerous to mention, we give our thanks and appreciation for what they did to make these ideas and this book possible. Attempting to name these people in no way diminishes the contributions of those who we also meant to name but in the pressure of time and the failure of memory somehow overlooked. Many people read draft versions of this book and sent us comments that improved the book substantially. The authors would like to thank all the reviewers for their willingness to send comments and constructive criticism on the various versions of the book and the sample applications. The authors would also like to thank Lisa Friendly for allowing us to publish this book in Sun’s Java book series and for lending us capable technical writing resources to finish this book. Jim Holliday, our technical writer and editor at Sun Microsystems, edited various versions of this book tirelessly. Without his expertise in the mysteries of desktop publishing, grammar, and that pesky topic known as punctuation, this work would have been much worse for the wear. Three other people at Sun Microsystems deserve special mention: Cindy Bloch, Senior Technical Writer, who contributed greatly in editing several chapters; Tasneem Sayeed, Staff Engineer, who provided very detailed comments on the various versions of the book; and Tim Dunn, Visual Designer, who devoted many long hours to perfecting the graphics in this book. Numerous companies have been involved in the standardization efforts related to the Java 2 Platform, Micro Edition. We would like to thank all the CLDC and MIDP expert group members for their active participation and valuable contribu-
xxvii
xxviii
ACKNOWLEDGMENTS
tions. In addition to the official members of the CLDC and MIDP expert groups, hundreds of other companies and individuals sent us feedback while the CLDC and MIDP standardization efforts were in progress. The authors found it amazing how much of their time people were willing to contribute to ensure the progress of the Java technology in the wireless space. Someone once said that hardware without software is a space heater. Similarly, without products, the CLDC and MIDP specifications would be limited in their value. The authors would like to thank wireless device manufacturers, wireless network operators, and software developers for widely embracing the CLDC and MIDP standards, thereby allowing software developers all over the world to finally have a common platform for mobile software development. Various product groups in Sun’s Consumer and Mobile Systems Group (CMSG) organization participated in the design and implementation of the CLDC and MIDP reference implementations. The authors would like to thank Sun’s CLDC team, MIDP team, and Wireless Toolkit team members who worked on the reference implementations of the standards and products discussed in this book. The TCK (Technology Compatibility Kit) and Quality Assurance teams at CMSG also played a critical role in ensuring the quality and compatibility of the products. The Nokia authors would like to thank the following Nokia people who have been closely involved in the MIDP 2.0 standardization work: Kari Systä, Kimmo Löytänä, Markku Tamski, Anna Zhuang, and Antti Rantalahti. Special thanks go to all the Nokia Java teams who have made it possible for Nokia to launch over 30 products with J2ME support and to ship tens of millions of J2ME devices. The Motorola authors would like to thank all the people in Motorola who helped make CLDC and MIDP a success. Special thanks go to the team members in Motorola’s WSAS and iDEN groups that had the vision, developed the first CLDC/MIDP device to reach the market, and still continue to push the envelope in terms of performance and capabilities. The preparation of this book has been a rather challenging endeavor. The authors are located in different cities and time zones, and because of the extensive amount of travel involved in standardization and product development work these days, a significant portion of the text in this book was written in airplanes, airports, and hotels. Luckily, the advances in wireless technology have made it easier for people to stay in touch regardless of their physical location. Unfortunately, it also means that it is increasingly difficult to avoid those after-8-p.m. phone calls and urgent text messages and e-mails, especially from your co-authors and colleagues located in Western time zones. The standards discussed in this book, for better or worse, will probably only accelerate this trend.
ACKNOWLEDGMENTS
All the authors would like to thank their family and friends who have had the patience and understanding to endure the long hours the authors have spent away from home writing this book, as well as developing these standards and related technologies and products. Without their support and understanding, none of this would have been possible. Jyri Huopaniemi, Helsinki, Finland Mark Patel, Chicago, Illinois, USA Roger Riggs, Burlington, Massachusetts, USA Antero Taivalsaari, Tampere, Finland Aleksi Uotila, Tampere, Finland Jim Van Peursem, Chicago, Illinois, USA April 2003
xxix
This page intentionally left blank
C H A P T E R
1
Introduction 1.1
The Wireless Internet Revolution
The wireless communications industry has seen rapid growth in the past several years. This has made wireless communication one of the fastest growing technology areas in the world. The total number of cellular phone subscribers worldwide exceeded one billion in 2002, and it has been estimated that there will be over 1.5 billion wireless subscribers in the world by 2005. This far exceeds the number of personal computer users in the world, which was estimated to be about 500 million in 2002. The total annual sales of cell phones in the world is expected to grow from about 423 million phones sold in 2002 to nearly 600 million phones sold in 2006. At the same time, the rapid emergence of the Internet has changed the landscape of modern computing. People have become more and more dependent on the information that is available on the Internet, and they will increasingly want to access the Internet not only from their personal computers and office workstations but also from mobile, wireless devices. Consequently, the rapid and efficient deployment of new wireless data and mobile Internet services has become a high priority for communication equipment manufacturers and telecommunication operators. The transition to wireless, mobile Internet devices will fundamentally alter the landscape and architecture of communication networks, devices, and services. Unlike in the past, when wireless devices typically came from the factory with a hard-coded feature set, the devices will become more and more customizable. The possibility to download new applications and features over wireless networks will open up completely new possibilities for device manufacturers, network operators, service and content providers, and device users themselves. The wireless Internet revolution will be facilitated by another important technological advance: the introduction of broadband third- and fourth-generation 1
2
CHAPTER 1
INTRODUCTION
wireless networks. While current wireless networks have limited data rates, allowing the users to transfer only up to a few tens of kilobits of data per second, broadband wireless networks will provide data rates ranging from hundreds of kilobits up to several megabits per second. This will provide enough bandwidth to transfer photographs, live video, and high-quality audio, as well as to download significantly larger applications and services than today. All these changes will happen relatively fast. Even though it will still take a few years before broadband wireless networks are in widespread use, it is safe to estimate that the majority of new wireless devices will have high-speed connectivity to the Internet by the end of the decade.
1.2
Why Java™ Technology for Wireless Devices?
The wireless Internet revolution will transform wireless devices from voice-oriented communication devices with relatively static, hard-coded functionality into extensible, Internet-enabled devices with advanced data and software capabilities. These devices will need to support dynamic downloading of new software and be capable of running software written not only by the device manufacturers themselves but also by third-party software developers. This will make the devices much more dependent on software and will place a much higher emphasis on software interoperability, security, and reliability. The Java™ programming language is ideally suited to become the standard application development language for wireless devices. After all, the Java platform provides a number of important benefits: • Dynamic delivery of content. New applications, services, and content can be downloaded dynamically over different kinds of networks. • Security. Class file verification, well-defined application programming interfaces, and security features ensure that third-party applications behave reliably and cannot harm the devices or the networks. • Cross-platform compatibility. Standardized language features and libraries mean that applications and content can be transferred flexibly between different devices, within constraints of the supported J2ME™ configuration and profiles (see Section 2.3, “Key Concepts of the J2ME Architecture,” for details). • Enhanced user experience and interactive content. The standards defined for wireless Java technology support sophisticated user interaction and provide compelling graphics capabilities for small devices.
A BIT OF HISTORY
• Offline access. Applications can also be used without active network connection. This reduces transport costs and alleviates the impact of possible network failures. • The power of a modern object-oriented programming language. The Java programming language has far better abstraction mechanisms and higher-level programming constructs than other languages and tools that are currently used for wireless software development, allowing applications to be developed more efficiently. • Large developer community. It is estimated that there are more than three million Java software developers worldwide. The Java programming language is rapidly becoming the most popular programming language taught in schools and universities. The developer talent needed for Java software development already exists and is readily available. Ultimately, Java technology will deliver far more compelling, entertaining, and engaging capabilities to wireless devices. What is particularly important is that this can be accomplished incrementally, by complementing existing technologies and standards, rather than by competing with them. One of the key points we emphasize throughout this book is that we are not defining a new operating system or a complete system software stack for wireless devices. Rather, the goal of this work is to define and standardize a portable wireless application development environment that targets primarily third-party application developers and will open the devices for third-party software development. This environment can be added flexibly on top of the existing software and hardware solutions that the device manufacturers already have. Typically, the changes required to the existing system software are very small. For more information, see Section 3.1, “High-Level Goals.”
1.3
A Bit of History
The Java programming language was initially targeted towards consumer devices, especially the interactive TV market. However, over time the Java platform evolved more and more towards the needs of desktop and enterprise computing. Enterprise applications generally require rich library functionality, and over time the Java libraries grew larger and more comprehensive to cater better to the needs of the enterprise market and large server-side applications. However, this evolution made the libraries too large and unsuitable for the majority of small, resource-constrained devices.
3
4
CHAPTER 1
INTRODUCTION
In January 1998, the Spotless project was started at Sun Microsystems Laboratories (Sun Labs) to investigate the use of the Java programming language in extremely resource-constrained devices. The research goal of the project was to build a Java runtime environment that would fit in less than one-tenth of the typical size. At the implementation level, the goal was to build a Java virtual machine with the following characteristics: • small size • portability • ease of use and readability of the source code Small size is important, since the majority of wireless, mobile devices (for example, cell phones) are still very resource-limited and often have only a few tens or hundreds of kilobytes of memory available for applications. Portability, ease of use, and the readability of the source code are equally important. Most embedded device manufacturers need to support dozens or even hundreds of different hardware configurations that run on several different hardware platforms, and it would be not only tedious but also very expensive to spend a lot of time porting and customizing the Java platform implementation to all those hardware configurations and platforms. Also, embedded device manufacturers cannot generally be expected to be experts on the Java programming language or virtual machine. Therefore, the easier the implementation is to understand and use, the faster the device manufacturers will deploy it across their devices. Even though the Spotless effort was initially a research project, the project group established active contacts with external customers early on. External customers, especially Motorola, played a significant role in convincing Sun to turn the Spotless system from a research project into a commercial product. The product version of the Spotless virtual machine is known today as the K Virtual Machine (KVM). The Spotless system is documented in the Sun Labs technical report The Spotless System: Implementing a Java System for the Palm Connected Organizer (Sun Labs Technical Report SMLI TR-99-73).
1.4
J2ME™ Standardization Efforts
Once Motorola, Nokia, NTT DoCoMo, Palm Computing, RIM, Siemens, and other device manufacturers became interested in the KVM development effort, standardization was necessary in order to guarantee interoperability between the different
J2ME™ STANDARDIZATION EFFORTS
kinds of Java Powered™ devices from different manufacturers. Two Java Community Process (JCP) standardization efforts were launched in the fall of 1999. The first of these standardization efforts, Connected, Limited Device Configuration (CLDC), was launched on October 1, 1999. The goal of this effort was to define the “lowest common denominator” Java platform for a wide variety of small, connected, resource-constrained devices. This specification defines the minimum required complement of Java technology components and libraries for small devices. Java programming language and virtual machine features, core libraries, input/output, networking, and security are the primary topics addressed by the CLDC Specification. The CLDC standard does not target any specific device category. Rather, it defines a general-purpose building block on top of which more device category specific profiles are defined. Eighteen companies participated in the CLDC 1.0 (JSR 30) expert group work. The second standardization effort, Mobile Information Device Profile (MIDP), was started in November 1999. That effort was based on the platform defined by the CLDC effort, adding features and APIs that focus specifically on two-way wireless communication devices such as cell phones and two-way pagers. Application model, user interface, networking, and storage APIs are the primary focus areas of the MIDP Specification. Twenty-two companies participated in the MIDP 1.0 (JSR 37) expert group work. After becoming widely accepted in the marketplace, second-generation CLDC and MIDP standardization efforts were launched in the fall of 2001. The CLDC 1.1 (JSR 139) effort was started in September 2001. CLDC 1.1 adds a number of features that improve the compatibility of the J2ME platform with the full Java 2 Platform, Standard Edition (J2SE™). The most significant new feature added in CLDC 1.1 is floating point support, but there are a number of other important features as well. The CLDC standardization effort is described in more detail in Chapter 4, “Connected Limited Device Configuration,” and Chapter 5, “CLDC Libraries.” The MIDP 2.0 (JSR 118) effort was started in August 2001. MIDP 2.0 adds a number of important new libraries such as a Sound API and a Game API, as well as provides important refinements and extensions to the existing MIDP APIs. The MIDP standardization effort is discussed in Chapter 6, “Mobile Information Device Profile” and subsequent chapters. The general framework for CLDC and MIDP, as well as other Java technology standardization efforts in the small device space, is known as Java™ 2 Platform, Micro Edition (J2ME) or simply Java 2 Micro Edition. An introduction to Java 2 Micro Edition is provided in the next chapter.
5
6
CHAPTER 1
INTRODUCTION
In addition to the CLDC and MIDP standardization efforts, there are a large number of additional J2ME standardization efforts that build upon these core standards. A summary of the J2ME optional packages created by the additional standardization efforts will be provided in Section 2.4, “Evolution of the J2ME Platform.”
C H A P T E R
2
Overview of Java 2 Platform, Micro Edition (J2ME™) 2.1
Java 2 Platform
Recognizing that one size does not fit all, Sun Microsystems has grouped Java technologies into three editions, each aimed at a specific area of today’s vast computing industry: • Java 2 Platform, Enterprise Edition (J2EE™) for enterprises needing to serve their customers, suppliers, and employees with scalable server solutions. • Java 2 Platform, Standard Edition (J2SE™) for the familiar and wellestablished desktop computer market. • Java 2 Platform, Micro Edition (J2ME™) for the combined needs of: ■
■
■
consumer and embedded device manufacturers who build a diversity of information devices, service providers who wish to deliver content to their customers over those devices, and content creators who want to make compelling content for small, resourceconstrained devices.
Each Java platform edition defines a set of technologies that can be used with a particular product: • Java Virtual Machines that fit inside a wide range of computing devices, • libraries and APIs specialized for each kind of computing device, and • tools for deployment and device configuration. 7
8
CHAPTER 2
OVERVIEW OF JAVA 2 PLATFORM, MICRO EDITION (J2ME™)
Figure 2.1 illustrates the Java 2 Platform editions and their target markets, starting from the high-end platforms on the left and moving towards low-end platforms on the right. Basically, five target markets or broad device categories are identified. Servers and enterprise computers are supported by Java 2 Enterprise Edition, and desktop and personal computers by Java 2 Standard Edition. Java 2 Micro Edition is divided broadly into two categories that focus on “high-end” and “low-end” consumer devices. Java 2 Micro Edition is discussed in more detail later in this chapter. Finally, the Java Card™ standard focuses on the smart card market.
Servers & Enterprise Computers
Desktop & Personal Computers
High-end Consumer Devices
Low-end Consumer Devices
Smart cards
Figure 2.1
Java 2 Platform editions and their target markets
JAVA 2 PLATFORM, MICRO EDITION (J2ME)
2.2
Java 2 Platform, Micro Edition (J2ME)
Java™ 2 Platform, Micro Edition (henceforth referred to as Java 2 Micro Edition or J2ME) specifically addresses the large, rapidly growing consumer space, which covers a range of devices from tiny commodities, such as pagers, all the way up to the TV set-top box, an appliance almost as powerful as a desktop computer. Like the larger Java editions, Java 2 Micro Edition aims to maintain the qualities that Java technology has become known for, including built-in consistency across products, portability of code, safe network delivery, and upward scalability. The high-level idea behind J2ME is to provide comprehensive application development platforms for creating dynamically extensible, networked devices and applications for the consumer and embedded market. J2ME enables device manufacturers, service providers, and content creators to capitalize on new market opportunities by developing and deploying compelling new applications and services to their customers worldwide. Furthermore, J2ME allows device manufacturers to open up their devices for widespread third-party application development and dynamically downloaded content without losing the security or the control of the underlying manufacturer-specific platform. At a high level, J2ME is targeted at two broad categories of products: • “High-end” consumer devices. In Figure 2.1, this category is represented by the grouping labeled CDC (Connected Device Configuration). Typical examples of devices in this category include TV set-top boxes, Internet TVs, Internet-enabled screenphones, high-end wireless communicators, and automobile entertainment/navigation systems. These devices have a large range of user interface capabilities, total memory budgets starting from about two to four megabytes, and persistent, high-bandwidth network connections, often using TCP/IP. • “Low-end” consumer devices. In Figure 2.1, this category is represented by the grouping labeled CLDC (Connected, Limited Device Configuration). Cell phones, pagers, and personal organizers are examples of devices in this category. These devices have simple user interfaces (compared to desktop computer systems), minimum memory budgets starting from about 128–256 kilobytes, and low bandwidth, intermittent network connections. In this category of products, network communication is often not based on the TCP/IP protocol suite. Most of these devices are battery-operated. The line between these two categories is fuzzy and becoming more so every day. As a result of the ongoing technological convergence in the computer, tele-
9
10
CHAPTER 2
OVERVIEW OF JAVA 2 PLATFORM, MICRO EDITION (J2ME™)
communication, consumer electronics, and entertainment industries, there will be less technical distinction between general-purpose computers, personal communication devices, consumer electronics devices, and entertainment devices. Also, future devices are more likely to use wireless connectivity instead of traditional fixed or wired networks. In practice, the line between the two categories is defined more by the memory budget, bandwidth considerations, battery power consumption, and physical screen size of the device rather than by its specific functionality or type of connectivity. Because of strict manufacturing cost constraints, the majority of high-volume wireless devices today, such as cell phones, belong to the low-end consumer device category. Therefore, this book focuses only on the CLDC and MIDP standards that were specifically designed for that category of products.
2.3
Key Concepts of the J2ME Architecture
While connected consumer devices such as cell phones, pagers, personal organizers, and TV set-top boxes have many things in common, they are also extremely diverse in form, function, and features. Information appliances tend to be special-purpose, limited-function devices. To address this diversity, an essential requirement for the J2ME architecture is not only small size but also modularity and customizability. In general, serving the information appliance market calls for a large measure of flexibility in how computing technology and applications are deployed. This flexibility is required because of • the large range of existing device types and hardware configurations, • the different usage models employed by the devices (key operated, stylus operated, voice operated), • constantly improving device technology, • the diverse range of existing applications and features, and • the need for applications and capabilities to change and grow, often in unforeseen ways, in order to accommodate the future needs of the consumer. The J2ME architecture is intended to be modular and scalable so that it can support the kinds of flexible deployment demanded by the consumer and embedded markets. To enable this, the J2ME environment provides a range of Java Virtual Machine technologies, each optimized for the different processor types and memory footprints commonly found in the consumer and embedded marketplace.
KEY CONCEPTS OF THE J2ME ARCHITECTURE
For low-end, resource-limited consumer products, the J2ME environment supports minimal configurations of the Java Virtual Machine and Java libraries that embody just the essential capabilities of each kind of device. As device manufacturers develop new features in their devices or service providers develop new and exciting applications, these minimal configurations can be expanded with additional libraries that address the needs of a particular market segment. To support this kind of customizability and extensibility, three essential concepts are defined by the J2ME architecture: • Configuration. A J2ME configuration defines a minimum platform for a “horizontal” category or grouping of devices, each with similar requirements on total memory budget and processing power. A configuration defines the Java language and virtual machine features and minimum class libraries that a device manufacturer or a content provider can expect to be available on all devices of the same category. • Profile. A J2ME profile is layered on top of (and thus extends) a configuration. A profile addresses the specific demands of a certain “vertical” market segment or device family. The main goal of a profile is to guarantee interoperability within a certain vertical device family or domain by defining a standard Java platform for that market. Profiles typically include class libraries that are far more domain-specific than the class libraries provided in a configuration. One device can support multiple profiles. • Optional package. Some APIs are applicable to a large number of devices and device families. A J2ME optional package is a set of APIs that is layered on top of (and thus extends) a profile. An optional package typically contains functionality that is independent of any particular vertical market segment or device family. The main goal of an optional package is to allow the definition of APIs that can be added flexibly on top of a number of different profiles. One device can support multiple optional packages. Configurations, profiles, and optional packages are discussed in more detail below. Configurations, profiles, and optional packages use the capabilities of the Java Virtual Machine (JVM), which is considered to be part of the configuration. The virtual machine usually runs on top of a host operating system that is part of the system software of the target device. The high-level relationship between the
11
12
CHAPTER 2
OVERVIEW OF JAVA 2 PLATFORM, MICRO EDITION (J2ME™)
different software layers—the JVM, configuration, profiles, optional packages, and the host operating system—is illustrated in Figure 2.2.
Figure 2.2
Software layers in a J2ME device
J2ME configurations, profiles, and optional packages are defined through industry collaboration using the Java Community Process (JCP). For further information on the Java Community Process, refer to the Java Community Process web site (http://jcp.org/). 2.3.1
Profiles
Application portability is a key benefit of Java technology in the desktop and enterprise server markets. Portability is an equally critical element in the consumer device space. However, application portability requirements in the consumer space are very different from portability requirements demanded by the desktop and server markets. In most cases, consumer devices differ substantially in memory size, networking, and user interface capabilities, making it very difficult to support all devices with just one solution. In general, the consumer device market is not so homogeneous that end users can expect or require universal application portability. Rather, in the consumer
KEY CONCEPTS OF THE J2ME ARCHITECTURE
space, applications should ideally be fully portable within the same device family. For example, consider the following types of consumer devices: • cellular telephones, • washing machines, and • electronic toys. It seems clear that each of these represents a different market segment, device family, or application domain. As such, consumers would expect useful applications to be portable within a device family. For example: • A discount broker’s stock trading application is generally expected to work on different cell phones, even though the phones are from different manufacturers. • It would be annoying if a highly useful grape-juice-stain-removing wash cycle application available on the Internet runs on an old brand-X washer but not a new brand-Z washer. • A child’s birthday party could be less enjoyable if the new toy robot does not “talk to” or “play games with” the new electronic teddy bear. On the other hand, consumers do not expect the stock trading application or an automobile service program to run on the washing machine or the toy robot. In other words, application portability across different device categories is not necessarily very important or even meaningful in the consumer device space. In addition, there are important economic reasons to keep these device families separate. Consumer devices compete heavily on cost and convenience, and these factors often translate directly into limitations on physical size and weight, processor power, memory size, and power consumption (in battery-powered devices). Consumers’ wallets will usually favor devices that have the right functionality at the right price. In other words, the devices must perform the desired functions well, but they do not have added cost for unnecessary features. Thus, the J2ME framework provides the concept of a profile to make it possible to define Java platforms for specific vertical markets. A profile defines a Java platform for a specific vertical market segment or device category. Profiles can serve two distinct portability requirements: • A profile provides a complete toolkit for implementing applications for a particular kind of device, such as a pager, set-top box, cell phone, washing machine, or interactive electronic toy.
13
14
CHAPTER 2
OVERVIEW OF JAVA 2 PLATFORM, MICRO EDITION (J2ME™)
• A profile may also be created to support a significant, coherent group of applications that might be hosted on several categories of devices. For example, while the differences between set-top boxes, pagers, cell phones, and washing machines are significant enough to justify creating a separate profile for each, it might be useful for certain kinds of personal information management or home banking applications to be portable to each of these devices. This could be accomplished by creating a separate profile for these kinds of applications and ensuring that this new profile can be easily and effectively supported on each of the target devices along with its “normal” more device-specific profile. It is possible for a single device to support several profiles. Some of these profiles are very device-specific, while others are more application-specific. Applications are written “for” a specific profile and are required to use only the features defined by that profile. Manufacturers choose which profile(s) to support on each of their devices, but are required to implement all features of the chosen profile(s). The value proposition to the consumer is that any application written for a particular profile will run on any device that supports that profile. In its simplest terms, a profile is a contract between an application and a vertical market segment. All the devices in the same market segment agree to implement all the features defined in the profile, and the application agrees to use only those features that are defined in the profile. Thus, portability is achieved between the applications and the devices served by that profile. New devices can take advantage of a large and familiar application base. Most importantly, new compelling applications (perhaps completely unforeseen by the original profile designers and device manufacturers) can be dynamically downloaded to existing devices. At the implementation level, a profile is defined simply as a collection of class libraries that reside on top of a specified configuration and that provide the additional domain-specific capabilities for devices in a specific market segment. In our example above, each of the three families of devices (cell phones, washing machines, and intercommunicating toys) could be addressed by a separate J2ME profile. The only one of these profiles in existence at the current time is the MIDP, designed for cell phones and other two-way communication devices. 2.3.2
Configurations
In the J2ME environment, an application is written “for” a particular profile, and a profile is “based upon” or “extends” a particular configuration. Thus, all of the features of a configuration are automatically included in the profile and may be used by applications written for that profile.
KEY CONCEPTS OF THE J2ME ARCHITECTURE
A configuration defines a Java platform for a “horizontal” category or grouping of devices with similar requirements on total memory budget and other hardware capabilities. More specifically, a configuration: • specifies the Java programming language features supported, • specifies the Java Virtual Machine features supported, and • specifies the basic Java libraries and APIs supported. The J2ME environment is designed so that it can be deployed in more than one configuration. Each configuration specifies the Java language and virtual machine features and a set of libraries that the profile implementer (and the applications using that profile) can safely assume to be present on all devices when shipped from the factory. Profile implementers must design their code to stay within the bounds of the features and libraries specified by that configuration. In its simplest terms, a configuration defines a “lowest common denominator” platform or building block for device manufacturers and profile implementers. All the devices with approximately the same amount of memory and processing power agree to implement all the features defined in the configuration, and the profile implementers agree to use only those features defined in the configuration. Thus, portability is achieved between the profile and the devices served by that configuration. In our example above, each of the three profiles (for cell phones, washing machines, and electronic toys) would most likely be built upon the same configuration, the CLDC. This configuration provides all the basic functionality to serve the needs of each of these, and perhaps many more, profiles. To avoid fragmentation, there are a very limited number of J2ME configurations. As depicted in Figure 2.1, only two standard J2ME configurations are available: • Connected, Limited Device Configuration (CLDC). This configuration focuses on low-end consumer devices. Typical examples of CLDC target devices include personal, mobile, battery-operated, connected information devices such as cell phones, two-way pagers, and personal organizers. This configuration includes some new libraries, not drawn from the J2SE APIs, designed specifically to fit the needs of small-footprint devices. • Connected Device Configuration (CDC). This configuration focuses on highend consumer devices. Typical examples of CDC target devices include shared, connected information devices such as TV set-top boxes, Internet TVs,
15
16
CHAPTER 2
OVERVIEW OF JAVA 2 PLATFORM, MICRO EDITION (J2ME™)
and high-end communicators. This configuration includes a much more comprehensive set of Java libraries and virtual machine features than CLDC. Figure 2.3 illustrates the relationship between CLDC, CDC, and Java 2 Standard Edition (J2SE). As shown in the figure, the majority of functionality in CLDC and CDC has been inherited from Java 2 Platform, Standard Edition (J2SE). Each class inherited from the J2SE environment must be precisely the same or a subset of the corresponding class in the J2SE environment. In addition, CLDC and CDC may introduce a number of features, not drawn from the J2SE, designed specifically to fit the needs of small-footprint devices.
Figure 2.3
Relationship between J2ME configurations and Java 2 Standard Edition
The most important reason for the configuration layer in the J2ME environment is that core Java libraries needed across a wide variety of Java platform implementations are usually intimately tied with the implementation of a Java Virtual Machine. Small differences in the specification of a configuration can require a number of significant modifications to the internal design of a Java Virtual Machine and can require a substantial amount of additional memory footprint. Such modifications would be very expensive and time-consuming to maintain. Having a small number of configurations means that a small number of virtual machine implementations can serve the needs of both a large number of profiles
EVOLUTION OF THE J2ME PLATFORM
and a large number of different device hardware types. This economy of scale provided by the J2ME environment is very important to the success and cost-effectiveness of devices in the consumer and embedded industry. 2.3.3
Optional Packages
Soon after the introduction of the original CLDC and MIDP standards, it was realized that, in addition to configurations and profiles, there is a need for additional, general-purpose libraries that are not bound to a single device category or family. For instance, a location API that provides facilities for geographic positioning is potentially applicable to a broad number of devices and device families, and is not functionally limited only to a single profile. Similarly, a wireless messaging API could potentially be applied to a number of different types of devices and profiles. To address the need to create such broadly applicable, device family independent APIs, the concept of optional packages was added to the architecture of the J2ME platform. Generally speaking, a J2ME optional package is an API that can be used to extend a profile. An optional package exposes specific functionality independent of any profile and is naturally distinct from any profile. Optional packages provide APIs that are intended for reuse by profile design teams and vendors of J2ME environments. It is expected that optional packages may sometimes play an important role in the evolution of a profile. As APIs are developed for new technologies and features, the new APIs are initially developed as optional packages. However, as those APIs mature and new versions are created through the Java Community Process, optional packages may later be incorporated into a profile. A summary of J2ME optional packages created so far for the wireless market is provided in the next section.
2.4
Evolution of the J2ME Platform
After the successful completion of the CLDC and MIDP standardization efforts, a number of additional J2ME standardization efforts have been launched to complement the functionality provided by the core standards. Most of these additional efforts define optional packages that can be deployed on top of MIDP. These efforts are summarized in Section 2.4.2, “Optional Packages for the Wireless Market” below. In addition, there are a number of more fundamental, core standardization efforts that are summarized in Section 2.4.1, “Core J2ME Standardization Efforts.”
17
18
CHAPTER 2
2.4.1
OVERVIEW OF JAVA 2 PLATFORM, MICRO EDITION (J2ME™)
Core J2ME Standardization Efforts
There are a number of standardization activities that have an important role in defining the overall J2ME architecture. These efforts can be viewed as “umbrella” activities that specify the ground rules for a number of standardization activities or provide additional instructions, recommendations, and clarifications for binding together the existing J2ME standards: • JSR 68: J2ME™ Platform Specification • JSR 185: Java™ Technology for Wireless Industry JSR 68: J2ME™ Platform Specification This specification defines the “ground rules” for the J2ME platform architecture and J2ME standardization activities. It formalizes the fundamental concepts behind J2ME, such as the notions of a configuration and profile, and defines how new J2ME APIs can be formed by subsetting existing APIs from the Java 2 Platform, Standard Edition (J2SE). JSR 185: Java™ Technology for the Wireless Industry (JTWI) This specification defines how various technologies associated with MIDP work together to form a complete handset solution for the wireless services industry. The specification provides an exposition of the overall architecture of the wireless client software stack, including a description of the following aspects: • Which optional packages fit with which profiles? • How does an end-to-end solution for interoperable Java applications work? • How does the migration of applications occur, and to which profiles, as the devices become more capable? A key goal of the JTWI Specification is to minimize the fragmentation of the Java APIs in the mobile handset market by creating a community that coordinates the API evolution and deployment as the industry continues to expand the capabilities of mobile devices. To accomplish this, the JSR 185 expert group coordinates the creation of new J2ME-related JSRs and provides recommendations for new optional packages that could take place within the context of the wireless development community as a whole.
EVOLUTION OF THE J2ME PLATFORM
2.4.2
Optional Packages for the Wireless Market
The following standardization efforts define optional packages that can reside on top of MIDP: • JSR 120: Wireless Messaging API • JSR 135: Mobile Media API • JSR 172: J2ME™ Web Services Specification • JSR 177: Security and Trust Services for J2ME™ • JSR 179: Location API for J2ME™ • JSR 180: Session Initiation Protocol (SIP) for J2ME™ • JSR 184: Mobile 3D Graphics for J2ME™ • JSR 190: Event Tracking API for J2ME™ Each of these efforts is summarized briefly below. JSR 120: Wireless Messaging API This JSR defines a set of optional APIs that provide standardized access to wireless communication resources, allowing third-party developers to build intelligent connected Java applications. The specification addresses the following wireless technologies: • Short Message Service (SMS), and • Cell Broadcast Service (CBS). JSR 135: Mobile Media API (MMAPI) This JSR specifies a multimedia API for J2ME, providing straightforward access and control of basic audio and multimedia resources and files. The MIDP 2.0 Sound API (introduced in Chapter 13 of this book) is a subset of the Mobile Media API defined by JSR 135. JSR 172: J2ME™ Web Services Specification This specification defines an optional package that provides standard access from J2ME devices to Web services. The JSR is designed to provide an infrastructure to
19
20
CHAPTER 2
OVERVIEW OF JAVA 2 PLATFORM, MICRO EDITION (J2ME™)
• provide basic XML processing capabilities, • enable reuse of Web service concepts when designing J2ME clients to enterprise services, • provide APIs and conventions for programming J2ME clients of enterprise services, • adhere to Web service standards and conventions around which the Web services and Java developer community is consolidating, • enable interoperability of J2ME clients with Web services, and • provide a programming model for J2ME client communication with Web services, consistent with that for other Java clients such as J2SE. JSR 177: Security and Trust Services API for J2ME™ The purpose of this JSR is to define a collection of APIs that provide security services to J2ME devices. These APIs are a necessary step for a device to become trusted, that is, to provide security mechanisms to support a wide variety of application-based services, such as access to corporate network, mobile commerce, and digital rights management. Many of these services rely on the interaction with a “security element” (such as a smart card) in the device for secure storage and execution, as described below: • Secure storage to protect sensitive data, such as the user’s private keys, public key (root) certificates, service credentials, personal information, and so on. • Secure execution, such as cryptographic operations to support payment protocols, data integrity, and data confidentiality. • Custom and enabling security features that J2ME applications can rely on to handle many valued-added services, such as user identification and authentication, banking, payment, ticketing, loyalty applications, and digital media playing. The JSR 177 specification defines an access model and a set of APIs that enable applications running on a J2ME device to communicate with a smart card inserted in the device, providing a flexible mechanism to allow service and equipment providers to define secure operations.
EVOLUTION OF THE J2ME PLATFORM
JSR 179: Location API for J2ME™ This specification defines an optional package that enables developers to write mobile, location-based applications for J2ME devices. The purpose of the specification is to provide a compact and generic API that produces information about the device’s present physical location to Java applications. This specification defines a generic interface that works with most positioning methods, such as GPS and E-OTD. JSR 180: Session Initiation Protocol (SIP) for J2ME™ The Session Initiation Protocol (SIP) is used to establish and manage multimedia IP sessions. This same mechanism can also be used to provide instant messaging, presence, and gaming services. This specification defines a general SIP API for J2ME devices based on the SIP protocol defined by IETF and 3GPP, and targeting resource constrained platforms. JSR 184: Mobile 3D Graphics API for J2ME™ This specification defines a lightweight, interactive 3D graphics API, which sits alongside J2ME and MIDP as an optional package. The API is targeted at devices that typically have very little processing power and memory, and no hardware support for 3D graphics or floating point math. However, the API also scales up to higher-end devices that have a color display, a DSP, a floating point unit, or even specialized 3D graphics hardware. The API is designed to make rapid development of compelling 3D applications feasible and is intended to be flexible enough for a wide range of applications, including games, animated messages, screen savers, custom user interfaces, product visualization, and so on. JSR 190: Event Tracking API for J2ME™ This specification defines an optional package that standardizes the tracking of application events in a mobile device and the submission of these event records to an event-tracking server via a standard protocol. The events can be used for purposes such as billing, usage tracking, application revocation, update notification, reviews and ratings, and so on. The Event Tracking API is intended to work with devices supporting CLDC 1.0 and later. The API is designed as an optional package that can be used with many J2ME profiles, in particular MIDP 1.0 and MIDP 2.0. For More Information For additional information on each effort mentioned above, refer to corresponding pages on the Java Community Process web site (http://jcp.org).
21
This page intentionally left blank
C H A P T E R
3
Goals, Requirements, and Scope The CLDC and MIDP standards intend to bring the benefits of Java technology to resource-constrained wireless devices with limited Internet connectivity. This chapter reviews the goals, requirements, and scope of these standards.
3.1
High-Level Goals
The general goal of the J2ME standardization efforts discussed in this book is to define a highly portable, secure, small-footprint application development environment for resource-constrained, connected devices. We emphasize the term application development environment. The CLDC and MIDP standards are not intended to replace existing system software stacks or to serve as a complete operating system for small devices. Rather, the goal of these efforts is to define an environment that can be added flexibly on top of an existing system software stack to support third-party application development and secure, dynamic downloading of applications. The CLDC and MIDP standardization efforts have slightly different but complementary goals. Connected, Limited Device Configuration is intended to serve as a generic, “lowest common denominator” platform that targets all kinds of small, connected devices—independent of any specific device category. Mobile Information Device Profile builds on top of CLDC and focuses on a specific category of devices: wireless, mobile, two-way communication devices such as cellular telephones and two-way pagers.
23
24
CHAPTER 3
3.1.1
GOALS, REQUIREMENTS, AND SCOPE
Dynamic Delivery of Java Applications and Content
One of the greatest benefits of Java technology in the small device space is the dynamic, secure delivery of interactive services and applications over different kinds of networks. Unlike in the past, when small devices such as cell phones and pagers came from the manufacturer with a hard-coded feature set, device manufacturers are increasingly looking for solutions that allow them to build extensible, customizable devices that support rich, dynamic, interactive content from third-party content providers and developers. With the recent introduction of Internet-enabled cell phones, communicators, and pagers, this transition is already under way. Several wireless device manufacturers are already offering cell phones that allow users to download new applications such as interactive games, screen savers, banking and ticketing applications, wireless collaboration tools, and so on (Figure 3.1). Note that such customizability is not necessarily limited to communication devices such as cell phones or two-way pagers. For instance, it is quite possible to envision automobile engines that obtain new service programs and updates as they become available, washing machines that download new washing programs dynamically, electronic toys that automatically download updated game programs, and so on. The range of possible applications is virtually endless. One of the main goals of both the Connected, Limited Device Configuration and Mobile Information Device Profile is to take this transition several steps further by allowing the use of the Java programming language as the standard platform for the secure delivery of dynamic content for these extensible nextgeneration devices. 3.1.2
Third-Party Application Development
The focus on dynamically delivered applications means that CLDC and MIDP are intended not only for hardware manufacturers and their system programmers but also for third-party application developers. In fact, we assume that once Java Powered™ small devices become commonplace, the vast majority of application developers for these devices will be third-party developers rather than device manufacturers. This focus on third-party application development has some important implications for the features and libraries included in the CLDC and MIDP standards. First, the CLDC and MIDP specifications include only high-level libraries that provide sufficient programming power for the third-party application developer. For instance, the networking APIs included in MIDP provide the programmer with meaningful high-level abstractions, such as the ability to transfer entire files or web pages at once, rather than require the programmer to know about the details of specific network transmission protocols. Second, we emphasize the
HIGH-LEVEL GOALS
Figure 3.1
Downloading customized services
importance of generality, portability, and interoperability. The CLDC and MIDP specifications are intended to support a wide range of devices and do not focus on any specific single type or brand of devices. 3.1.3
Independence of Network Technology Standards
The wireless communications industry has never suffered from the lack of technology standards. There is a plethora of wireless technologies in use all over the world, with varying levels of sophistication, compatibility, and interoperability. The second-generation (2G) digital wireless network technologies include standards such as GSM, TDMA, CDMA, and PDC. Third-generation (3G) wireless network technology standards include WCDMA, CDMA2000, and TD-SCDMA. In addition, there are several second-and-a-half-generation (2.5G) standards such as GPRS, CDPD, and EDGE. One of the key goals for J2ME standardization efforts is to define solutions that can work effectively with all these network technologies and standards. Any APIs or features that would focus only on one specific type of network technology are generally avoided. An additional goal in the CLDC and MIDP standardization work was to ensure that the solutions can be used both in today’s relatively lowspeed wireless networks and in tomorrow’s high-speed broadband wireless networks.
25
26
CHAPTER 3
GOALS, REQUIREMENTS, AND SCOPE
To reach the goals just mentioned, the CLDC standard defines a special Generic Connection framework for supporting networking in a coherent, extensible fashion. This is discussed in detail in Section 5.3.2, “The Generic Connection Framework.” The MIDP standard utilizes the Generic Connection framework and defines a number of concrete network protocols that are guaranteed to be available in all devices supporting MIDP. 3.1.4
Compatibility with Other Wireless Application Standards
A key goal for the standards defined in this book is to provide interoperability with existing and forthcoming wireless application development standards and technology stacks such as Open Mobile Architecture1 (OMA) and i-Mode. This means that the application development environments defined by CLDC and MIDP can complement existing technologies rather than compete with them. For instance, today’s wireless devices already commonly provide a simple microbrowser for finding services on the Internet. This microbrowser can be extended to locate and launch Java applications as well. A microbrowser augmented with Java application execution capabilities will provide better user interaction and graphics capabilities, support offline use of applications, and make the development of compelling applications generally much easier.
3.2
Target Devices
Potential target devices for the Mobile Information Device Profile (MIDP) include two-way communication devices such as cellular telephones, two-way pagers, and wireless personal organizers. The Connected, Limited Device Configuration (CLDC) can additionally be used to support other kinds of devices such as point-ofsale terminals, barcode scanners, inventory control devices, audio/video equipment, home appliances, and device controllers (for routers, sensors, vending machines, engines, and so forth). In general, CLDC is intended to be applicable to any resource-constrained device that might benefit from a portable, low-cost application development environment that supports secure, dynamic downloading of third-party applications.2 The characteristics of the CLDC and MIDP target devices are summarized in Figure 3.2. The technical hardware and software requirements of CLDC and MIDP target devices are defined in detail later in this chapter. 1. 2.
Defined by Open Mobile Alliance (http://www.openmobilealliance.org/). Note that CLDC defines only general-purpose APIs, so additional APIs and/or J2ME profiles are typically necessary to address the specific needs of each device category.
TARGET DEVICES
Figure 3.2
CLDC and MIDP target devices
The user interaction models of CLDC and MIDP target devices vary significantly. Consider, for example, how a user interacts with today’s crop of mobile information devices. The most common example is that of “one-handed” operation. Devices of this type are typical cellular phones with small LCD displays and a standard ITU-T telephone keypad (containing at least the keys 09, *, and #). Users interact with this type of device with one hand, usually with their thumb only. With devices of this type, smaller is better, so these devices typically have a very limited display. Other mobile information devices are operated in “two-handed mode.” These devices have a small, conventional “QWERTY” keyboard. Data entry for these devices is much like using a PC, although due to the small size, touch typing can be problematic; consequently, many devices in this category are operated by two thumbs rather than ten fingers. Given that a QWERTY keyboard takes up more space than a telephone keypad, the display in these devices is usually larger than that found in a normal cellular phone. As a final example of user interaction models, consider a device that depends on a touch screen. These devices primarily interact with the user by having a simple, consistent, and well-designed menu system. In addition, these devices might depend on handwriting recognition or a virtual keyboard for user-input text. Given
27
28
CHAPTER 3
GOALS, REQUIREMENTS, AND SCOPE
that text input is commonly done via a stylus, these devices typically have larger LCD screens—in fact, often much larger than the other two types of devices discussed. Both CLDC and MIDP are designed to cater to all the different usage models presented in Figure 3.3, and consequently the CLDC and MIDP specifications make minimal assumptions about user interaction models of the target devices.
Figure 3.3
3.3
One-handed, two-handed, and stylus-operated mobile information devices
General Notes on Consumer Devices and Embedded Systems
Over the past thirty years, the performance of computer hardware has doubled approximately every 12 to 24 months. This has led to unprecedented miniaturization and widespread usage of computer technology. The price of the microprocessor in today’s personal computers is only a few cents per megahertz, and the price is still decreasing rapidly. Today’s small wireless devices such as cell phones and two-way pagers have microprocessors that are similar to those that were commonly used in high-end desktop computers less than fifteen years ago. Ultimately, computing power and storage capacity will become extremely cheap. Inexpensive devices, home appliances, and consumer products such as microwave ovens, shopping carts, wallets, and toys will include powerful processors and megabytes of storage memory. Thanks to Mooreí s Law, software developers for desktop computers and servers haven’t had to worry very much about processing power or efficiency of their software. Many performance problems have been resolved simply by waiting for a more powerful computer to become available. However, the consumer device space and embedded software development are different. Even though the processing power of consumer devices and embedded systems is increasing, the majority of these systems are still very resource-
GENERAL NOTES ON CONSUMER DEVICES AND EMBEDDED SYSTEMS
constrained and limited in processing power. And, unlike in the desktop and enterprise computing area, the situation is not likely to change dramatically in the next few years. There are several reasons for this: • Moore’s Law does not apply to the battery. Most consumer devices are batteryoperated. Even though battery technology has advanced substantially in the past years, the advances in battery technology are not as dramatic and predictable as in microprocessor development. Low power consumption is very important in wireless devices, because 75 to 85 percent of the battery power typically needs to be reserved for the radio transmitter and RF signal processing. This places severe power constraints on the rest of the system. • High-volume production. Typically, consumer devices such as cellular phones are manufactured in extremely large quantities (millions or even tens of millions of units). They are sold to price-conscious consumers at prices that are very low, often subsidized. To improve their profit margins, device manufacturers want to keep the per-unit costs of the devices as low as possible. Additional processing power or precious dynamic memory will not be added unless the consumers are willing to pay for the extra capabilities. • Specialized nature of devices. Consumer devices are typically highly specialized. Each device is usually highly customized for its intended usage: cell phones for voice communication, pagers for alphanumeric message retrieval, digital cameras for photography, and so on. Again, to keep the price of the devices reasonable, device manufacturers are not willing to add general-purpose features and capabilities that would raise the cost of the device, unless the features are well-justified from the viewpoint of the target market and the consumer. In general, a fundamental difference between desktop/enterprise computing and consumer devices is that in the consumer device space one solution does not fit all. Unlike personal computers, which can run tens of thousands of different kinds of applications, and are not customized particularly well for any single application, consumer devices are typically highly specialized for their intended use and are designed to do only one or a few things well. This means that unlike desktop and enterprise computers, whose performance is typically easy to measure in terms of their processing power, the performance and value of consumer devices and embedded systems is measured in terms of how well they serve their intended usage. The specialized nature of the devices has to be kept in mind when developing software for these devices.
29
30
CHAPTER 3
GOALS, REQUIREMENTS, AND SCOPE
There are further factors differentiating the consumer device space from desktop computers. These include: • Small screen size. The majority of consumer devices have miniscule screens compared to desktop computers or servers. Some devices have no screens at all. • Different usage models. The usage models of small devices vary considerably. Some are stylus-operated, some have tiny phone keypads operated with one hand only, some have small QWERTY keyboards operated using two thumbs, some are voice-operated/hands-free, and so on. • Mobility. Compared to personal computers, consumer devices are operated in varying and sometimes unusual circumstances, for example, while in traffic, while roller skating or skiing, at night, on a beach, in a snowstorm, and so on. • Limited network bandwidth with intermittent connections. Personal computer users have become accustomed to relatively reliable, rather high-speed networks based on TCP/IP and other well-established network protocols. In contrast, many wireless devices have intermittent, low-bandwidth network connections. In summary, the rules that apply to desktop and enterprise software development do not generally apply to consumer devices and embedded software development. Even though from the historical viewpoint it would be quite easy to predict the future of small devices to be similar to the past history of personal computers, it is by no means obvious that the history will actually repeat itself in this context. Rather, at least for the time being, a fundamentally different mindset is required to address the peculiarities of consumer devices, embedded systems, and the consumer market.
3.4
Requirements
This section introduces the technical requirements and constraints that were followed in defining the CLDC and MIDP standards. We start with the hardware and software requirements, and then discuss the specific constraints that Java 2 Micro Edition imposes on its configurations and profiles. It should be noted that the requirements of CLDC and MIDP are different. CLDC is not targeted to any specific device category, and therefore its requirements are broader than those of MIDP. MIDP is focused specifically on two-way
REQUIREMENTS
wireless communication devices such as cell phones, and the requirements of MIDP are specific to its target market. 3.4.1
Hardware Requirements of CLDC
CLDC is intended to run on a wide variety of small devices. The underlying hardware capabilities of these devices vary considerably, and therefore the CLDC Specification does not impose any specific hardware requirements other than memory requirements. Even for memory limits, the CLDC Specification defines minimum limits only. The actual CLDC target devices may have significantly more memory than the minimum. The CLDC Specification assumes that the minimum total memory budget available for the Java Virtual Machine, configuration libraries, profile libraries, and the applications is at least 192 kilobytes. More specifically, it is assumed that: • At least 160 kilobytes of non-volatile3 memory is available for the virtual machine and CLDC libraries. • At least 32 kilobytes of volatile4 memory is available for the virtual machine runtime (for example, the object heap). The ratio of volatile to non-volatile memory in the total memory budget can vary considerably depending on the target device and the role of the Java platform in the device. If the Java platform is used strictly for running system applications that are built in a device, then applications can be prelinked and preloaded, and a very limited amount of volatile memory is needed. If the Java platform is used for running dynamically downloaded content, then devices will need a higher ratio of volatile memory.
3.
The term non-volatile is used to indicate that the memory is expected to retain its contents between the user turning the device “on” or “off.” For the purposes of the CLDC Specification and MIDP Specification, it is assumed that non-volatile memory is usually accessed in read mode and that special setup might be required to write to it. Examples of non-volatile memory include ROM, flash, and battery-packed SDRAM. The CLDC Specification or MIDP Specification do not define which memory technology a device must have, nor do they define the behavior of such memory in a power-loss scenario. 4. The term volatile is used to indicate that the memory is not expected to retain its contents between the user turning the device “on” or “off.” For the purposes of the CLDC Specification and MIDP Specification, it is assumed that volatile memory can be read from and written to directly. The most common type of volatile memory is DRAM.
31
32
CHAPTER 3
3.4.2
GOALS, REQUIREMENTS, AND SCOPE
Hardware Requirements of MIDP
The MIDP expert group defined a Mobile Information Device (MID) to be a device that should meet the following minimum requirements: • Memory: ■
256 kilobytes of non-volatile memory for the MIDP components5
■
8 kilobytes of non-volatile memory for application-created persistent data
■
128 kilobytes of volatile memory for the virtual machine run time (for example, the object heap)
• Display: ■
Screen-size: 96x54
■
Display depth: 1-bit
■
Pixel shape (aspect ratio): approximately 1:1
• Input: ■
One or more of the following user-input mechanisms (see Figure 3.3): – “one-handed keypad” – “two-handed keyboard” – touch screen
• Networking: ■
Two-way, wireless, possibly intermittent, with limited bandwidth
• Sound: ■
3.4.3
The ability to play tones, either via dedicated hardware, or via software algorithm. Software Requirements of CLDC
Like the hardware capabilities, the system software in CLDC target devices varies considerably. For instance, some of the devices might have a full-featured operating system that supports multiple, concurrent operating system processes and a hierarchical file system. Many other devices might have extremely limited system software with no notion of a file system. Faced with such variety, CLDC makes minimal assumptions about the underlying system software. 5.
Memory requirements cited here are for MIDP components only. MIDP runs on top of CLDC, so the static size of the CLDC implementation must be added to this figure.
REQUIREMENTS
Generally, the CLDC Specification assumes that a minimal host operating system or kernel is available to manage the underlying hardware. This host operating system must provide at least one schedulable entity to run the Java virtual machine. The host operating system does not need to support separate address spaces or processes, nor does it have to make any guarantees about the real-time scheduling or latency behavior. 3.4.4
Software Requirements of MIDP
For devices meeting the MIDP hardware requirements described in previous subsection, there is a broad range of possible system software capabilities. Unlike the consumer desktop computer model where there are large, dominant system software architectures, the Mobile Information Device (MID) space is characterized by a wide variety of system software. For example, some MIDs might have a full-featured operating system that supports multiprocessing6 and hierarchical file systems, while other MIDs might have small, thread-based operating systems with no notion of a file system. Faced with such variety, the MIDP Specification, like the CLDC Specification, makes minimal assumptions about system software. These requirements are as follows: • A minimal kernel to manage the underlying hardware (that is, handling of interrupts, exceptions, and minimal scheduling). This kernel must provide at least one schedulable entity to run the Java Virtual Machine. The kernel does not need to support separate address spaces (or processes) or make any guarantees about either real-time scheduling or latency behavior. • A mechanism to read and write from non-volatile memory to support the MIDP persistence APIs discussed in Chapter 14. • Read and write access to the device’s wireless networking to support the MIDP networking APIs discussed in Chapter 15. • A mechanism to provide a time base for use in time-stamping the records written to persistent storage and to provide the basis of the timer APIs defined in Section 20.1, “Timer Support.” • A minimal capability to write to a bit-mapped graphics display. • A mechanism to capture user input from one (or more) of the three input mechanisms previously discussed. 6.
The ability to run multiple, concurrent processes, each with a separate and distinct memory map.
33
34
CHAPTER 3
3.4.5
GOALS, REQUIREMENTS, AND SCOPE
J2ME Requirements
CLDC is defined as a Java 2 Micro Edition (J2ME™) configuration. MIDP is defined as a Java 2 Micro Edition profile. The rules for J2ME configurations and profiles impose certain additional constraints on the CLDC and MIDP specifications: • A J2ME configuration shall only define a minimum complement or the “lowest common denominator” of Java technology. All the features included in a configuration must be generally applicable to a wide variety of devices. Features specific to a certain vertical market, device category, or industry should be defined in a profile. This means that the scope of the Connected, Limited Device Configuration Specification is limited and must generally be complemented by profiles. • Since the goal of the J2ME configurations is to guarantee portability and interoperability between various kinds of resource-constrained devices, the configurations do not define any optional features. This limitation has a significant impact on what can be included in the CLDC Specification and what should not be included. More device-specific or optional functionality should generally be avoided, but, if necessary, such functionality must be defined in J2ME optional packages, manufacturer-specific licensee open classes (also known as OEMspecific classes), rather than in the J2ME configuration or profile specifications. • A J2ME configuration specification shall generally define a subset of the Java technology features and libraries provided by the Java 2 Platform, Standard Edition (J2SE). Consequently, rather than providing a complete description of all the supported features, the CLDC Specification shall only define the variances and differences compared to the full Java Language Specification (JLS) and Java Virtual Machine Specification (JVMS). If something is not explicitly specified in the CLDC Specification, then it is assumed that a virtual machine conforming to the CLDC Specification shall comply with the JLS and JVMS. Note that the absence of optional features in CLDC and MIDP does not preclude the use of various implementation-level optimizations. For instance, at the implementation level, alternative bytecode execution techniques (for example, Just-In-Time compilation) or application representation techniques can be used as long as the observable user-level semantics of the implementation remain the same as defined by the CLDC Specification and MIDP Specification.
SCOPE OF THE CLDC AND MIDP STANDARDS
3.5
Scope of the CLDC and MIDP Standards
3.5.1
Scope of CLDC
Based on the decisions of the JSR 30 and JSR 139 expert groups, the CLDC Specification addresses the following areas: • Java language and virtual machine features • core libraries (java.lang.*, java.io.*, java.util.*) • input/output • networking • security • internationalization The CLDC Specification intentionally does not address the following functionality areas and features: • application life-cycle management (installation, launching, deletion) • user interface functionality • event handling • high-level application model (interaction between the user and the application) These features can be addressed by profiles implemented on top of the Connected, Limited Device Configuration. In general, the CLDC expert group intentionally kept small the number of areas addressed by the CLDC Specification in order not to exceed the strict memory limitations or to exclude any particular device category. 3.5.2
Scope of MIDP
Mobile Information Devices (MIDs) span a potentially wide set of capabilities. Rather than try to address all such capabilities, the MIDP 1.0 expert group agreed to limit the set of APIs specified, addressing only those APIs that were considered absolute requirements to achieve broad portability.
35
36
CHAPTER 3
GOALS, REQUIREMENTS, AND SCOPE
These APIs are: • application model (that is, defining the semantics of a MIDP application and how the application is controlled) • user interface (includes display and input) • persistent storage • networking • timers The MIDP 2.0 expert group expanded upon these APIs to add the highest priority functionality identified as missing after the experience of the initial MIDP device deployments. The added MIDP 2.0 APIs are: • sounds • 2D games • MIDlet signing model for added security • end-to-end security through HTTPS and secure sockets • application delivery and installation By the same reasoning, some areas of functionality were considered to be outside the scope of the MIDP expert groups. These areas include: • System-level APIs: The emphasis of the Mobile Information Device Profile is on enabling application programming rather than enabling system programming. Thus, low-level APIs that specify a system interface to, for example, power management or voice CODECs, are beyond the scope of the MIDP Specification. • Low-level security7: MIDP specifies no additional low-level security features other than those provided by the CLDC. • Application-level cryptography8: MIDP specifies no explicit cryptography APIs, although MIDlet Suite Security is described in Chapter 18.
7.
Low-level security (also known as virtual machine security) ensures that an ill-formed or maliciously encoded class file does not crash the virtual machine or the device. 8. Application-level cryptography defines which APIs and system resources the application can access.
SCOPE OF THE CLDC AND MIDP STANDARDS
At first glance, the scope of the MIDP Specification might seem limited. However, given the broad range of devices that the MIDP Specification addresses, the MIDP expert group felt that it would be better to concentrate on a small set of common, required functionality, and by doing so create a “lowest common denominator” platform where none exists today. In particular, the MIDP expert group did not want to mandate features that cannot be supported easily on all the MIDP target devices and wireless networks.
37
This page intentionally left blank
C H A P T E R
4
Connected Limited Device Configuration This chapter introduces the Connected, Limited Device Configuration (CLDC), one of the core building blocks of the Java™ 2 Platform, Micro Edition (J2ME™). The goal of the Connected, Limited Device Configuration is to provide a standardized, highly portable, minimum-footprint Java application development platform for resource-constrained, connected devices. The CLDC target devices are characterized generally as follows: • at least 192 kilobytes of total memory budget available for the Java platform, • a 16-bit or 32-bit processor, • low power consumption, often operating with battery power, and • connectivity to some kind of network, often with a wireless, intermittent connection and with limited (often 9600 bps or less) bandwidth. CLDC is core technology that can be used as the basis for one or more J2ME profiles. Cell phones, two-way pagers, personal digital assistants (PDAs), organizers, home appliances, low-end TV set-top boxes, and point-of-sale terminals are some, but not all, of the devices that might be supported by the Connected, Limited Device Configuration. The material in this chapter comes from the CLDC Specification document that is available from the Java Community Process (JCP) web site.1 The CLDC Specification defines the minimum required complement of Java technology components and libraries for small connected devices. Java language and virtual 1.
http://jcp.org/en/jsr/detail?id=139
39
40
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
machine features, core libraries, input/output, networking, and security are the primary topics addressed by the CLDC Specification.
4.1
CLDC Expert Groups
4.1.1
CLDC 1.0 Expert Group
The CLDC Specification version 1.0, completed in May 2000, was the result of the work of a Java Community Process (JCP) expert group JSR 30 consisting of a large number of industrial partners. The following 18 companies (in alphabetical order) were members of the CLDC 1.0 expert group:
4.1.2
• America Online
• Oracle
• Bull
• Palm Computing
• Ericsson
• Research In Motion (RIM)
• Fujitsu
• Samsung
• Matsushita
• Sharp
• Mitsubishi
• Siemens
• Motorola
• Sony
• Nokia
• Sun Microsystems
• NTT DoCoMo
• Symbian
CLDC 1.1 Expert Group
The CLDC Specification version 1.1 was produced by the Java Community Process (JCP) expert group JSR 139 consisting of the following full members:
• aJile Systems
• Openwave Systems
• Aplix Corporation
• Oracle
• France Telecom
• Panasonic
CLDC ARCHITECTURE, APPLICATION MODEL, AND SECURITY
• Fujitsu
• Research In Motion
• Insignia Solutions
• Samsung
• Liberate Technologies
• Siemens
• Mitsubishi Electric
• Sony
• Motorola
• Sony Ericsson Mobile Communications
• NEC
• Sun Microsystems
• Nokia
• Symbian
• NTT DoCoMo
• Vulcan Machines
• OpenTV
• Zucotto Wireless
4.2
CLDC Architecture, Application Model, and Security
4.2.1
Architectural Overview
The high-level architecture of a typical CLDC device is illustrated in Figure 4.1. At the heart of a CLDC implementation is the Java Virtual Machine, which, apart from specific differences defined later in this chapter, is compliant with the Java Virtual Machine Specification and Java Language Specification. The virtual machine typically runs on top of a host operating system that provides the necessary capabilities to manage the underlying hardware. As explained in Section 3.4.3, “Software Requirements of CLDC,” the CLDC Specification makes minimal assumptions about the capabilities of the host operating system. On top of the virtual machine are the Java libraries. These libraries are divided broadly into two categories: 1. those defined by the Connected, Limited Device Configuration (CLDC Libraries), and 2. those defined by profiles (such as MIDP) and optional packages. Libraries defined by the Connected, Limited Device Configuration are discussed in Chapter 5. Libraries defined by profiles are outside the scope of the
41
42
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
CLDC Specification. The libraries supported by the Mobile Information Device Profile are discussed in Chapters 8 through 20.
Figure 4.1
4.2.2
Architecture overview of a CLDC target device
The Concept of a Java Application
Connected, Limited Device Configuration is not targeted to any specific device category. Many of the target devices may have an advanced graphical user interface, some target devices may be operated from a textual, character-based user interface, while some other target devices may not have any visual user interface or display at all. To cater to such a broad variety of devices, the application model defined in the CLDC Specification is intentionally very simple. In the CLDC Specification, the term Java application is used to refer to a collection of Java class files containing a single, unique method main that identifies the launch point of the application. As specified in the Java Virtual Machine Specification (JVMS) Sections 5.2 and 2.17.1, the method main must be declared public, static, and void, as shown below: public static void main(String[] args)
CLDC ARCHITECTURE, APPLICATION MODEL, AND SECURITY
A virtual machine conforming to CLDC starts the execution of a Java application by calling the method main. J2ME profiles such as MIDP define alternative application models that extend or override the basic application model defined by the CLDC Specification. 4.2.3
Application Security
The total amount of code devoted to security in the Java 2 Platform, Standard Edition far exceeds the total memory budget available for CLDC. Therefore, some simplifications are necessary when defining the security model for CLDC applications. Basically, the security model of CLDC can be examined at three different levels: • Low-level security (also known as virtual machine security). Ensures that the applications running in the virtual machine follow the semantics of the Java programming language, and that an ill-formed or maliciously encoded class file does not crash or in any other way harm the target device. • Application-level security. Means that a Java application running on a device can access only those libraries, system resources, and other components that the device and the Java application environment allows it to access. • End-to-end security. Refers to a model that guarantees that any transaction initiated on a device is protected along the entire path from the device to/from the entity providing the services for that transaction (e.g, a server located on the Internet). Encryption or other means may be necessary to achieve this. End-toend security is outside the scope of the CLDC Specification. Below we take a more detailed look at low-level security and application-level security requirements. Low-level security A key requirement for a Java virtual machine in a mobile information device is lowlevel security. An application running in the virtual machine must not be able to harm the device in which the virtual machine is running, or crash the device. In a standard Java virtual machine implementation, this constraint is guaranteed by the class file verifier, which ensures that the bytecodes and other items stored in class files cannot contain illegal instructions, cannot be executed in an illegal order, and cannot contain references to invalid memory locations or memory areas that are outside the Java object memory (the object heap). In general, the role of the class file
43
44
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
verifier is to ensure that class files loaded into the virtual machine do not execute in any way that is not allowed by the Java™ Virtual Machine Specification. As will be explained in more detail later, the CLDC Specification requires that a Java virtual machine conforming to the CLDC standard must be able to reject invalid class files. This is guaranteed by the class file verification technology presented in Section 4.4.2, “Class File Verification.” Application-level security Even though class file verification plays a critical role in ensuring the security of the Java platform, the security provided by the class file verifier is insufficient by itself. The class file verifier can only guarantee that the given program is a valid Java application and nothing more. There are still several other potential security threats that will go unnoticed by the verifier. For instance, access to external resources such as the file system, printers, infrared devices, native libraries, or the network is beyond the scope of the class file verifier. By application-level security, we mean that a Java application can access only those libraries, system resources, and other components that the device and the Java application environment allows it to access. In CLDC, application-level security is accomplished by using a metaphor of a closed “sandbox.” A CLDC application runs in a closed environment in which the application can access only those libraries that have been defined by the configuration, profiles, optional packages, and other classes supported by the device. Java applications cannot escape from this sandbox or access any libraries or resources that are not part of the predefined functionality. The sandbox ensures that a malicious or possibly erroneous application cannot gain access to system resources. More specifically, the CLDC sandbox model requires that: • Class files must be properly verified and guaranteed to be valid Java applications. (Class file verification is discussed in more detail in Section 4.4.2, “Class File Verification.”) • The downloading, installation, and management of Java applications on the device takes place in such a way that the application programmer cannot modify or bypass the standard class loading mechanisms of the virtual machine. • A closed, predefined set of Java APIs is available to the application programmer, as defined by CLDC, profiles, optional packages, and manufacturerspecific classes. • The set of native functions accessible to the virtual machine is closed, meaning that the application programmer cannot download any new libraries containing native functionality or access any native functions that are not part of the Java
CLDC ARCHITECTURE, APPLICATION MODEL, AND SECURITY
libraries provided by CLDC, profiles, optional packages, or manufacturerspecific classes. For security reasons, the CLDC Specification also defines some additional requirements related to the interplay between system classes and application classes. For instance, a CLDC implementation is required to ensure that the application programmer cannot override, modify, or add any classes to system packages such as java.*, javax.microedition.*, or profile-specific packages, or manipulate the built-in class file lookup order in any way. Class file lookup order is discussed in more detail in Section 4.4.3, “Class File Format and Class Loading.” In addition, it is required that a CLDC application can load application classes only from its own Java Archive (JAR) file. This restriction ensures that Java applications on a device cannot interfere with each other or steal data from each other. Additionally, this ensures that a third-party application cannot gain access to the private or protected components of the Java classes that the device manufacturer or a service provider may have provided as part of the system applications. JAR files and applications representation formats are discussed in more detail in Section 4.4.3, “Class File Format and Class Loading.” J2ME profiles such as MIDP may define additional security solutions on top of those provided by CLDC. MIDP security will be discussed in detail in Chapter 16, “Secure Networking” and Chapter 18, “Security for MIDlet Suites.” 4.2.4
Application Management
Many small, resource-constrained devices do not have a file system or any other conventional mechanism for storing dynamically downloaded information on the device. Therefore, a CLDC implementation does not require that Java applications downloaded from an external source are stored persistently on the device. Rather, the implementation might just load the application and discard it immediately after execution. However, in many potential CLDC devices, it is beneficial to be able to execute the same Java applications multiple times without having to download the applications over and over again. This is particularly important if applications are being downloaded over a wireless network, and the user could incur high downloading expenses. If a device implementing CLDC is capable of storing applications persistently, we assume that the device implementing has capabilities for managing the applications that have been stored in the device. At the high level, application management refers to the ability to
45
46
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
• download and install Java applications, • inspect existing Java applications stored on the device, • select and launch Java applications, and • delete existing Java applications. Depending on the resources available on the device, a CLDC system may allow multiple Java applications to execute concurrently or can restrict the system to permit the execution of only one Java application at a time. It is up to the particular implementation to decide whether the execution of multiple Java applications is supported by utilizing the multiprocessing capabilities (if they exist) of the underlying host operating system or by instantiating multiple logical virtual machines to run the concurrent Java applications. Due to significant variations and feature differences among potential CLDC devices, the details of application management are highly device-specific and implementation-dependent. The actual details of application management are outside the scope of the CLDC Specification. Application management issues in the context of the Mobile Information Device Profile are discussed in Section 19.2, “MIDP System Software.”
4.3
Java Language Specification Compatibility
The general goal for a virtual machine conforming to CLDC is to be as compliant with the Java Language Specification as is feasible within the strict memory limits of CLDC target devices. This section summarizes the differences between a virtual machine conforming to CLDC and the Java Virtual Machine of Java 2 Standard Edition (J2SE). Except for the differences indicated herein, a virtual machine conforming to CLDC is compatible with The Java Language Specification, Second Edition, by James Gosling, Bill Joy, Guy L. Steele, and Gilad Bracha, AddisonWesley, 2000, ISBN 0-201-31008-2.
Note: For the remainder of this book, the Java Language Specification is referred to as JLS. Sections within the Java Language Specification are referred to using the § symbol. For example, (JLS §4.2.4).
JAVA LANGUAGE SPECIFICATION COMPATIBILITY
4.3.1
No Finalization of Class Instances
CLDC libraries do not include the method java.lang.Object.finalize(). Therefore, a virtual machine conforming to CLDC does not support finalization of class instances (JLS §12.6). No application built to conform to the Connected, Limited Device Configuration can require that finalization be available. 4.3.2
Error-Handling Limitations
A virtual machine conforming to CLDC generally supports exception handling as defined in JLS Chapter 11, with the exception that asynchronous exceptions (JLS §11.3.2) are not supported. In contrast, the set of error classes included in CLDC libraries is limited, and consequently the error-handling capabilities of CLDC are considerably more limited. This is because of two reasons: 1. In embedded systems, recovery from error conditions is usually highly devicespecific. Application programmers cannot be expected to know about devicespecific error-handling mechanisms and conventions. 2. As specified in JLS §11.5, class java.lang.Error and its subclasses are exceptions from which programs are not ordinarily expected to recover. Implementing the error-handling capabilities fully according to the Java™ Language Specification is rather expensive, and mandating the presence and handling of all the error classes would impose an overhead on the virtual machine implementation. A virtual machine conforming to CLDC provides a limited set of error classes defined in Section 5.2.7, “Exception and Error Classes.” When encountering any other error, the implementation behaves as follows: • either the virtual machine halts in an implementation-specific manner, • or the virtual machine throws an Error that is the nearest CLDC-supported superclass of the Error class that must be thrown according to the Java™ Language Specification. If the virtual machine conforming to CLDC implements additional error checks that are part of the Java™ Language Specification but that are not required by the CLDC Specification, the implementation shall throw the nearest CLDC-
47
48
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
supported superclass of the Specification.
4.4
Error
class that is defined by the Java™ Language
Java Virtual Machine Specification Compatibility
The general goal for a virtual machine conforming to CLDC is to be as compliant with the Java Virtual Machine Specification as is possible within strict memory constraints of CLDC target devices. This section summarizes the differences between a virtual machine conforming to CLDC and the Java Virtual Machine of Java 2 Standard Edition (J2SE). Except for the differences indicated herein, a virtual machine conforming to CLDC is compatible with the Java Virtual Machine as specified in the The Java Virtual Machine Specification, Second Edition, by Tim Lindholm and Frank Yellin. Addison-Wesley, 1999, ISBN 0-201-43294-3. Note: For the remainder of this book, the Java Virtual Machine Specification is referred to as JVMS. Sections within the Java Virtual Machine Specification are referred to using the § symbol. For example, (JVMS §2.4.3).
4.4.1
Features Eliminated from the Virtual Machine
A number of features have been eliminated from a virtual machine conforming to CLDC because the Java libraries included in CLDC are substantially more limited than libraries in Java 2 Standard Edition, and/or the presence of those features would have posed security problems in the absence of the full J2SE security model. The eliminated features include: • user-defined class loaders (JVMS §5.3.2), • thread groups and daemon threads (JVMS §2.19, §8.12), • finalization of class instances (JVMS §2.17.7), and • asynchronous exceptions (JVMS §2.16.1). In addition, a virtual machine conforming to CLDC has a significantly more limited set of error classes than a full J2SE virtual machine. Applications written to conform to the Connected, Limited Device Configuration shall not rely on any of the features above. Each of the features in this list is discussed in more detail next.
JAVA VIRTUAL MACHINE SPECIFICATION COMPATIBILITY
User-defined class loaders A virtual machine conforming to CLDC does not support user-defined, Java-level class loaders (JVMS §5.3, §2.17.2). A virtual machine conforming to CLDC has a built-in “bootstrap” class loader that cannot be overridden, replaced, or reconfigured. The elimination of user-defined class loaders is part of the security restrictions of the CLDC Specification. Thread groups and daemon threads A virtual machine conforming to CLDC implements multithreading, but does not have support for thread groups or daemon threads (JVMS §2.19, §8.12). Thread operations such as starting of threads can be applied only to individual thread objects. If application programmers want to perform thread operations for groups of threads, explicit collection objects (such as instances of classes Hashtable or Vector) must be used at the application level to store the thread objects. Finalization of class instances CLDC libraries do not include the method java.lang.Object.finalize(). Therefore, a virtual machine conforming to CLDC does not support finalization of class instances (JVMS §2.17.7). No application built to conform to the Connected, Limited Device Configuration can require that finalization be available. Errors and asynchronous exceptions As discussed earlier in Section 4.3.2, “Error-Handling Limitations,” the error-handling capabilities of a virtual machine conforming to CLDC are limited. A virtual machine conforming to CLDC supports the set of Error classes defined in Section 5.2, “Classes Derived from Java 2 Standard Edition.” When encountering any other error, the implementation shall behave as follows: • either the virtual machine halts in an implementation-specific manner, • or the virtual machine throws an Error that is the nearest CLDC-supported superclass of the Error class that must be thrown according to the Java™ Virtual Machine Specification. If the virtual machine conforming to CLDC implements additional error checks that are part of the Java™ Virtual Machine Specification but that are not required by the CLDC Specification, the implementation will throw the nearest
49
50
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
CLDC-supported superclass of the Error class that is defined by the Java™ Virtual Machine Specification. A virtual machine conforming to CLDC generally supports exception handling as defined by Java™ Virtual Machine Specification. However, a virtual machine conforming to CLDC does not support asynchronous exceptions (JVMS §2.16.1). 4.4.2
Class File Verification
Like the Java Virtual Machine of Java 2 Standard Edition, a virtual machine conforming to CLDC must be able to reject invalid class files. However, since the static and dynamic memory footprint of the standard class file verifier is excessive for a typical CLDC target device, an alternative solution is defined in the CLDC Specification. This solution is described below. Off-device preverification and runtime verification with stack maps The existing J2SE class file verifier defined in the Java Virtual Machine Specification (JVMS §4.9) is not ideal for small, resource-constrained devices. The J2SE verifier takes a minimum of 50 kilobytes of binary code space and typically at least 30 to 100 kilobytes of dynamic RAM at run time. In addition, the CPU power needed to perform the complex dataflow algorithm in the conventional verifier can be substantial. The verification approach described in this subsection is significantly smaller and more efficient in resource-constrained devices than the existing J2SE verifier. The implementation of the new verifier in Sun’s CLDC reference implementation requires about 12 kilobytes of Intel x86 binary code and less than 100 bytes of dynamic RAM at run time for typical class files. The verifier performs only a linear scan of the bytecode, without the need of a costly dataflow algorithm. The CLDC class file verifier operates in two phases, as depicted in Figure 4.2. • First, class files have to be run through a special preverifier tool in order to remove certain bytecodes and augment the class files with additional StackMap attributes to speed up runtime verification. The preverification phase is typically performed on the development workstation that the application developer uses for writing and compiling the applications. • At run time, the runtime verifier component of the virtual machine uses the additional StackMap attributes generated by the preverifier to perform the actual class file verification efficiently. The execution of bytecodes in a class file can start only when the class file has successfully passed the runtime verifier.
JAVA VIRTUAL MACHINE SPECIFICATION COMPATIBILITY
Development workstation MyApp.java
Download...
Target device (KVM runtime)
javac
MyApp.class
runtime verifier
preverifier interpreter MyApp.class
Figure 4.2
Two-phase class file verification in CLDC
Runtime class file verification guarantees type safety. Classes that pass the runtime verifier cannot, for example, violate the type system of the Java virtual machine or corrupt the memory. Unlike approaches based on code signing, such a guarantee does not rely on the predefined verification information to be authentic or trusted. A missing, incorrect, or corrupted StackMap attribute causes the class to be rejected by the runtime verifier. The new verifier requires the methods in class files to contain a special StackMap attribute. The preverifier tool inserts this attribute into normal class files. A transformed class file is still a valid Java class file, with additional StackMap attributes (refer to the CLDC Specification for further details) that allow verification to be carried out efficiently at run time. These attributes are automatically ignored by the conventional class file verifier used in Java 2 Standard Edition, so the solution is fully upward compatible with the Java Virtual Machine of Java 2 Standard Edition. Preprocessed class files containing the extra attributes are approximately 5 to 15 percent larger than the original, unmodified class files. Additionally, the new verifier requires that all the subroutines in the bytecodes of class files are inlined. In Java class files, subroutines are special bytecode sequences that contain the bytecodes jsr, jsr_w, ret, or wide ret. The inlining process removes all the jsr, jsr_w, ret, and wide ret bytecodes from all the methods in class files, replacing these instructions with semantically equivalent byte-
51
52
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
code. The inlining process makes runtime verification significantly easier and faster. The new verification process and the format of the StackMap attribute have been specified in more detail in the CLDC Specification. 4.4.3
Class File Format and Class Loading
An essential requirement for the Connected, Limited Device Configuration is the ability to support dynamic downloading of Java applications and third-party content. The dynamic class loading mechanism of the Java platform plays a central role in this. This section discusses the application representation formats and class loading practices required of a virtual machine conforming to CLDC. Supported file formats A CLDC implementation must be able to read standard class files (defined in JVMS Chapter 4) with the preverification changes discussed above. In addition, a CLDC implementation must support compressed Java Archive (JAR) files. Detailed information about the JAR format is provided at http://java.sun.com/products/jdk/ 1.2/docs/guide/jar/. Network bandwidth conservation is very important in lowbandwidth wireless networks. The compressed JAR format provides 30 to 50 percent compression over regular class files without loss of any symbolic information or compatibility problems with existing Java systems. A CLDC implementation must be able to read Java class files in all the formats supported by Java 2 Platform Standard Edition, JDK versions 1.1, 1.2, 1.3, and 1.4. Note: The class file formats used by different JDK versions are as follows2: – The 45.* (usually 45.3) version number identifies JDK 1.1 class files. – The 46.* version number identifies JDK 1.2 class files. – The 47.* version number identifies JDK 1.3 class files. – The 48.* version number identifies JDK 1.4 class files. A virtual machine conforming to CLDC should be able to read Java class files in any of the formats listed above. However, the virtual machine is allowed to 2.
In practice, the situation is a bit more complicated. In pre-JDK 1.4 releases, the javac compiler produced class files in 45.3 format for compatibility with the older versions of the JDK. In JDK 1.4, javac produces 46.0 (JDK 1.2) files by default. However, the compiler can be instructed to produce other class file formats using the “-target” option. For instance, “javac -target 1.1” would produce 45.3 class files.
JAVA VIRTUAL MACHINE SPECIFICATION COMPATIBILITY
ignore certain class file attributes that the CLDC implementation does not need. More specifically, the following attributes can be ignored by a CLDC implementation: • The Synthetic attribute (JVMS §4.7.6) • The SourceFile attribute (JVMS §4.7.7) • The LineNumberTable attribute (JVMS §4.7.8) • The LocalVariableTable attribute (JVMS §4.7.9) • The Deprecated attribute (JVMS §4.7.10) Public representation of Java applications and resources A Java application is considered to be “represented publicly” or “distributed publicly” when the system it is stored on is open to the public and the transport layers and protocols it can be accessed with are open standards. In contrast, a device can be part of a closed network environment where the vendor (such as the operator of a wireless network) controls all communication. In this case, the application is no longer represented publicly once it enters and is distributed via the closed network system. Whenever Java applications intended for a CLDC device are represented publicly, the compressed JAR file representation format must be used. The JAR file must contain regular class files with the following restrictions and additional requirements: 1. StackMap attributes (see CLDC Specification version 1.1, Appendix 1, for details) must be included in class files. 2. The class files must not contain any of the following bytecodes: jsr (JVMS p. 304, jsr_w (JVMS p. 305), ret (JVMS p. 352), and wide ret (JVMS p. 360). Sun’s CLDC reference implementation includes a preverification tool for performing these modifications to a class file. The stack map attributes are automatically ignored by the conventional class file verifier described in JVMS §4.9. That is, the modified class file format is fully upward compatible with other Java environments such as J2SE or J2EE. Additionally, the JAR file may contain application-specific resource files that can be loaded into the virtual machine by calling method Class.getResourceAsStream(String name).
53
54
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
Class file lookup order The Java Language Specification and Java Virtual Machine Specification do not specify the order in which class files are searched when new class files are loaded into the virtual machine. At the implementation level, a typical virtual machine implementation uses the environment variable CLASSPATH to define the lookup order. The CLDC Specification assumes class file lookup order to be implementation-dependent, with the restrictions described in the next paragraph. The lookup strategy is typically defined as part of the application management implementation (see Section 4.2.4, “Application Management.”) A virtual machine conforming to CLDC is not required to support the notion of CLASSPATH, but may do so at the implementation level. Two restrictions apply to class file lookup order. First, a virtual machine conforming to CLDC must guarantee that the application programmer cannot override, modify, or add new system classes (classes belonging to CLDC, profiles, or other libraries) in any way. Second, it is required that the application programmer must not be able to manipulate the class file lookup order in any way. Both of these restrictions are important for security reasons. Implementation optimizations The CLDC Specification mandates the use of compressed JAR files for Java applications that are represented and distributed publicly. However, in closed network environments (see the discussion above) and internally inside the virtual machine at run time, alternative application representation formats can be used. For instance, in low-bandwidth wireless networks it is often advised to use alternative, more compact transport formats at the network transport level to conserve network bandwidth. Similarly, when storing the downloaded applications in CLDC devices, more compact representations can be used as long as the observable user-level semantics of the applications remain the same as with the public representation required by the CLDC Specification. The definition of more compact class file representations is assumed to be implementation-dependent and outside the scope of the CLDC Specification. Preloading/prelinking (“ROMizing”) A virtual machine conforming to CLDC may choose to preload and prelink some classes to reduce class loading time at run time. This technology is often referred to informally as ROMizing.3 3.
The term ROMizing is somewhat misleading, since this technology can be used independent of any specific memory technology. ROMized class files do not necessarily have to be stored in ROM.
NEW FOR CLDC 1.1
Typically, small virtual machine implementations choose to preload all the system classes (for instance, classes belonging to a specific configuration or profile) and perform application loading dynamically. The actual mechanisms for preloading are implementation-dependent and beyond the scope of the CLDC Specification. In all cases, the runtime effect and semantics of preloading/prelinking must be the same as if the actual class had been loaded in at that point. There must be no visible effects from preloading other than the possible speed-up in application launching. In particular, any class initialization that has a user-visible effect must be performed at the time the class would first have been used if it had not been preloaded into the system. Application representation format optimizations Java class files are not optimized for network transport in limited bandwidth environments. Each Java class file is an independent unit that contains its own constant pool (symbol table), method, field and exception tables, bytecodes, exception handlers, and some other information. The self-contained nature of class files is one of the virtues of Java technology, allowing applications to be composed of multiple pieces that do not necessarily have to reside in the same location, making it possible to extend applications dynamically at run time. However, this flexibility has its price. If Java applications were treated as a sealed unit, a lot of space could be saved by removing the redundancies in multiple constant pools and other structures, especially if full symbolic information was left out. Also, one of the desirable features of an application transport format in a limited-power computing environment is the ability to execute applications “in place,” without any special loading or conversion process between the static representation and runtime representation. The CLDC Specification allows the use of such formats at the implementation level as long as the public application representation and the publicly observable semantics of the CLDC implementation remain the same as with the original representation required by the CLDC Specification. The definition of alternative application representation formats is implementation-dependent and outside the scope of the CLDC Specification.
4.5
New for CLDC 1.1
The CLDC 1.1 (JSR 139) expert group members were generally satisfied with the CLDC Specification version 1.0 and did not see any need for radical changes in the new specification. Therefore, CLDC Specification version 1.1 is primarily an incremental release that is intended to be fully backwards compatible with CLDC Specifi-
55
56
CHAPTER 4
CONNECTED LIMITED DEVICE CONFIGURATION
cation version 1.0. Some important new functionality, such as floating point support, has been added. The list below summarizes the main differences between CLDC Specification versions 1.1 (JSR 139) and 1.0 (JSR 30). Those differences that are specific to Java libraries supported by CLDC are summarized in Section 5.4, “New for CLDC 1.1.” • Floating point support has been added. ■
■
All floating point bytecodes are supported by CLDC 1.1. Classes Float and Double have been added, and various methods have been added to the other library classes to handle floating point values. (Refer to Section 5.4, “New for CLDC 1.1,” and the CLDC Almanacs at the end of this book for a detailed summary of the changes.)
• Weak reference support (small subset of the J2SE weak reference classes) has been added. • Error-handling requirements have been clarified, and one new error class, NoClassDefFoundError, has been added. • In CLDC 1.1, Thread objects have names like threads in J2SE do. The method Thread.getName() has been introduced, and the Thread class has a few new constructors that have been inherited from J2SE. • In CLDC 1.1, Threads can be interrupted using the Thread.interrupt method. • Minimum total memory budget for CLDC has been increased from 160 to 192 kilobytes, mainly because of the added floating point functionality. • Much more detailed verifier specification (“CLDC Byte Code Typechecker Specification”) is provided as an appendix of the CLDC Specification version 1.1.
C H A P T E R
5
CLDC Libraries Java 2 Platform, Standard Edition (J2SE) and Java 2 Platform, Enterprise Edition (J2EE) provide a very rich set of Java class libraries for the development of enterprise applications for desktop computers and servers. Unfortunately, these libraries require tens of megabytes of memory to run and are therefore unsuitable for small devices with limited resources. In this chapter we introduce the class libraries supported by the Connected, Limited Device Configuration.
5.1
Background and Goals
A general goal for designing the libraries for the Connected, Limited Device Configuration was to provide a minimum useful set of libraries for practical application development and profile definition for a variety of small devices. As explained earlier in Section 3.1, “High-Level Goals,” CLDC is a “lowest common denominator” standard that includes only minimal Java platform features and APIs for a wide range of consumer devices. Given the strict memory constraints and differing features of today’s small devices, it is virtually impossible to come up with a set of libraries that would be ideal for all devices. No matter where the bar for feature inclusion is set, the bar is inevitably going to be too low for some devices and users, and too high for many others. To ensure upward compatibility with the larger editions of the Java 2 Platform, the majority of the libraries included in CLDC are a subset of Java 2 Standard Edition (J2SE) and Java 2 Enterprise Edition (J2EE). While upward compatibility is a very desirable goal, J2SE and J2EE libraries have strong internal dependencies that make subsetting them difficult in important areas such as security, input/output, user interface definition, networking, and storage. These dependencies are a natural consequence of design evolution and reuse that has taken place during the development of the libraries over time. Unfortunately, these 57
58
CHAPTER 5
CLDC LIBRARIES
dependencies make it difficult to take just one part of the libraries without including several others. For this reason, some of them have been redesigned, especially in the area of networking. The libraries defined by the CLDC Specification can be divided broadly into two categories: 1. those classes that are a subset of standard J2SE libraries, and 2. those classes that are specific to CLDC (but that can be mapped onto J2SE). Classes belonging to the former category are located in packages
java.lang,
java.util, and java.io. These classes have been derived from Java 2 Standard Edi-
tion version 1.3.1. A list of these classes is presented in Section 5.2, “Classes Derived from Java 2 Standard Edition.” Classes belonging to the latter category are located in package javax.microedition. These classes are discussed in Section 5.3, “CLDC-Specific Classes.”
5.2
Classes Derived from Java 2 Standard Edition
CLDC provides a number of classes that have been derived from Java 2 Standard Edition (J2SE). The rules for J2ME configurations require that each class with the same name and package name as a J2SE class must be identical to or a subset of the corresponding J2SE class. The semantics of the classes and their methods included in the subset may not be changed. The classes may not add any public or protected methods or fields that are not available in the corresponding J2SE classes. 5.2.1
System Classes
J2SE class libraries include several classes that are intimately coupled with the Java Virtual Machine. Similarly, several commonly used Java tools assume the presence of certain classes in the system. For instance, the standard Java compiler (javac) generates code that requires certain methods of classes String and StringBuffer to be available. The system classes included in the CLDC Specification are listed below. Each of these classes is a subset of the corresponding class in J2SE. Note that in CLDC 1.1, many of these classes contain additional methods that are not present in CLDC 1.0. Refer to CLDC library documentation in the end of this book for more details on each class, as well as for the differences between CLDC 1.0 and 1.1. java.lang.Object java.lang.Class
CLASSES DERIVED FROM JAVA 2 STANDARD EDITION
java.lang.Runtime java.lang.System java.lang.Thread java.lang.Runnable
(interface)
java.lang.String java.lang.StringBuffer java.lang.Throwable
5.2.2
Data Type Classes
The following basic data type classes from package java.lang are supported. Each of these classes is a subset of the corresponding class in J2SE. Classes Float and Double are new in CLDC 1.1. java.lang.Boolean java.lang.Byte java.lang.Short java.lang.Integer java.lang.Long java.lang.Float java.lang.Double java.lang.Character
5.2.3
Collection Classes
The following collection classes from package java.util are supported. java.util.Vector java.util.Stack java.util.Hashtable java.util.Enumeration
5.2.4
(interface)
Input/Output Classes
The following classes from package java.io are supported. java.io.InputStream java.io.OutputStream java.io.ByteArrayInputStream java.io.ByteArrayOutputStream
(interface) java.io.DataOutput (interface) java.io.DataInput
59
60
CHAPTER 5
CLDC LIBRARIES
java.io.DataInputStream java.io.DataOutputStream java.io.Reader java.io.Writer java.io.InputStreamReader java.io.OutputStreamWriter java.io.PrintStream
5.2.5
Calendar and Time Classes
CLDC includes a small subset of the standard J2SE classes java.util.Calendar, java.util.Date, and java.util.TimeZone. To conserve space, the CLDC Specification requires only one time zone to be supported. By default, this time zone is GMT. Additional time zones may be provided by manufacturer-specific implementations of CLDC as long as the time zones are compatible with those provided by Java 2 Standard Edition. java.util.Calendar java.util.Date java.util.TimeZone
5.2.6
Additional Classes
Two additional utility classes are provided. Class java.util.Random provides a simple pseudo-random number generator that is useful for implementing applications such as games. Class java.lang.Math provides methods min, max, and abs, which are frequently used by other Java library classes. In CLDC 1.1, class java.lang.Math also includes support for floating point trigonometric functions and square root calculation, as well as some additional utility functions such as ceil and floor. java.util.Random java.lang.Math
5.2.7
Exception and Error Classes
Since the libraries included in CLDC are generally intended to be compatible with J2SE libraries, the library classes included in CLDC throw precisely the same exceptions as regular J2SE classes do. Consequently, a fairly comprehensive set of exception classes has been included. In contrast, as explained in Section 4.3.2, “Error-Handling Limitations,” the error-handling capabilities of CLDC are limited. By default, a virtual machine
CLASSES DERIVED FROM JAVA 2 STANDARD EDITION
conforming to CLDC is required to provide only the error classes listed below. (Class NoClassDefFoundError was added to the libraries in CLDC 1.1.) Error classes java.lang.Error java.lang.NoClassDefFoundError java.lang.OutOfMemoryError java.lang.VirtualMachineError
Exception classes java.lang.Exception java.lang.ArithmeticException java.lang.ArrayIndexOutOfBoundsException java.lang.ArrayStoreException java.lang.ClassCastException java.lang.ClassNotFoundException java.lang.IllegalAccessException java.lang.IllegalArgumentException java.lang.IllegalMonitorStateException java.lang.IllegalThreadStateException java.lang.IndexOutOfBoundsException java.lang.InstantiationException java.lang.InterruptedException java.lang.NegativeArraySizeException java.lang.NullPointerException java.lang.RuntimeException java.lang.NumberFormatException java.lang.SecurityException java.lang.StringIndexOutOfBoundsException java.util.EmptyStackException java.util.NoSuchElementException java.io.EOFException java.io.InterruptedIOException java.io.IOException java.io.UnsupportedEncodingException java.io.UTFDataFormatException
61
62
CHAPTER 5
5.2.8
CLDC LIBRARIES
Weak References
As of CLDC Specification version 1.1, the following classes are supported: java.lang.ref.Reference java.lang.ref.WeakReference
5.2.9
Internationalization Support
Character sets and character case conversion support A CLDC implementation is required to support Unicode characters. Character information is based on the Unicode Standard, version 3.0. However, since the full character case conversion tables required for Unicode support are excessively large for devices with tight memory budgets, by default the case conversion facilities in CLDC assume the presence of ISO Latin-1 range of characters only. More specifically, implementations must provide support for character properties and case conversions for characters in the “Basic Latin” and “Latin-1 Supplement” blocks of Unicode 3.0. Other Unicode character blocks may be supported as necessary. Character encodings CLDC includes limited support for the translation of Unicode characters to and from a sequence of bytes. In J2SE this is done using objects called Readers and Writers, and this same mechanism is utilized in CLDC using the InputStreamReader and OutputStreamWriter classes with identical constructors. new InputStreamReader(InputStream is); new InputStreamReader(InputStream is, String enc) throws UnsupportedEncodingException; new OutputStreamWriter(OutputStream os); new OutputStreamWriter(OutputStream os, String enc) throws UnsupportedEncodingException;
If the enc parameter is present, it is the name of the encoding to be used. Where it is not, a default encoding (defined by the system property microedition.encoding) is used. Additional converters may be provided by manufacturer-specific implementations of CLDC. If a converter for a certain encoding is not available, an UnsupportedEncodingException is thrown. For official information on character encodings in J2SE, refer to: http://java.sun.com/j2se/1.3/docs/guide/intl/encoding.doc.html.
CLASSES DERIVED FROM JAVA 2 STANDARD EDITION
No localization support Note that CLDC does not provide any localization features. All the solutions related to the formatting of dates, times, currencies and so on are assumed to be outside the scope of the CLDC Specification. 5.2.10 Property Support CLDC libraries do not include the java.util.Properties class familiar from Java 2 Standard Edition. In J2SE, that class is used for storing system properties such as the name of the host operating system, version number of the virtual machine and so on. In CLDC, a limited set of system properties described in Table 5.1 is available. These properties can be accessed by calling the method System.getProperty(String key). Table 5.1 Standard system properties Key
Explanation
Value
microedition.platform
Name of the host platform or device
(implementationdependent)
microedition.encoding
Default character encoding
“ISO-8859-1”
microedition.configuration
Name and version of the supported configuration
“CLDC-1.1”
microedition.profiles
Names of the supported profiles
(implementationdependent)
Property microedition.encoding describes the default character encoding name. This information is used by the system to find the correct class for the default character encoding for supporting internationalization. Property microedition.platform characterizes the host platform or device. Property microedition.configuration describes the current J2ME configuration and version, and property microedition.profiles defines a string containing the names of the supported profiles, separated by blanks. Note that the set of properties defined above can be extended by J2ME profile specifications or device manufacturers. For instance, the MIDP Specification defines additional properties not included in Table 5.1. The set of system properties defined by the Mobile Information Device Profile can be found in Section 20.2, “System Properties.”
63
64
CHAPTER 5
CLDC LIBRARIES
Manufacturer-specific property definitions are prefixed with the same package name that the manufacturer-specific classes use (such as “com.companyname.propertyname”). The “microedition” namespace, as well as the “java” and “javax” namespaces, are reserved and may only be extended by official J2ME configurations, profiles, or optional packages.
5.3
CLDC-Specific Classes
This section contains a description of the Generic Connection framework for supporting input/output and networking in a generalized, extensible fashion. The Generic Connection framework provides a coherent way to access and organize data in a resource-constrained environment. 5.3.1
Background and Motivation
The class libraries included in Java 2 Standard Edition and Java 2 Enterprise Edition provide a rich set of functionality for handling input and output access to storage and networking systems. For instance, in JDK 1.3.1, the package java.io contained 59 regular classes and interfaces, and 16 exception classes. The package java.net of JDK 1.3.1 consisted of 31 regular classes and interfaces, and 8 exception classes. It is difficult to make all this functionality fit in a small device with only a few hundred kilobytes of total memory budget. Furthermore, a significant part of the standard I/O and networking functionality is not directly applicable to today’s small devices, which often do not have TCP/IP support, or which commonly need to support specific types of connections such as Infrared or Bluetooth. In general, the requirements for the networking and storage libraries vary significantly from one resource-constrained device to another. For instance, device manufacturers who are dealing with packet-switched networks typically want datagram-based communication mechanisms, while those dealing with circuitswitched networks require stream-based connections. Due to strict memory limitations, manufacturers supporting certain kinds of networking capabilities generally do not want to support any other mechanisms. All this makes the design of the networking facilities for CLDC very challenging, especially since J2ME configurations are not allowed to define optional features. Also, the presence of multiple networking mechanisms and protocols is potentially very confusing to the application programmer, especially if the programmer has to deal with low-level protocol issues.
CLDC-SPECIFIC CLASSES
5.3.2
The Generic Connection Framework
The challenges presented above have led to the generalization of the J2SE networking and I/O classes. The high-level goal for this generalized design is to be a precise functional subset of J2SE classes, which can easily map to common low-level hardware or to any J2SE implementation, but with better extensibility, flexibility, and coherence in supporting new devices and protocols. The general idea is illustrated below. Instead of using a collection of different kinds of abstractions for different forms of communication, a set of related abstractions are used at the application programming level. General form Connector.open(":;");
Note: These examples are provided for illustration only. CLDC itself does not define any protocol implementations (see Section 5.3.3, “No Network Protocol Implementations Defined in CLDC”). It is not expected that a particular J2ME profile would provide support for all these kinds of connections. J2ME profiles may also support protocols not shown below.
HTTP Connector.open("http://www.sun.com");
Sockets Connector.open("socket://129.144.111.222:2800");
Communication ports Connector.open("comm:com0;baudrate=9600");
Datagrams Connector.open("datagram://129.144.111.222:2800");
All connections are created by calling the static method open of the class javax.microedition.io.Connector. If successful, this method will return an object that implements one of the javax.microedition.io.Connection interfaces
65
66
CHAPTER 5
CLDC LIBRARIES
shown in Figure 5.1. The Connector.open method takes a String parameter in the general form: Connector.open(":;");
Connection
StreamConnectionNotifier
InputConnection
OutputConnection
DatagramConnection
StreamConnection
ContentConnection
Figure 5.1
Connection interface hierarchy
The syntax of the Connector.open parameter strings should generally follow the Uniform Resource Indicator (URI) syntax as defined in the IETF standard RFC2396 (http://www.ietf.org/rfc/rfc2396.txt). A central objective of this design is to isolate, as much as possible, the differences between the use of one protocol and another into a string characterizing the type of connection. This string is the parameter to the method Connector.open. A key benefit of this approach is that the bulk of the application code stays the same regardless of the kind of connection that is used. This is different from traditional implementations in which the abstractions and data types used in applications often change dramatically when changing from one form of communication to another. The binding of protocols to a J2ME program is done at run time. At the implementation level, the string (up to the first occurrence of ‘:’) that is provided as the parameter to the method Connector.open instructs the system to obtain the desired protocol implementation from a location where all the protocol implementations are stored. It is this late binding mechanism that permits a program to dynamically adapt to use different protocols at run time. Conceptually this is identical to the relationship between application programs and device drivers on a personal computer or workstation. In order to read and write data to and from Generic Connections that have been opened using the Connector.open method, a number of input and output
CLDC-SPECIFIC CLASSES
stream classes are provided. The input and output stream classes supported by CLDC are listed in Section 5.2.4, “Input/Output Classes.” J2ME profiles may provide additional stream classes as necessary. 5.3.3
No Network Protocol Implementations Defined in CLDC
The Generic Connection framework included in CLDC does not specify the actual supported network protocols or mandate implementations of any specific networking protocols. The CLDC Specification provides an extensible framework that can be customized by J2ME profiles such as MIDP to support those protocols that specific device categories might need. The actual implementations and decisions regarding supported protocols must be made at the profile level. Refer to Chapter 15, “MIDP Networking and Serial Communications” and Chapter 16, “Secure Networking” for details on the MIDP networking libraries. Those chapters include a number of sample applications that illustrate the use of the Generic Connection framework. 5.3.4
Summary of the Generic Connection Interfaces
Connections to different types of devices will need to exhibit different forms of behavior. A file, for instance, can be renamed, but no similar operation exists for a TCP/IP socket. The Generic Connection framework reflects these different capabilities, ensuring that operations that are logically the same share the same API. The Generic Connection framework is implemented using a hierarchy of Connection interfaces (located in package javax.microedition.io) that group together classes of protocols with the same semantics. This hierarchy consists of seven interfaces shown earlier in Figure 5.1. Additionally, there is the Connector class, one exception class (ConnectionNotFoundException), one other interface, and a number of data stream classes for reading and writing data. At the implementation level, a minimum of one class is needed for implementing each supported protocol. Often, each protocol implementation class contains simply a number of wrapper functions that call the native functions of the underlying host operating system. There are six basic interface types that are addressed by the Generic Connection framework: • A basic serial input device • A basic serial output device • A datagram-oriented communications device
67
68
CHAPTER 5
CLDC LIBRARIES
• A circuit-oriented communications device • A notification mechanism to inform a server of client-server connections • A basic Web server connection The collection of Connection interfaces forms a hierarchy that becomes progressively more capable as the hierarchy progresses from the root Connection interface. This arrangement allows J2ME profile designers or application programmers to choose the optimal level of cross-protocol portability for the libraries and applications they are designing. The Connection interface hierarchy is illustrated in Figure 5.1. A brief summary of each interface class is provided below. For a definitive reference on the Connection interfaces, refer to the documentation that is provided as part of the CLDC reference implementation. Interface Connection This is the most basic connection type that can only be opened and closed. The open method is not included in the interface because connections are always opened using the static open method of the Connector class. Methods: public void close() throws IOException;
Interface InputConnection This connection type represents a device from which data can be read. The openInputStream method of this interface will return an InputStream for the connection. The openDataInputStream method of this interface will return a DataInputStream for the connection. Methods: public InputStream openInputStream() throws IOException; public DataInputStream openDataInputStream() throws IOException;
Interface OutputConnection This connection type represents a device to which data can be written. The openOutputStream method of this interface will return an OutputStream for the connection. The openDataOutputStream method of this interface will return a DataOutputStream for the connection.
CLDC-SPECIFIC CLASSES
Methods: public OutputStream openOutputStream() throws IOException; public DataOutputStream openDataOutputStream() throws IOException;
Interface StreamConnection This connection type combines the InputConnection and OutputConnection interfaces. It forms a logical starting point for classes that implement two-way communication interfaces. Interface ContentConnection This connection type is a sub-interface of StreamConnection. It provides access to some of the most basic metadata information provided by HTTP connections. Methods: public String getType(); public String getEncoding(); public long getLength();
Interface StreamConnectionNotifier This connection type is used when waiting for a connection to be established. The acceptAndOpen method of this interface will block until a client program makes a connection. The method returns a StreamConnection on which a communications link has been established. Like all connections, the returned StreamConnection must be closed when it is no longer needed. Methods: public StreamConnection acceptAndOpen() throws IOException;
Interface DatagramConnection This connection type represents a datagram endpoint. In common with the J2SE datagram interface, the address used for opening the connection is the endpoint at which datagrams are received. The destination for datagrams to be sent is placed in the datagram object itself. There is no address object in this API. Instead, a string is used that allows the addressing to be abstracted in a similar way as in the Connection interface design.
69
70
CHAPTER 5
CLDC LIBRARIES
Methods: public int getMaximumLength() throws IOException; public int getNominalLength() throws IOException; public void send(Datagram datagram) throws IOException; public void receive(Datagram datagram) throws IOException; public Datagram newDatagram(int size) throws IOException; public Datagram newDatagram(int size, String addr) throws IOException; public Datagram newDatagram(byte[] buf, int size) throws IOException; public Datagram newDatagram(byte[] buf, int size, String addr) throws IOException;
This DatagramConnection interface requires a data type called Datagram that is used to contain the data buffer and the address associated with it. The Datagram interface contains a useful set of access methods with which data can be placed into or extracted from the datagram buffer. These access methods conform to the DataInput and DataOutput interfaces, meaning that the datagram object also behaves like a stream. A current position is maintained in the datagram. This is automatically reset to the start of the datagram buffer after a read operation is performed. Refer to Chapter 15, “MIDP Networking and Serial Communications,” and Chapter 16, “Secure Networking,” for sample applications that illustrate the use of the Generic Connection framework and the interfaces listed above.
5.4
New for CLDC 1.1
The following list summarizes the Java library changes between CLDC Specification versions 1.0 and 1.1. For details, refer to “CLDC Almanac” on page 359. • Classes Float and Double have been added. • The following methods have been added to other library classes to handle floating point values: • • • • •
java.lang.Integer.doubleValue() java.lang.Integer.floatValue() java.lang.Long.doubleValue() java.lang.Long.floatValue() java.lang.Math.abs(double a)
NEW FOR CLDC 1.1
• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •
java.lang.Math.abs(float a) java.lang.Math.max(double a, double b) java.lang.Math.max(float a, float b) java.lang.Math.min(double a, double b) java.lang.Math.min(float a, float b) java.lang.Math.ceil(double a) java.lang.Math.floor(double a) java.lang.Math.sin(double a) java.lang.Math.cos(double a) java.lang.Math.tan(double a) java.lang.Math.sqrt(double a) java.lang.Math.toDegrees(double angrad) java.lang.Math.toRadians(double angrad) java.lang.String.valueOf(double d) java.lang.String.valueOf(float f) java.lang.StringBuffer.append(double d) java.lang.StringBuffer.append(float f) java.lang.StringBuffer.insert(int offset, double d) java.lang.StringBuffer.insert(int offset, float f) java.io.DataInput.readDouble() java.io.DataInput.readFloat() java.io.DataInputStream.readDouble() java.io.DataInputStream.readFloat() java.io.DataOutput.writeDouble(double v) java.io.DataOutput.writeFloat(float v) java.io.DataOutputStream.writeDouble(double v) java.io.DataOutputStream.writeFloat(float f) java.io.PrintStream.print(double d) java.io.PrintStream.print(float f) java.io.PrintStream.println(double d) java.io.PrintStream.println(float f) java.util.Random.nextDouble() java.util.Random.nextFloat()
• The following fields have been added to support floating point calculations: • java.lang.Math.E • java.lang.Math.PI
• Classes java.lang.ref.Reference and java.lang.ref.WeakReference have been added. • Classes java.util.Calendar, java.util.Date and java.util.TimeZone have been redesigned to be more J2SE-compliant by adding a number of fields and methods. • One new error class, NoClassDefFoundError, has been added. • Class Thread has the following new methods and constructors:
71
72
CHAPTER 5
• • • •
CLDC LIBRARIES
Thread.getName() Thread.interrupt() Thread(Runnable Target, String name) Thread(String name)
• In addition, the following fields and methods have been added: • • • • •
java.lang.Boolean.TRUE
and java.lang.Boolean.FALSE
java.lang.String.intern() java.lang.String.equalsIgnoreCase() java.util.Date.toString() java.util.Random.nextInt(int n)
C H A P T E R
6
Mobile Information Device Profile The Mobile Information Device Profile (MIDP) for the Java™ 2 Platform, Micro Edition (J2ME™) is an architecture and a set of Java libraries that create an open application environment for small, resource-constrained mobile information devices, or MIDs. Typical examples of MIDP target devices include cellular phones, two-way pagers, and wireless personal organizers. As summarized in Chapter 3, MIDP 2.0 devices typically fulfill the following minimum requirements: • Memory: ■
256 kilobytes of non-volatile memory for the MIDP components
■
8 kilobytes of non-volatile memory for application-created persistent data
■
128 kilobytes of volatile memory for the virtual machine runtime (for example, the object heap)
• Display: ■
Screen-size: 96x54
■
Display depth: 1-bit
■
Pixel shape (aspect ratio): approximately 1:1
• Input: ■
One or more of the following user-input mechanisms: • “one-handed keypad” • “two-handed keyboard” • touch screen
73
74
CHAPTER 6
MOBILE INFORMATION DEVICE PROFILE
• Networking: ■
Two-way, wireless, possibly intermittent, with limited bandwidth
• Sound: ■
The ability to play tones, either via dedicated hardware or via software algorithm
Note that since MIDP runs on top of the J2ME Connected Limited Device Configuration (CLDC), the memory requirements of CLDC must be added to the minimum numbers shown above.
6.1
MIDP Expert Groups
6.1.1
MIDP 1.0 Expert Group
The MIDP Specification version 1.0 was produced by the Mobile Information Device Profile Expert Group (MIDPEG) as part of the Java Community Process (JCP) standardization effort JSR 37. The following 22 companies, listed in alphabetical order, were members of the MIDP 1.0 standardization effort: • America Online
• DDI
• Ericsson
• Espial Group
• Fujitsu
• Hitachi
• J-Phone
• Matsushita
• Mitsubishi
• Motorola
• NEC
• Nokia
• NTT DoCoMo
• Palm Computing
• RIM
• Samsung
• Sharp
• Siemens
• Sony
• Sun Microsystems
• Symbian
• Telcordia Technologies
6.1.2
MIDP 2.0 Expert Group
The MIDP Specification version 2.0 was produced as part of the Java Community Process (JCP) standardization effort JSR 118. More than 120 people (the largest expert group ever created in the Java Community Process) were members of the MIDP 2.0 expert group.
MIDP EXPERT GROUPS
The expert group included people from the following 49 companies (alphabetical): • 4thpass Inc.
• AGEA Corporation
• Alcatel
• Aplix Corporation
• AromaSoft Corp
• Baltimore Technologies
• CELLon France
• Distributed Systems Technology Centre
• Elata PLC
• Esmertec
• Espial Group
• France Telecom / Orange
• Fujitsu Limited
• German Aerospace Center (DLR), Institute of Communications and Navigation
• Hitachi Ltd. / Digital Media Group
• In Fusio
• J-PhoneEast Co. Ltd
• Logical Mobile Networks
• Mitsubishi Electric Corp
• Mobile Scope AG
• Mobilitec
• Motorola
• NEC Corporation
• Nextel Communications
• Nokia
• NTT DoCoMo
• Omnitel Pronto Italia S.p.A
• One 2 One
• Openwave Systems Inc.
• Orange (UK)
• Palm
• Philips Consumer Communications
• Philips Semiconductors
• Research In Motion (RIM)
• Samsung Electronics Co., Ltd
• Sharp Labs
• Siemens AG
• Siemens ICM
• Smart Fusion
• Sony Ericsson Mobile Communications
• Sun Microsystems
• Symbian Ltd.
• Telefónica Móviles España
• Vaultus Inc.
• Veloxsoft Inc.
• Vodafone Global Platform & Internet Services
• Vodafone Group Services Limited
• Vodafone Multimedia
• Zucotto Wireless
75
76
CHAPTER 6
MOBILE INFORMATION DEVICE PROFILE
In addition, the following nine individuals were members of the MIDP 2.0 expert group: • Fabio Ciucci
• Wai Kit Tony Fung
• Neil Katin
• Glen Cordrey
• David Hook
• Steve Ma
• Jon Eaves
• Myank Jain
• Ravi Kumar Reddy
6.2
Areas Covered by the MIDP Specification
The Mobile Information Device Profile Specification extends the functionality defined by the Connected, Limited Device Configuration (CLDC) Specification. The MIDP Specification defines a set of APIs that add a minimum set of capabilities that are common to various kinds of mobile information devices. The MIDP Specification version 2.0 extends the capabilities of the original MIDP Specification version 1.0 while retaining full backward compatibility. As already summarized earlier in Section 3.5.2, “Scope of MIDP,” the specific areas covered by the MIDP Specification version 2.0 include: • application model (that is, defining the semantics of a MIDP application and how the application is controlled), • user interface support (Limited Capability Device User Interface, LCDUI), • networking support (based on the HTTP protocol and the Generic Connection framework introduced by CLDC), • persistent storage support (Record Management System, RMS), • sounds, • 2D games, • end-to-end security through HTTPS and secure sockets, • MIDlet signing model for added security, • application delivery and installation, and • miscellaneous classes such as timers and exceptions. In addition to these areas, the MIDP Specification defines an extension of the CLDC application model that allows for the execution and communication of applications called MIDlets. A MIDlet is the basic unit of execution in MIDP. One
AREAS COVERED BY THE MIDP SPECIFICATION
or more MIDlets packaged together are called a MIDlet suite. The MIDP application model and each of the areas mentioned above are discussed in detail in the subsequent chapters of this book. The concept of a MIDlet suite is discussed in detail in Section 19.1, “MIDlet Suites.”
77
This page intentionally left blank
C H A P T E R
7
MIDP Application Model Due to the strict memory constraints and the requirement to support application interaction and data sharing within related applications, the Mobile Information Device Profile does not support the familiar Applet programming model introduced by the Java™ 2 Platform, Standard Edition (J2SE™). Rather, MIDP introduces a new application model that is better suited for the specific needs of small, resourceconstrained devices. This application model is integrated closely with the MIDP user interface libraries (see Chapters 8–11), and it replaces the simple, command line-oriented application model supported by the Connected, Limited Device Configuration.
7.1
MIDlets
In MIDP, the basic unit of execution is a MIDlet. A MIDlet is a class that extends the class javax.microedition.midlet.MIDlet and implements a few methods—including startApp, pauseApp, and destroyApp—to define the key behavior of the application. As an example of programming with the MIDP application model, consider the following program that implements one of the simplest MIDlets possible: the canonical “Hello World” application. package examples; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class HelloWorld extends MIDlet implements CommandListener { private Command exitCommand; private TextBox tb;
79
80
CHAPTER 7
MIDP APPLICATION MODEL
// Constructor of the HelloWorld class public HelloWorld() { // Create “Exit” Command so the user can exit the MIDlet exitCommand = new Command("Exit", Command.EXIT, 1); // Create TextBox in which the output will be displayed tb = new TextBox("Hello MIDlet", "Hello, World!", 15, 0); // Add the Command and set the CommandListener tb.addCommand(exitCommand); tb.setCommandListener(this); // Set our TextBox as the current screen Display.getDisplay(this).setCurrent(tb); } // Called by the system when the MIDlet is started // for the first time, and when it is resumed after // being paused. protected void startApp() {} // Called by the system when the MIDlet is paused. // In this application, there is no need to do anything // when we are paused. protected void pauseApp() {} // Called when the MIDlet is destroyed.
In this case,
// there is no need to do anything when we are destroyed. protected void destroyApp(boolean force) {} // This method is called automatically by the system // in response to a user activating one of the Commands. public void commandAction(Command c, Displayable d) { // Upon receiving the “Exit” Command, destroy ourselves if (c == exitCommand) { destroyApp(false); notifyDestroyed(); } } }
MIDLETS
The output of this simple MIDlet, when run on a MIDP device emulator, is shown in the figure on the right. In the figure, the MIDlet’s startApp method has just completed its execution. Pressing the “Exit” button on the phone’s keypad would trigger the delivery of the exitCommand to the commandAction method which invokes the destroyApp and notifyDestroyed methods. In this example, there are a few key things that are common to all MIDlets, no matter how simple or complex the applications are. First, HelloWorld extends the class javax.microedition.midlet.MIDlet. Second, like every Java class, a MIDlet can have a constructor. In the MIDP application model, the system (see Section 19.2, “MIDP System Software”) calls the no-argument constructor of a MIDlet exactly once to instantiate the MIDlet. The functions that need to be performed in the constructor depends on how the MIDlet is written, but in general, any operations that must be performed only once when the application is launched should be placed in the constructor. If no such functionality is required by the MIDlet, then there is no need to provide a constructor. Care should be taken in the constructor to catch any exceptions and handle them gracefully because an uncaught exception will prevent the MIDlet from being created and the application will not be able to run. Third, the application’s MIDlet class must implement the abstract lifecycle methods of class javax.microedition.midlet.MIDlet so the application can respond to state changes. These methods are: startApp, pauseApp, and destroyApp. The startApp method is used for starting or restarting a MIDlet. The pauseApp method is called by the system to ask a MIDlet to “pause.” The destroyApp method is called by the system when the MIDlet is about to be destroyed; it can also be called indirectly by the MIDlet itself in order to clean up before exiting. Taken as a whole, the startApp, pauseApp, and destroyApp methods represent a state machine that controls the life cycle of the MIDlet. This life cycle, as well as the recommended practices for defining the startApp, pauseApp, and destroyApp methods, are described in more detail in Section 7.1.1, “MIDlet States.” Fourth, the application also implements the CommandListener interface (see method CommandAction) so that the application can respond to user actions. This interface, along with the TextBox, Command, and Display classes, is part of the javax.microedition.lcdui package that will be discussed in detail later in this book.
81
82
CHAPTER 7
7.1.1
MIDP APPLICATION MODEL
MIDlet States
MIDlets have a well-defined life cycle. A MIDlet is typically started (for example, when the user launches it from a screen of applications available to be run), it interacts with the user through its graphical user interface, and is then stopped (for example, when the user chooses a button labelled “Exit”).
new HelloWorld() pauseApp
Active
Paused
startApp
destroyApp
destroyApp
Destroyed
Figure 7.1
MIDlet states and state transitions
In general, during the lifetime of a MIDlet, it may be in one of three distinct states, with well-defined rules that govern the transitions between these states (see Figure 7.1): • Paused: A MIDlet is in the Paused state when it has just been constructed and has not yet entered its startApp method. It can also be in the Paused state as a result of the pauseApp or the notifyPaused methods (see below). When in the Paused state, a MIDlet should hold as few resources as possible. A MIDlet in the Paused state can receive asynchronous notifications, for example, from a timer firing (see Section 20.1, “Timer Support”). • Active: A MIDlet is in the Active state upon entry to its startApp method. In addition, a MIDlet can transition from the Paused state to the Active state as the result of the resumeRequest method. While in the Active state, a MIDlet can
MIDLETS
allocate and hold all necessary resources for optimal execution. • Destroyed: A MIDlet is in the Destroyed state when it has returned from the destroyApp or notifyDestroyed methods. Once a MIDlet enters the Destroyed state, it cannot reenter any other state. The Destroyed state replaces the normal convention of an application calling the System.exit method to terminate. A MIDlet cannot call the System.exit method, since doing so will throw a java.lang.SecurityException (see Section 20.4, “Exiting a MIDlet.”) The MIDlet state transitions can be triggered either by the MIDP system itself or by requests from the application. Below we summarize how the MIDP system initiates these state transitions by calling methods on the MIDlet. Note that with the exception of startApp, which completes the state change to Active upon the origination of the call, all other state changes complete after the associated methods return to the caller. The MIDlet’s constructor is invoked to create an instance of the MIDlet. A MIDlet is in the Paused state when it has just been constructed and has not yet entered its startApp method. If defined, a constructor must be public or protected and have no arguments. The MIDP system calls the constructor exactly once to instantiate the MIDlet. (See Section 19.2, “MIDP System Software” for an explanation of the MIDP system.) In general, MIDlet programmers should use the constructor for any initialization operations that must be performed only once and can be performed when the application is launched. If a MIDlet has no such operations, then the MIDlet programmer need not provide a constructor. The initialization done within the constructor should be brief. Lengthy delays caused by long operations such as network access should be performed in the background or delayed until the user can be informed appropriately. The startApp method is called by the system to move a MIDlet into the Active state for the first time and also when a MIDlet is being resumed from the Paused state. When a MIDlet enters its startApp method, it is in the Active state. An important note: Beginning MIDlet programmers are often tempted to treat startApp as equivalent to the main method, and thus combine MIDlet initialization and main-line processing in the startApp method. In general this is not a good idea, since the startApp method may be called more than once: one time initially, and then once per each transition from Paused to Active state. The pauseApp method is called to move the MIDlet into the Paused state. During the normal operation of a mobile device, the system might run into situations where it is necessary to suspend or pause some of the MIDlets on the device. The most common example is when a device is running low on memory. In order to reclaim memory, the system may call the pauseApp method of all the Active
83
84
CHAPTER 7
MIDP APPLICATION MODEL
MIDlets. When the pauseApp method of a MIDlet is called, the MIDlet should release as much of its resources as possible and become quiescent. Note that the system does not actually try to force any specific behavior on a MIDlet in a Paused state, so it is possible for an ill-behaved MIDlet to ignore this request. However, if such a situation occurs, the system may forcibly terminate the MIDlet or even the virtual machine itself, especially in a low-memory situation. The destroyApp method is the normal way the system terminates a MIDlet. The destroyApp method has one boolean parameter that indicates whether or not the request is unconditional. If the request is not unconditional (that is, the boolean parameter is false), then the MIDlet may request a “stay of execution” by throwing a MIDletStateChangeException. In this case, if the system is able to honor the request, the MIDlet may continue in its current state (Paused or Active). If, on the other hand, the request is unconditional, then the MIDlet should give up its resources, save any persistent data it might be caching, and return. Upon normal return from this method, the MIDlet enters the Destroyed state and can be reclaimed by the system. While the MIDP system is the primary instigator of MIDlet state changes, a MIDlet application programmer can also request state changes using the resumeRequest, notifyPaused, and notifyDestroyed methods in the MIDlet class. The resumeRequest method can be called by a Paused MIDlet to indicate that it wishes to reenter the Active state. The primary scenario for this call is when a Paused MIDlet handles a timer expiration and needs to resume processing. The notifyPaused method is provided to allow a MIDlet to signal to the system that it has voluntarily entered the Paused state (that is, it has released its resources and is now quiescent). An example use case for this call is a time-based MIDlet that sets timers and has nothing to do until those timers expire. The notifyDestroyed method can be called by the MIDlet to tell the system that the MIDlet has released all its resources and has saved any cached data to persistent storage. Note that the destroyApp method of a MIDlet will not be called by the system as a result of invoking this method. The MIDlet may reasonably call destroyApp itself to do the same cleanup as if the system called it. 7.1.2
Using the startApp, pauseApp, and destroyApp Methods
Using the startApp method The startApp method is used for starting or restarting a MIDlet. This method may be called by the system under different circumstances (see Section 7.1.1, “MIDlet States”), but its purpose is to acquire or reacquire resources needed by the MIDlet and to prepare the MIDlet to handle events such as user input and timers. Note that
MIDLETS
the startApp method may be called more than once—once to start execution for the first time and again for every time the MIDlet is “resumed”; therefore, a startApp method should be written so that it can be called under these different circumstances. The startApp method can “fail” in two ways: with a transient failure or a nontransient failure. A transient failure is one that might have to do with a certain point in time (such as a lack of resources, network connectivity, and so forth). Since this type of error may not be fatal, a MIDlet can tell the system that it would like to try to initialize later by throwing a javax.microedition.midlet.MIDletStateChangeException. A non-transient failure is one that is caused by any other unexpected and uncaught runtime error. In this case, if the runtime error is not caught by the startApp method, it is propagated back to the system that will destroy the MIDlet immediately and call the MIDlet’s destroyApp method. A robust startApp method should distinguish between transient and nontransient exceptions and respond accordingly, as illustrated in the following code fragment: void startApp() throws MIDletStateChangeException { CommConnection port = null; try { port = (CommConnection)Connector.open(...); ... } catch (IOException ioe) { // Transient failure: could not connect to the serial port throw new MIDletStateChangeException( "Serial port not available"); } catch (Exception e) { // Non-transient failure: can either catch this and // exit here, or let the exception propagate back to // the system destroyApp(true); notifyDestroyed(); } }
Using the pauseApp method The pauseApp method is called by the system to ask a MIDlet to “pause.” The definition of what pause means is discussed in Section 7.1.1, “MIDlet States,” but in general, the pauseApp method works in conjunction with the startApp method to release as many resources as possible so that there is more memory and/or resources
85
86
CHAPTER 7
MIDP APPLICATION MODEL
available to other MIDlets or native applications. The use of the pauseApp method is illustrated in the following code fragment: int[] runTimeArray = null; void startApp() { // Coming from a paused state; initialize data runTimeArray = new int[200]; ... } void pauseApp() { // Set runTimeArray to null so that it is // a candidate for garbage collection runTimeArray = null; ... }
Using the destroyApp method The last method that a MIDlet must implement is the destroyApp method. This method is called by the system when the MIDlet is about to be destroyed; it can also be called indirectly by the MIDlet itself in order to clean up before exiting. In either case, the destroyApp method should be written so that it performs all the necessary cleanup operations to release all the resources (that is, close the graphical user interface components, network connections, and database records) that the application had allocated during its execution. The following code fragment provides a simple example: RecordStore rs = null; void startApp() { ... rs = RecordStore.openRecordStore(...); ... } void destroyApp(boolean force) { if (rs != null) { // Make sure all records are written to storage // and close the record store ... } }
MIDLETS
7.1.3
Application Lifecycle and the User Interface API
Since the user interface components play a key role in a MIDP application, the initialization of the user interface components is one of the first tasks for the application when a MIDlet is instantiated. The application management software of a MIDP system assumes that the application is well-behaved with respect to the MIDlet events. The paragraphs below summarize what a well-behaved MIDlet is expected to do when each of its lifecycle methods is called. The constructor initializes the application state. The method can access the Display for the MIDlet by calling the Display.getDisplay method. It can create screens and objects needed when the application is started. It does not have access to the user interface, so information or alerts cannot be shown. The method can set the first screen to be shown to the user. The initialization performed should be brief; lengthy delays caused by long operations such as network access should be performed in the background or delayed until the user can be informed appropriately. The application manager calls the startApp method to notify the MIDlet that it has been started (or resumed after being paused) and makes the screen set with Display.setCurrent visible when startApp returns. Note that startApp can be called several times if pauseApp is called in between. This means that objects or resources freed by pauseApp might need to be recreated. When the pauseApp method is called the application should release any unneeded resources that can be re-initialized if the application is restarted. The application should pause its threads unless they are needed for background activities. Also, if the application should restart with another screen when the application is reactivated, the new screen should be set with Display.setCurrent. Since CLDC does not provide guaranteed real-time behavior, the system is not required to use the Paused state to manage the interaction of the real-time portions of the phone and the Java environment. Consider, for example, the case where the virtual machine is running on a cellular phone, and the phone receives a call. In this scenario, the real-time operating system on the phone might suspend the virtual machine altogether rather than cycle the MIDlets to the Paused state. When the destroyApp method is called the application’s user interface will no longer be displayed. Still, the application should close all active resources, stop any active threads, and unregister or free any objects that would not be freed by a normal garbage collection cycle.
87
88
CHAPTER 7
7.2
MIDP APPLICATION MODEL
MIDlet Suites
When MIDlets are delivered to devices for execution, they are packaged in a MIDlet suite. MIDlet suites provide a controlled way of downloading multiple MIDlets onto a device as well as support controlled sharing of data and resources between multiple, possibly simultaneously running MIDlets. MIDlet suites will be discussed in detail in Chapter 19, “MIDlet Deployment.”
7.3
New for MIDP 2.0
The MIDP application model has not changed since MIDP 1.0. However, the interactions with the user interface and the suggested application actions that are performed in these methods are now more precisely defined. By limiting the complexity of functions performed in these methods, the application can be more responsive to both system requests and user actions.
C H A P T E R
8
MIDP User Interface Libraries In light of the wide variations in cellular phones and other MIDP target devices, the requirements for user interface support are very challenging. MIDP target devices differ from desktop systems in many ways, especially in how the user interacts with them. The following UI-related requirements were seen as important when the user interface library of the MIDP Specification was designed: • The devices and applications should be useful to users who are not necessarily experts in using computers. • The devices and applications should be useful in situations where the user cannot pay full attention to the application. For example, many cellular phones and other wireless devices are commonly operated with one hand while the user is walking, cooking, fishing, and so forth. • The form factors and user interface concepts of MIDP target devices vary considerably between devices, especially compared to desktop systems. For example, display sizes are much smaller, and input devices are much more limited or at least different. Most mobile devices have only numeric keypads, and few have pointing devices such as pen-operated touch screens. • The Java applications for mobile information devices should have user interfaces that are consistent with the native applications so that the user finds them intuitive to use. Given these requirements and the capabilities of devices that implement the MIDP (see Section 3.2, “Target Devices”), a dedicated user interface toolkit is provided in MIDP in the javax.microedition.lcdui package. 89
90
CHAPTER 8
8.1
MIDP USER INTERFACE LIBRARIES
MIDP UI Compared to Desktop AWT
The differences between mobile devices and desktop computers are evident when comparing the designs of the MIDP lcdui with the Abstract Windowing Toolkit (AWT) of the JavaTM 2 Platform, Standard Edition. AWT was designed and optimized for desktop computers. The assumptions that are appropriate for desktop computers are not appropriate for mobile devices. For example, when a user interacts with AWT, event objects are created dynamically. These objects are short-lived and exist only until each associated event is processed by the system. The event object then becomes garbage and must be reclaimed by the garbage collector of the Java virtual machine. The limited CPU and memory subsystems of a mobile information device (MID) typically cannot afford the overhead of unnecessary garbage objects. To limit the creation of such objects, lcdui events are simply method calls that pass the event parameters directly as the parameters of the method. AWT also assumes certain desktop environment specific user interaction models. For instance, the component set of AWT was designed to work with a pointing device such as a mouse or pen. As mentioned earlier, this assumption is valid only for a small subset of MIDs, since most of the MIDP target devices have just a keypad for user input. The MIDP user interface API uses a layer of abstraction to separate applications from concrete input methods used in different devices. For example, a MIDP device with touch input allows the user to use this input method on high-level user interface components but it is not visible to applications. The different concrete input methods are transparent to the application code. AWT has extensive support for window management, such as overlapping windows, window resizing, and so forth. In contrast, MIDP target devices have small displays that are not large enough for multiple overlapping windows. The lcdui API of MIDP has no window management capabilities. A lcdui user interface is constructed using a set of Displayables. This displayable model and the class structure of user interface are described in the next section.
8.2
Structure of the MIDP User Interface API
The following sections provide an overview to the MIDP user interface API (javax.microedition.lcdui). The remainder of this chapter and the following two chapters concentrate on the high-level parts of the API. The low-level user interface API features are detailed in Chapter 11, “MIDP Low-Level User Interface Libraries.”
STRUCTURE OF THE MIDP USER INTERFACE API
The separation of high-level and low-level API is often not very clear-cut. There are many classes that are used both in low-level and high-level APIs. For example, classes Image and Font are used both in high-level Screen components and low-level graphics drawing. Also, in MIDP 2.0 the new CustomItem class makes it possible to mix low-level graphics and high-level components within a Form object. MIDP 2.0 also includes a new game-specific API provided in javax.microedition.lcdui.game package. The MIDP 2.0 Game API is discussed in Chapter 12. 8.2.1
Displayable Model
The central abstraction of the MIDP user interface is class Displayable. Class Displayable helps organize the user interface into manageable pieces. This results in user interfaces that are easy to use and learn. Each MIDP application has a Display on which a single Displayable object is shown. The application sets and resets the current Displayable object on the Display for each step of the task, based on user interactions. The user tasks (interactions with the user interface) are implemented using Command objects. The application is notified automatically when a Command is selected by the user. As a result of these notifications the application often changes the current Displayable to some other Displayable. The device software manages the sharing of the physical display between the native applications and the MIDP applications. The rationale behind the displayable-oriented approach is based on the wide variations in display and keypad configurations found in MIDP devices. Each device provides a consistent look and feel by handling the component layout, painting, scrolling, and focus traversal. If an application needed to be aware of these details, portability would be difficult to achieve, and smooth integration with the look and feel of the device and its native applications would place a heavy burden on application developers. There is a hierarchy of Displayable subclasses called Screens in the lcdui API. Each Screen is a functional user interface element that encapsulates devicespecific graphics rendering and user input handling. Figure 8.1 shows the hierarchy of the user interface classes.
91
92
CHAPTER 8
MIDP USER INTERFACE LIBRARIES
javax.microedition.lcdui Display Screen
StringItem List
ImageItem
TextBox
TextField
Alert
DateField
Form
Gauge
0..1
Displayable Canvas
ChoiceGroup
0..n
0..n
Command
Item
Spacer CustomItem
GameCanvas
LayerManager
0..n
Sprite
Layer javax.microedition.lcdui.game
Figure 8.1
TiledLayer
MIDP user interface class hierarchy (all classes not shown)
There are two types of Displayable subclasses: •
Canvas: low-level objects that allow the application to provide the graphics and
handle input •
Screen:
high-level objects that encapsulate complete user interface components (classes Alert, List, TextBox, or Form)
Any application may use combinations of Screens and Canvases to present an integrated user interface. For instance, in a game application, Lists and Forms can be used to select or configure the options of a game, while Canvas (or GameCanvas) can be used for the interactive game components. The Command class is used for implementing the application specific operations. For example, the navigation between different application Displayables is implemented using Commands. Details of Commands are described in Section 8.5, “Commands.”
STRUCTURE OF THE MIDP USER INTERFACE API
8.2.2
Low-Level User Interface
The low-level user interface API for Canvas is designed for applications that need precise placement and control of graphic elements as well as access to low-level input events. Typical examples are a game board, a chart object, or a graph. Using the low-level user interface API, an application can • control what is drawn on the display, • handle primitive events such as key presses and releases, and • access concrete keys and other input devices. Applications that are programmed with the low-level API can be portable if the application uses only the standard features; applications should stick to the platform-independent part of the low-level API whenever possible. This means that the applications should not directly assume the presence of any keys other than those defined in class Canvas. Also, applications should inquire about the size of the display and its color capabilities and adjust behavior accordingly. See Section 8.6.2, “Adaptation to Device-Specific User Interface Style.” The CustomItem class allows the application developer to use low-level graphics on a Form. CustomItem provides a way to mix both low-level and high-level components within a single Form. Painting using the CustomItem class is done similarly to painting to Canvas via the Graphics class. The low-level API is described in detail in Chapter 11, “MIDP Low-Level User Interface Libraries,” and in Chapter 12, “MIDP Game API.” 8.2.3
High-Level User Interface
The high-level user interface API is designed for business applications whose client components run on mobile information devices. For these applications, portability across devices is important. To achieve such portability, the high-level user interface API employs a high level of abstraction and provides very little control over look and feel. This allows devices to use the native user interface look and feel for the high-level MIDP user interface API components. This means that when an application is written with the high-level API, its look and feel automatically uses the look and feel of the device in which the application is currently running. For the end users this provides seamless user interaction: the MIDP application works the same way as the other (native) applications on the device. The high-level user interface components described in this section behave consistently with the in-built user interfaces and applications of a device. More specifically, when using the high-level API:
93
94
CHAPTER 8
MIDP USER INTERFACE LIBRARIES
• Drawing to the display is performed by the device’s system software. Applications do not define the visual appearance (such as shape, color, and so forth) of the components. • Navigation, scrolling, and other primitive interactions with the user interface components are performed by the device. The application is not aware of these interactions. • Applications cannot access concrete input mechanisms, such as individual keys. The high-level API is provided through the Screen classes, which are: •
List:
•
TextBox:
•
Alert:
•
Form:
allows a selection from a predefined set of choices. is a plain text editor with controllable editing modes.
displays temporary messages or simple choice queries.
is a more generic container that allows to display multiple, closely-related user interface elements called Items.
These different Screen classes are more thoroughly presented in Chapter 9, “MIDP High-Level User Interface – Screen.” The class Form is defined for cases where a screen with a single function is not sufficient. Class Form is designed to contain a small number of closely related user interface elements, or Items. For example, an application might have two TextFields, or a TextField and a simple ChoiceGroup. If all the Items of a Form do not fit on the screen, the implementation might make the Form scrollable, expand each Item automatically when the user edits it, or use a “pop up” representation. Each Form can contain a combination of the following Item subclasses: •
StringItem,
•
ImageItem,
used for static image display, or as an image button or hyperlink.
•
TextField,
used for textual input with constraints.
•
DateField,
used for display or input of time and date values.
•
Gauge, used as a progress indicator or as a numeric input from a specific range.
•
ChoiceGroup,
•
CustomItem
•
Spacer
used for static text display, or as a button or hyperlink.
used for single or multiple selections from a set of elements.
(MIDP 2.0), used to create application specific items; drawing is done with low-level Graphics API. (MIDP 2.0), used to create empty spaces for layout purposes.
DISPLAY
Although the Form class allows the creation of arbitrary combinations of components, developers should keep in mind the limited display size and make Forms simple and functional. Chapter 10, “MIDP High-Level User Interface – Form” discusses the various Form classes in detail.
8.3
Display
The Display class is the central controller of the display of a MIDP application. An application gets a Display instance by calling the static method getDisplay and by passing the MIDlet instance to the method: Display midletDisplay = Display.getDisplay(myMIDlet);
When the Display instance is obtained, the application can change the Displayables presented on the device using the methods of the Display class. There are three methods in class Display that allow the application to set the current Displayable instance presented on the device display. The most commonly used method is: public void setCurrent(Displayable nextDisplayable)
The two other methods are provided for more specialized use: public void setCurrent(Alert alert, Displayable nextDisplayable) public void setCurrentItem(Item item)
The first of these specialized methods sets an Alert to be displayed and also provides the Displayable that is presented after the Alert is dismissed. See Section 9.3, “Alert.” The second of these specialized methods presents a specific Item attached to a Form instance. The Form that has the Item is set as the current displayable, and it is scrolled so that the Item becomes visible. Focus, if supported by device, moves to this Item.
95
96
CHAPTER 8
8.3.1
MIDP USER INTERFACE LIBRARIES
Current Displayable
Technically, the methods just discussed set only the current displayable of class Display. During the lifecycle of the application the current Displayable never again is null after it has been initially set at application startup. The current Displayable is made visible by the device software referred to as application management software (AMS) in MIDP Specification (see Section 19.2, “MIDP System Software.”) The current Displayable is visible when the application is in the foreground. There often are, however, situations when the application management software moves the application to the background, and thus the current Displayable is not actually visible. The current Displayable does not change in these cases. Applications are commonly moved to background upon system events such as incoming calls in a phone device or upon certain other system notifications. When the application management software decides that the application can again be brought to the foreground, the current Displayable is simply made visible. The application can determine whether a Displayable is visible on the display by calling the method isShown. In the case of Canvas and CustomItem, the showNotify and hideNotify methods are called when the component is made visible and is hidden, respectively. Applications need to override showNotify and hideNotify methods in Canvas or CustomItem subclasses to be able receive these notifications. Some devices may have the capability to run multiple applications simultaneously. If multiple applications are actually running simultaneously, some of the applications are in background. For such devices there is a feature in class Display that allows the application to request to be sent to background. The method call setCurrent(null) does not set the current Displayable to null, but instead does the background request and the current Displayable remains unchanged. It should be noted that in many devices this request is simply ignored, but those that can support background applications may move the application to the background. The application management software decides which application should be presented if this request is honored. Similarly, for background applications, any non-null call to setCurrent methods is treated as a request to return the application to the foreground. Conversely, since the current Displayable is unchanged when an application is in the background, the method call d.setCurrent(d.getCurrent()) can be used to request a return to the foreground without changing the Displayable.
DISPLAYABLES
8.3.2
Screen Backlight and Device Vibrator
In MIDP 2.0, class Display has methods to control the screen backlight and vibrator often found in mobile devices: public boolean vibrate(int duration) public boolean flashBacklight(int duration)
Both methods take a parameter that indicates the duration of the action in milliseconds. These methods work only if there is a controllable backlight and vibrator present in a device. The methods return false if no such feature is available. Applications should use these methods with care, as they both consume battery significantly and may be irritating to some users or in specific situations. Devices commonly also have general native settings for turning off these features, in which case the methods also return false. The Display class also includes methods for retrieving some device properties, such as the color capabilities of the device. See Section 8.6.2, “Adaptation to Device-Specific User Interface Style,” for a more detailed discussion of these methods.
8.4
Displayables
objects are the views in which the application interaction takes place. Application-defined operations in Displayable objects are implemented using Commands. The device implementation provides additional operations based on displayable type, as will be discussed in Section 8.6.3, “Device-Provided Operations.” All Displayable objects have the following properties: Displayable
• Zero or more Commands for application specific user operations on the Displayable
• A CommandListener (set by the application with the method setCommand1 Listener ) that gets notified when the user selects any of the Commands • A title2 string (set with the setTitle method) that is presented to the user in a standard place, for example, as a header text for the Displayable • A Ticker object (set with the setTicker method) that provides automatically scrolling text attached to the Displayable 1.
Note that only a single CommandListener can be added because of the unicast listener model is used in the lcdui API. 2. In MIDP Specification version 2.0, the title and Ticker properties were added to class Displayable, which means that they are also available in class Canvas. In MIDP 1.0, these properties were only available in the Screen classes.
97
98
CHAPTER 8
MIDP USER INTERFACE LIBRARIES
Both the title and Ticker can be null, which means that no title text or Ticker is displayed. Depending on the user interface implementation of the device, the existence of a Ticker or title can consume space from the rest of the displayable content. The application is responsible for providing the means for the user to progress through different Displayables. The transition from one Displayable to another is performed using the Commands that the application has added to the current Displayable. When user selects a command, the command listener of the Displayable is activated. The listener typically changes the Displayable by calling the method setCurrent of class Display. A badly behaving application might set up a Displayable that has no Commands. This is allowed by the API, but is generally not useful. If this occurs, the user would have no means to move to another screen. Often a device provides the means for the user to request the application manager to kill such an erroneous application. An application can also implement Displayable changes in Canvas as actions resulting from low-level events, such as key events. In addition, nothing prevents an application from automatically changing its Displayable, for example, using a timer or thread. A possible scenario for such usage is when an application wants to continue its execution from a progress bar view3 after a long network transaction has finished. Generally these types of automatic displayable changes should be used with care. Displayable classes that form the high-level API are called Screens. The use of different Screens is described in Chapter 9, “MIDP High-Level User Interface – Screen.” The Canvas class is the main displayable on graphic-intensive applications such as games. Canvas is also used for custom components when high-level Screen classes do not provide the necessary components. For example, a data grid or table could be implemented using the Canvas low-level drawing primitives. (See Section 11.5, “Drawing Primitives.”)
3.
This kind of a view could be implemented, e.g., using an Alert (MIDP 2.0 only) or Form with a non-interactive Gauge item. These user interface structures are discussed later.
DISPLAYABLES
8.4.1 Ticker
The Ticker class implements a “ticker-tape,” a piece of text that runs continuously across the display. The direction and speed of scrolling are determined by the device. The ticker string scrolls continuously; that is, when the string finishes scrolling off the display, the ticker string starts over at the beginning of the string. There is no API provided for starting and stopping the Ticker. Rather, the application model is that the Ticker is always scrolling continuously. A Ticker can be added to any instance of Displayable with the method addTicker, and it can be removed with the method setTicker(null). Applications should not use Ticker on Alert screens because some devices present Alerts as pop-up dialogs that may not have space for the Ticker. The same Ticker may be shared by several Displayable objects. Setting a Ticker often affects the size of the area available for contents of Displayable. For example, fewer elements may be visible on a List. This change in content size is especially important to note when a Ticker is used in a Canvas. If the available area changes, the application is notified via a call to the sizeChanged method. Also, the getHeight and getWidth methods of class Canvas report smaller sizes. In a typical usage scenario, an application uses the same Ticker on all of its Displayables. When the application switches between two Displayables that have the same Ticker, the desirable consequence is for the Ticker to be displayed at the same location on the display and to continue scrolling its contents at the same position. This gives the illusion of the Ticker being attached to the display instead of separately to each Displayable. Nothing prevents an application from using different Tickers on different sets of Displayables, or even a different one on each Displayable. For example, a Ticker can be added to a List and the Ticker can be running while the List is being presented. Ticker ticker = new Ticker( "Special offer! Apples only” + “ two gold coins per box."); List list = new List("", List.IMPLICIT); ... // Add choices to the List // and set command listener list.addCommand(okCommand); list.addCommand(backCommand); list.setTicker(ticker); display.setCurrent(list);
99
100
CHAPTER 8
8.5
MIDP USER INTERFACE LIBRARIES
Commands
Abstract Commands are the operations that the applications add to the user interface. Commands can be added to all Displayables, so they are part of the application when using both high-level or low-level API. The most common task for Commands is to provide users with a way to navigate between different Displayables of an application. Normally, if there are no Commands in a Displayable, the user has no way to proceed to other Displayables. Commands are added to a Displayable using addCommand method. There is also removeCommand to remove already-added commands. This allows to dynamically change available operations within displayables. When the user selects a Command from the user interface, the device calls the CommandListener’s commandAction method and passes the Command object and the Displayable instance in which the Command was activated. In the next sections, the idea of Command abstraction is described first. Then the proper use of Commands in applications is summarized. 8.5.1
Command Mapping to Device User Interface
Since the MIDP user interface API is highly abstract, it does not dictate any concrete user interaction technique such as softkeys,4 buttons, or menus. An abstract command mechanism allows an application to adjust to the widely varying input mechanisms of MIDP target devices and also allows it to be unaware of device specifics, such as number of keys, key locations, and key bindings. Low-level user interactions such as traversal or scrolling are not visible to the application, which helps the devices implement the high-level components in very different user interface styles. This also leverages application portability between devices. MIDP applications define Commands, and the implementation can provide user control over these with softkeys, buttons, menus, or whatever mechanisms are appropriate for the device. Generally, Commands may be implemented using any user interface construct that has the semantics for activating a single action. Commands are added to a Displayable (Canvas or Screen) with the method addCommand of class Displayable. The Commands can also be removed with the removeCommand method. This allows, for example, the application to control which Commands are available at a given time, based on user interaction. Some Commands can be paired with others or presented only in certain situations or context.
4.
Softkeys are very common in mobile devices. Softkey is a keypad key positioned near the device display so that there is an changeable label present on the display that indicates the operation associated with the softkey.
COMMANDS
Each command has a type and a priority. Command types and priorities allow the device to place the commands to match the native user interface style of the device, and the device might put certain types of commands in standard places. For example, the “Go back” operation might always be mapped to the right softkey in a user interface style of a device. The device may decide to map a command with the BACK type to the right softkey. The Command class allows the application to communicate the abstract semantics of an action associated with a Command to the device so that action placements that are standard for that device can be used. However, the device does not provide any automatic behavior for the Command. The type of a Command is used only for mapping it onto the user interface. The actual behavior of a Command is always implemented by the application in a CommandListener, which is set by the application to the Displayable. The mapping of Commands to concrete user interface constructs might also depend on the total number of commands. If an application uses more commands than can be mapped onto the available physical buttons on a particular device, the device may use an alternate human interface such as a menu. For example, the abstract commands that cannot be mapped onto physical buttons may be placed in a menu, and the label “Menu” can be mapped onto one of the programmable buttons. 8.5.2
Command Properties
Each Command object has a string label, a command type and a priority: •
Label:
•
Command type: The purpose of a
The label strings are what the application requests to be shown to the user to represent this Command. A single Command can have two versions of labels: short and long. The long label is optional. The implementation decides whether the short or long version is appropriate for a given situation. For example, a device can choose to use a short version of a given Command near a softkey and the long version of the Command in a menu. The short label string should be as short as possible so that it consumes a minimum of screen real estate. The long label can be longer and more descriptive, but it should be no longer than a few words. For example, a Command's short label might be “Play,” and its long label might be “Play Sound Clip.”
command, selected from a defined set of constant types. The defined types are BACK, CANCEL, EXIT, HELP, ITEM, OK, SCREEN, and STOP. The implementation will use the command type for placing the command appropriately within the device’s user interface. Commands with similar types may, for example, be found near each other in certain dedicated places in the user interface. Often, devices will have policy for the placement
101
102
CHAPTER 8
MIDP USER INTERFACE LIBRARIES
and presentation of certain operations. For example, a “backward navigation” command might be always placed on the right softkey on a particular device, but it might be placed on the left softkey on a different device. The Command class provides a fixed set of command types that provide MIDlets with the capability to tell the device implementation the intent of a Command. The application can use the BACK command type for commands that perform backward navigation. On the devices mentioned above, this type of information would be used to assign the command to the appropriate softkey. •
Priority: A number that defines the relative importance between Commands of
the same type on the same Displayable. A lower number indicates greater importance. A Command with a lower numeric priority value is more important than a Command of the same type but with a higher int priority value. If possible, a more important Command is presented before, or is more easily accessible than, a less important one. Typically, the implementation first chooses the placement of a Command based on the type of Command and then places similar Commands based on a priority order. This could mean that the Command with the highest priority (lowest numeric priority value) is placed so that the user can trigger it directly and that Commands with a lower priority (higher numeric priority value) are placed on a menu. It is not an error to define Commands on the same screen with the same priorities and types. If this occurs, the implementation will choose the order in which the Commands are presented. 8.5.3
Command Types
Since the command type is the most important means for an application to adapt to the user interface style of a device, it is important that the applications correctly define the command types. Selecting a correct type for a Command makes applications more consistent with the native applications in a device. There are six command types that are used for more specific purposes: •
BACK: Returns the user to
the logically previous screen. The actual jump to the previous screen is done by the CommandListener provided by the application. The application is responsible, for example, for calling the setCurrent method in CommandListener to change the current displayable to the previous one. Note that the application defines the actual action, since the previous screen may not always be the logically correct place to jump to.
COMMANDS
•
OK and CANCEL: Standard positive and negative answers to a dialog implemented by the current screen. With the OK command type, the application hints to the implementation that the user wants to use the command to confirm the data that has been entered in the current screen and to proceed to the next logical screen. With the CANCEL command type, the application hints to the implementation that the user wants to dismiss the current screen without taking any action on the data that has been entered in the current screen, and that the user (usually) wants to return to the prior screen. OK and CANCEL types should be used together if both positive and negative responses are available in a dialog. In many cases CANCEL is interchangeable with BACK, but BACK should be used for navigation only.
•
HELP: Activates online help. The help information should be presented using the Form class.
•
EXIT:
•
STOP:
Used for exiting the application. All applications should provide an exit function, and thus should have at least one EXIT type command.
Stops some currently running process, operation, or other action. With this command type, the application hints to the implementation that the user will use this command to stop any currently running process visible to the user on the current screen. Examples of running processes might include downloading or sending of data. Use of the STOP command does not necessarily imply a switch to another screen. STOP must not be used when Command is used to close the application; in this case the EXIT type must be used.
If none of the above command types describe the intent of the one of the two more generic command types must be used:
Command,
then
•
With this command type the application can hint to the implementation that the command is specific to the items of the Screen or the elements of a Choice. Normally this means that command relates to the focused item or element. For example, an e-mail application might present the list of mail headers using a List screen. “Delete” or “Read” labeled commands in the List have ITEM type. Delete or Read commands only affect the highlighted List element, not all the elements in the List. The commands either delete the mail or open the mail in reader view.
•
SCREEN:
ITEM:
This command type is used for commands that generally relate to or affect all of the items of a Screen or elements of a List. Examples could be “Delete all,” “Load,” or “Save.” The SCREEN type should be used also if no other type is relevant for the intent of a Command. A SCREEN command generally ap-
103
104
CHAPTER 8
MIDP USER INTERFACE LIBRARIES
plies to the entire screen contents or to navigation among screens. This is in contrast with the ITEM type, which applies to the currently activated or focused item or element contained within the screen. class CommandExample extends Canvas implements CommandListener { Command save = new Command("Save", Command.SCREEN, 1); Command soundOff = new Command("Sound off", Command.SCREEN, 2); Command soundOn = new Command("Sound on", Command.SCREEN, 2); Command exit = new Command("Exit", Command.EXIT, 3); MIDlet midlet; public CommandExample(MIDlet owner) { midlet = owner; setCommandListener(this); addCommand(save); addCommand(soundOff); addCommand(exit); } public void setSound(boolean sound) { // ... implementation-dependent ... } public void paint(Graphics g) { // ... implementation-dependent ... } public void commandAction(Command cmd, Displayable d) { // (see code in next section) } }
COMMANDS
8.5.4
Command Listeners
The application-level handling of Commands is based on a listener model. Each Displayable object has a single listener. When the user invokes a Command on a Displayable, its listener is called. Listeners are registered using the method Displayable.setCommandListener. To define itself as a listener, an object must implement the interface CommandListener, which has following method: void commandAction(Command c, Displayable d)
The application receives these command events if the Screen or Canvas has attached Commands and if there is a registered listener. Only a unicast version of the listener model is adopted, so the Screen or Canvas can have only one listener at a time. Here is a sample CommandListener interface method implementation for the CommandExample class defined above. public void commandAction(Command cmd, Displayable d) { if (cmd == save) { // Save game state and show confirmation dialog Alert alert = new Alert(null, "Saved", null, AlertType.CONFIRMATION); Display.getDisplay(midlet).setCurrent(alert); } else if (cmd == soundOff) { removeCommand(soundOff); addCommand(soundOn); setSound(false); Alert alert = new Alert(null, "Sound off", null, AlertType.CONFIRMATION); Display.getDisplay(midlet).setCurrent(alert); } else if (cmd == soundOn) { removeCommand(soundOn); addCommand(soundOff); setSound(true); Alert alert = new Alert(null, "Sound on", null, AlertType.CONFIRMATION); Display.getDisplay(midlet).setCurrent(alert); } else if (cmd == exit) { // Exit the application midlet.notifyDestroyed(); } }
105
106
CHAPTER 8
8.6
MIDP USER INTERFACE LIBRARIES
Advanced Topics
The following sections present more advanced topics related to the MIDP user interface libraries. 8.6.1
System Screens
Typically, the current screen of the foreground MIDlet is visible on the display. However, under certain circumstances, the system may create a screen that temporarily obscures the current screen of the application. These screens are referred to as system screens. This may occur if the system needs to show a menu or if the system requires the user to edit text on a separate screen instead of a TextField inside a Form. Even though the system screen obscures the application’s screen, from the viewpoint of the application the notion of the current screen does not change. In particular, while a system screen is visible, a call to the method getCurrent will still return the application’s current screen, not the system screen. The value returned by the method isShown is false while the current Displayable is obscured by a system screen. If the system screen obscures a Canvas, the hideNotify method of the Canvas is called. When the system screen is removed, restoring the Canvas, its showNotify method and then its paint method are called. If the system screen was used by the user to issue a command, the commandAction method is invoked automatically after the showNotify method is called. 8.6.2
Adaptation to Device-Specific User Interface Style
The lcdui API contains several methods to query the user interface properties of the target device. The Display class provides methods to query the color capability of the client device. The methods isColor, numColors, and numAlphaLevels provide information about whether the device has a color or monochrome display, the number of colors (or gray levels), and the number of supported alpha-channel levels in off-screen images, respectively. The Display class also has methods to retrieve the prevailing foreground and background colors of the high-level user interface. These methods are useful for creating CustomItem objects that match the user interface of other items and for creating user interfaces within Canvas that match the user interface of the rest of the system. Implementations are not limited to using foreground and background colors in their user interfaces (for example, they might use highlight and shadow colors for a beveling effect), but the color values returned are those that match rea-
ADVANCED TOPICS
sonably well with the color scheme of a device. An application implementing a custom item should use the background color to clear its region and then paint text and geometric graphics (lines, arcs, rectangles) in the foreground color. The system colors can be queried with a method: public int getColor(int colorSpecifier)
The color specifiers are: •
COLOR_BACKGROUND
•
COLOR_FOREGROUND
•
COLOR_BORDER
•
COLOR_HIGHLIGHTED_BORDER
•
COLOR_HIGHLIGHTED_BACKGROUND,
•
COLOR_HIGHLIGHTED_FOREGROUND.
and
The getBorderStyle method is used to query which border style is used in the device for highlighted and non highlighted components. Similarly, using class Font, some of the device fonts, FONT_INPUT_TEXT and FONT_STATIC_TEXT, can be queried using the method: public static Font getFont(int fontSpecifier)
The method returns a Font object that matches fonts used in text editors such as TextField, and for static text presented in Items. Class Display also provides the methods getBestImageWidth and getBestImageHeight for querying the preferred sizes of images used in high-level components. The Displayable class provides the methods getWidth and getHeight to check the screen size provided for the application. The methods for querying screen or component sizes and low-level input capabilities are provided in the classes Canvas and CustomItem. For the applicable methods of class CustomItem, refer to Section 10.8.1, “Interaction Modes.” For the applicable methods of class Canvas, see Section 11.2.3, “Pointer Events.” 8.6.3
Device-Provided Operations
In many high-level user interface classes such as Screens there are some additional operations that are visible only to the end user and not to the applications. This means that the user interface may present commands for which no listeners or event mechanisms are available in the lcdui API. When the user activates such deviceprovided operations, no application listeners are called.
107
108
CHAPTER 8
MIDP USER INTERFACE LIBRARIES
The set of available operations depends on the user interface design of the specific device. For example, in the TextBox class, an operation that allows the user to change the mode for text input between alphabetic and numeric is needed in devices that have only an ITU-T keypad. Many devices with an ITU-T keypad have more complex predictive input systems, and these require additional operations in TextBox. Some of the operations are presented in the user interface in the same way as application-defined commands. End users need not understand which of the operations are provided by the application and which are provided by the system. Not all operations are available in every implementation. For example, a system that has a word-lookup-based text input scheme will generally provide additional operations within the TextBox class. A system that lacks such an input scheme will also lack the corresponding operations. Some operations are available on all devices, but the way the operation is implemented may differ greatly from device to device. Examples of such operations are: the mechanism that is used to navigate between List elements and Form items, the selection of List elements, moving the insertion point within a text editor, and so forth. Some devices do not allow the direct editing of the value of an Item, but instead require the user to switch to an off-screen editor. In such devices, there must be a dedicated selection operation that can be used to invoke the offscreen editor. The selection of List elements could be, for example, implemented with a dedicated “Go” or “Select” key. Some devices have no dedicated selection key and must select elements using some other means. On devices where the selection is performed using a dedicated select key, this key will often not have a label displayed for it. It is appropriate for the implementation to use this key in situations where its meaning is obvious. For example, if the user is presented with a set of mutually exclusive options, the selection key will obviously select one of those options. However, in a device that does not have a dedicated select key, it is likely that the selection operation will be implemented using a softkey that requires a label. The ability to set the select command for a List of type IMPLICIT and the ability to set the default command for an Item are provided so that the application can set the label for this operation and can therefore receive a notification when this operation occurs. 8.6.4
A Note on Concurrency
The MIDP user interface API has been designed to be thread-safe. There are methods that may be called from callbacks, for example, the methods of a CommandListener, ItemCommandListener, ItemStateListener, TimerTask, or a Thread created by the application. The MIDP system implementation handles its own locking and synchronization to make this possible.
NEW FOR MIDP 2.0
The application is responsible for the synchronization of its own objects and data structures. The MIDP user interface API purposefully serializes callbacks to listeners of high-level API and calls to the event notifications methods of class Canvas, so in most cases the application does not need to perform locking.
8.7
New for MIDP 2.0
We have marked a number of topics in this chapter as New! with an icon in the book margin. The user interface capabilities of the high-level user interface have been dramatically improved to allow increased control by the application developer over the layout and visual elements. Class Display has been improved to allow: • the querying of the colors used by the device for normal and highlighted colors for foreground, background, and borders (see the getColor method), • the activation of the backlight and vibrator of the device as added effects to gain the attention of the user (see the vibrate and flashBacklight methods), • the querying of the best width and height for Images used in Lists, Choice elements, and Alerts (see the getBestImageWidth and getBestImageHeight methods), • the querying of the number of alpha levels supported (see the numAlphaLevels method), and • the querying of the border style used for highlighted and normal elements (see the getBorderStyle method). Class Displayable has been extended to allow: • a title and Ticker to be set for any Displayable including Canvas (see the setTitle and setTicker methods), and • the querying of the width and height of any Displayable; previously this was only possible for Canvas objects (see the getWidth and getHeight methods). Abstract Commands have been enhanced to provide: • the ability to create Commands with both a short label and long label; which one is used depends on the context and the available display area (see the constructor and getLonglabel methods).
109
This page intentionally left blank
C H A P T E R
9
MIDP High-Level User Interface – Screen Each subclass of class
Screen is a complete functional user interface element. The
software in a given MIDP device implements each kind of Screen using the native look and feel of the device. The device software takes care of all events that occur as the user navigates in a Screen. When a user action causes a Command invocation event, the event is passed to the application, which brings about a transition to a different Screen. Each Screen can have a title, multiple Commands, and a Ticker. It is up to the device software to include these elements in the visual presentation of the Screen. The four kinds of Screens (List, TextBox, Alert, and Form) are described in this chapter.
9.1
List
The List class is a Screen that displays a list of choice items. The choice items are called elements. Each element has an associated string and may have an icon (an Image). There are three types of Lists: implicit, exclusive, and multiple choice. The type of the List is selected when the List is constructed and cannot be changed during the lifetime of the List object. The look and feel of Lists varies from one type of List to another, as illustrated in the examples below. Also, note that different MIDP implementations may render the Lists differently. When a List is being displayed, the user can interact with it, for instance, by traversing from element to element. The traversal may cause the List to be scrolled. These traversing and scrolling operations are handled by the system and do not generate any events that are visible to the MIDP application. The system notifies the application only when a Command is fired. The notification to the application is carried out via the CommandListener of the Screen. This means that the 111
112
CHAPTER 9
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
application operations associated with list elements are added to the List as ITEM or SCREEN type commands, depending upon whether the operation affects only the selected element or the entire list. In the List class there is also a notion of the select operation, which is central to the user’s interaction with the List. The select operation is implemented differently from device to device. On devices that have a dedicated hardware key for selection operations, such as a “Select” or “Go” key, the select operation is invoked with that key. Devices that do not have a dedicated key must provide other means to perform the select operation; for example, using a labeled softkey. The behavior of the select operation within the three different types of lists is described in the following sections: Section 9.1.1, “Implicit List,” Section 9.1.2, “Exclusive Choice List,” and Section 9.1.3, “Multiple Choice List.” Methods on List objects include insert, append and delete, and methods to get the String or the Image from any element. Elements can be added and removed from the List at any time. The selected elements in the List can be retrieved or changed. However, changing the List while the user is viewing it or trying to select an item is not recommended since it might cause confusion. The majority of the behavior for managing a List is common with class ChoiceGroup; the common API is defined in the interface class Choice. Elements in the List are manipulated with the methods append, delete, getImage, getString, insert, and set. Item selection is handled with methods getSelectedIndex, setSelectedIndex, getSelectedFlags, setSelectedFlags, and isSelected. Here is an example of List creation: List list = new List(“Fruits“, Choice.IMPLICIT); list.append("Apple", null); list.append("Pear", null); list.append("Orange", null); list.append("Banana", null); list.append("Pineapple", null); list.append("Mandarin", null); list.setCommandListener(this); list.addCommand(backCommand);
LIST
9.1.1
Implicit List
An implicit List is used as a normal selection list. The List is presented as a menu from which the user can choose one of the elements. As with other List types, there can be one or more available operations provided as Commands. The operations that operate in the context of the selected element are provided as ITEM type Commands. In other words, List operations that affect or are related to the focused or highlighted element should have the type ITEM. The correct type allows MIDP devices to place the context-sensitive operations in the correct place in the user interface. The implicit List automatically selects the currently focused element when any Command is initiated. To be notified of the selection, the List must have a CommandListener set. The application can query the selection state of a List from CommandListener using the methods getSelectedIndex or isSelected. The implicit List also has the concept of a select command. A select command is a command that the user can activate with the select operation of the device. This user action delivers the select command to the CommandListener of the List. An application can set a select command with the method setSelectCommand. Initially, when a List is constructed, the select command is set to be the built-in List.SELECT_COMMAND. As a general rule, applications should provide their own select command to replace the built-in SELECT_COMMAND. This allows applications to provide a meaningful label instead of relying on the one provided by the system for SELECT_COMMAND. The select command can also be removed completely by passing null to the setSelectCommand method. There is a special usage scenario for this. There can be multiple ITEM commands on a List, but there can be only one select command. In some cases, none of the ITEM commands can be considered suitable for being a select command. If there is more than one ITEM command on a List, the select command can be considered as a default operation for the List. The following code sample illustrates how this can be accomplished. The code creates a list that presents the message headers of an e-mail messaging application. Two of the commands, openCommand and removeCommand, are related to the List elements, so they have type ITEM. The openCommand is considered to be a default operation, invoked when a select operation in the List is activated by the user.
113
114
CHAPTER 9
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
The following code initializes the List: // Construct a list of message headers List list = new List(“Messages“, Choice.IMPLICIT, messageHeaders, messageStateIcons); // The command handler is implemented in the same class list.setCommandListener(this); // Command for “opening” the selected message Command openCommand = new Command(“Open“, Command.ITEM, 1); // Command for “removing” the selected message Command removeCommand = new Command(“Remove“, Command.ITEM, 2); // Command for going “back” Command backCommand = new Command(“Back“, Command.BACK, 3); list.addCommand(openCommand); list.addCommand(removeCommand); list.addCommand(backCommand); list.setSelectCommand(openCommand); // openCommand is the default
The following code defines the command handler of the List: public void commandAction(Command cmd, Displayable d) { int selectedIndex = ((List) d).getSelectedIndex(); if (cmd == openCommand) { // Handle “open” command based on selectedIndex } else if (cmd == removeCommand) { // Handle “remove” command based on selectedIndex } else if (cmd == backCommand) { // Handle backward navigation } }
LIST
9.1.2
Exclusive Choice List
An Exclusive List allows the user to select only a single element. This type of a List is commonly rendered to the screen as a group of radio buttons. When the user selects an element, any previously selected element is automatically deselected. Selecting an element does not notify the application. Notification to the List’s CommandListener occurs when a Command on the List is chosen. When the listener is invoked, it can determine which element is selected with the List.getSelected method. An exclusive List must have Commands added to it, or the user will not be able to trigger any action and will be stuck on the screen. In the example below, the user is able to pick one element and then can select either the OK or BACK command. List list = new List("Border Style", Choice.EXCLUSIVE); list.append("None", null); list.append("Plain", null); list.append("Fancy", null); list.addCommand(backCommand); list.addCommand(okCommand); ... public void commandAction(Command cmd, Displayable d) { List list = (List) d; if (cmd == okCommand) { int i = list.getSelectedIndex(); // Use the index of the selected list element... } else if (cmd == backCommand) { // Handle the back command } }
115
116
CHAPTER 9
9.1.3
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
Multiple Choice List
A Multiple Choice List allows the user to select zero or more elements. Each element can be selected or deselected individually. Typically, this kind of List is presented on the screen as a set of check boxes. Each element has an indicator displaying whether or not the element it is currently selected, and the user can toggle individual elements on or off. Toggling the selection of an element does not notify the application. Notification to the List’s CommandListener occurs when a Command on the List is chosen. When the listener is invoked, it can determine which element(s) are selected with the List.getSelectedFlags or List.isSelected method. A multiple choice List must have Commands added to it, or the user will not be able to trigger any action and will be stuck on the screen. In this example, the user can individually select and deselect the choices “Red”, “Green”, and “Blue.” When satisfied with the choices, the user can select either the OK or BACK command to exit the screen. List list = new List("Colors to mix", Choice.MULTIPLE); list.append("Red", null); list.append("Green", null); list.append("Blue", null); list.addCommand(backCommand); list.addCommand(okCommand); ... public void commandAction(Command cmd, Displayable d) { if (cmd == okCommand) { List list = (List) d; for (int i = 0; i < list.size(); i++) { boolean selected = list.isSelected(i); // If selected, take action... } } }
9.1.4
Long List Elements
In MIDP 2.0, an application can set a preference indicating what to do with longer element text that does not fit in a single line in a List. The setFitPolicy(int fitPolicy) method controls this preference, but a device may decide to ignore the
LIST
application preference. The valid settings of the element fit policy are TEXT_WRAP_DEFAULT, TEXT_WRAP_ON, and TEXT_WRAP_OFF. The initial value of the element fit policy is TEXT_WRAP_DEFAULT, which indicates that the normal devicespecific wrapping policy is used. If the TEXT_WRAP_ON request is honored, the text element contents are wrapped to multiple lines, if necessary, up to the available content space. Conversely, TEXT_WRAP_OFF causes the text element contents to be limited to a single line. Line ending is forced, usually by cropping, if there is too much text to fit in the line. 9.1.5
List Element Fonts
Each List element has a Font that may be used in drawing the text part of the element. An element font that is set by an application is just a hint from the application; some devices might not use it for rendering the text. The same Font class used in the low-level Graphics API is used in element fonts. An application can set the Font of an element with the method setFont(int elementNum, Font font). By default, all elements of a List have the same font. The default Font is determined by the device and is the font most commonly used in selection lists. If an application changes the element font, it can later restore the default font with the call setFont(elementNum, null). There are two general usage scenarios for setting a font for a List that differs from the default. First, the element fonts with differing styles (such as plain, bold, or italic) might be used to highlight some implicit difference in elements. For example, in an e-mail client application, “unread” items might be presented using a bold font, and “read” items with plain font. Because the default font can itself be bold or plain, the application should, as a general rule, set all the element fonts, or else it should query the default font and create a variant font based on the properties of the default font. This also helps ensure that the font sizes of different elements remain consistent: // Get the default font Font defaultFont = list.getFont(0); int defaultFontFace = defaultFont.getFace(); int defaultFontSize = defaultFont.getSize(); // Define a style that differs from the default font int readFontStyle; if (defaultFont.isBold()) { // If default is itself bold, use bold and italic readFontStyle = Font.STYLE_BOLD | Font.STYLE_ITALIC;
117
118
CHAPTER 9
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
} else { // Otherwise use simply bold readFontStyle = Font.STYLE_BOLD; } // Get a new font with only the style differing from default font Font readElementFont = Font.getFont(defaultFontFace, readFontStyle, defaultFontSize); // Set the readElementFont for “unread” elements for (int i = 0 ; i < list.size() ; i++) { // readState array contains boolean true if item is read if (!readState[i]) { list.setFont(i, readElementFont); } }
The second general use case is that the setFont method can be passed a font that differs in size from the default font. If this is done, the application should change the font of all elements to have the same size. If the List element font sizes differ from element to element, this could result in awkward-looking user interfaces. Some devices might limit the element sizes of Lists, so it might not be possible for the application to completely control the font sizes. For more a detailed description about Font properties and their proper values refer to Section 11.3.6, “Fonts.”
9.2
TextBox
The TextBox class is a Screen that allows the user to enter and edit text. The input devices and input methods1 for the text entry differ dramatically from device to device. Many devices have only a numeric keypad, which allows text entry by repetitive tapping of the number keys. Also, there can be separate user-changeable input modes: for example, separate modes for entering text and numbers. Many numeric keypad devices have a more advanced input method called predictive input.2 If there are several alternate input methods available, the user can often select which input mode to use in the editor. Some MIDP devices may have full-character keyboards, and devices with touch screen often have on-screen vir1.
Input methods are software components that interpret user operations on input devices, such as typing keys, speaking, or writing using a pen device to generate text input. 2. Predictive input enables text entry with a numeric keypad using only one key press per letter in most common cases.
TEXTBOX
tual keyboards. The input methods differ also from language to language. For example, in Chinese devices there are several different input modes. These different methods are not directly visible to applications, but developers should bear in mind that in many devices the input of long character strings might be cumbersome or rather slow. In MIDP 2.0, an application now has more concrete control on the input modes used, as described later in this subsection. An application defines the maximum size of the TextBox, which is the maximum number of characters that the editor can contain. The application also sets the input constraints for the editor. These parameters are described in detail in the next section (Section 9.2.1, “Input Constraints.”) The characters in the TextBox can be modified and retrieved by the application either as a String or a sequence of characters. The capabilities of the device determine a limit on the maximum size. The maximum size available may be smaller than the application had requested. The maximum size value is returned from both the setMaxSize and getMaxSize methods. The TextBox constructor and methods that change the text contents throw an IllegalArgumentException if the contents exceed maximum size. This means that when the application needs to use some initial value in the TextBox, it should compare the value returned from getMaxSize to the size of the String that it intends to use in the TextBox. A TextBox must have Commands added to it. Otherwise, the user will not be able to trigger any action and will be stuck in the TextBox. This sample code illustrates the creation of a TextBox with an initialized editable phone number and two commands. TextBox text = new TextBox(“Phone”, “18005551212”, 50, TextField.PHONENUMBER); text.addCommand(backCommand); text.addCommand(okCommand);
9.2.1
Input Constraints
The application can set the input constraint individually for each TextBox. The constraints are defined in the TextField class (see Section 10.4, “TextField”) but are also available in TextBoxes. The available input constraint are ANY, NUMERIC, DECIMAL, PHONENUMBER, URL, and EMAILADDR. The device can use the input constraints to
119
120
CHAPTER 9
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
make it easier for the user to input allowed characters or can use them to format the field value for display. This means that the available input modes are likely to be affected by the input constraints. The NUMERIC and DECIMAL constraints force the contents to numerical values. For example, if the device has a specific input mode for numbers, then the editor is fixed to that mode. NUMERIC is used for entering integer numbers that are, however, returned to applications as strings. DECIMAL is a new constraint in MIDP Specification version 2.0. It is used for entering numerical values that might contain decimal fractions. PHONENUMBER is used for entering phone numbers. Other types are used for alphanumerical entry without any character restrictions other than those imposed by the device itself. The ANY constraint is the most generic alphanumeric type for creating a generic text editor for entering free-form text. The input constraints EMAILADDR and URL allow the input of the same characters as ANY but give hints about the contents of the editor. These constraints do not automatically validate the format or syntax of the input but may be used by the device implementation to choose a better input mode: for example, automatic capitalization and predictive input may be turned off by default in EMAILADDR and URL editors. The PHONENUMBER type constrains the entered characters to those available in phone numbers. The set of special characters in phone numbers differs from device to device and is likely based on the network standard for which the device is intended. In a PHONENUMBER TextBox, the numeric keypad can be automatically enabled for direct input of numbers, and the output can be formatted as a phone number using device-specific or network-specific formatting rules. The text editor may also include device-specific operations. For instance, a PHONENUMBER TextBox may have an operation that allows the user to copy a phone number to be input to the editor from the device-specific phone book application. The device may also enable the “TALK” button on the phone to dial the number. This provides applications with a simple way to present a phone number to the user and to allow the user to dial that number. There are additional modifiers for the input constraints. The input constraint modifiers are: •
PASSWORD:
•
UNEDITABLE:
•
SENSITIVE: Used to indicate that the text entered is sensitive and must never be
Used when confidential data needs to be entered. The device typically masks the data with a “*” character. When this modifier is active, the user cannot edit the contents.
stored in any auto-completion or predictive input dictionaries that the devices might normally use.
TEXTBOX
•
NON_PREDICTIVE: Indicates that device should not use predictive input even if such an input method is available on the device. The mode can be used if the text to be entered is something that most likely cannot be entered with predictive input methods. The user interaction thus becomes more seamless, since the user does not need to turn predictive input off manually. On a device that does not have predictive input, this modifier is simply ignored.
•
INITIAL_CAPS_WORD: Is a hint to the implementation that during text editing, the
initial letter of each word should be capitalized. The flag is useful, for example, for entering names in an address book application. •
INITIAL_CAPS_SENTENCE:
This flag is a hint to the implementation that during text editing, the initial letter of each sentence should be capitalized.
The modifiers are used by combining the set of modifiers with constraints using the bitwise OR operator. For example, the constraint “NUMERIC | PASSWORD” creates an editor that allows the input of numeric passwords only. 9.2.2
Input Modes
The application can request that the implementation use a particular input mode when the user initiates the editing of a TextBox. As described earlier, devices often have multiple input modes for text entry. These input modes allow easy text entry for certain types of text, such as numeric or lowercase alphabets, or specific modes for different languages. If the requested mode is not supported by the device, normal text entry mode is used. The MIDP Specification does not try to specify all the possible input modes found in devices. Rather, the specification is based on the idea that the applications themselves define for which characters input should be made as convenient as possible. The input modes are identified by strings. The MIDP Specification defines standard rules for the input mode strings and specifies a set of concrete strings that may be used by devices. The specification also allows the set to be extended by the device implementations. The initial input mode is set with the method: public void setInitialInputMode(String characterSubset)
This method allows the application to specify the input mode best suited for the editor. If a device supports the input mode, the TextBox is initially set to that mode, but the user may select another one from the device-specific menus. Many of the input mode strings are based on Unicode character blocks. For example, the UCB_BASIC_LATIN input mode allows the easy input of Latin charac-
121
122
CHAPTER 9
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
ters, and UCB_HIRAGANA is the input mode that is specific to the Japanese language Hiragana script characters. There are also input modes that define subsets of the Unicode blocks. For example, the following Latin-specific modes are available: MIDP_UPPERCASE_LATIN for uppercase mode, MIDP_LOWERCASE_LATIN for lowercase input mode, and IS_LATIN_DIGITS for Latin number entry. The input mode settings have a lower priority than the input constraints. If the input constraint and input mode are in conflict, then the input mode is ignored. For example, if the constraint is set to NUMERIC and mode to MIDP_UPPERCASE_LATIN, the input mode is ignored and numeric input is activated. Often an initial input mode is used simply with the input constraint ANY. In many cases, however, the input modes can be combined with constraints other than ANY. For example, the NUMERIC constraint together with UCB_ARABIC input mode initially sets the editor to number entry with Arabic-Indic digit input mode (if supported by the device.)
9.3
Alert
Alerts are Screens that can be used to inform the user about errors and other excep-
tional conditions. Alerts can also be used as short informational notes and reminders. For the presentation of longer information, other Screen classes such as Form should be used. An Alert shows a message and an optional Image to the user. An Alert is either presented for a certain period of time, or it can be modal with a special user operation to dismiss (close) the Alert. The time the Alert is presented can be controlled with the setTimeout method. If the timeout is not set by application, the Alert timeout is the default timeout determined by the device. The default value can be inspected using the getDefaultTimeout method. The Alert is set to be modal if the application sets the alert time to be infinite with the method call setTimeout(Alert.FOREVER). A timed Alert is forced to be modal if the device cannot present the Alert contents without scrolling. In modal Alerts the device provides a feature that allows the user to dismiss the Alert, whereupon the next screen is displayed. Timed Alerts can be used when the user does not need to be aware of the information presented and can safely ignore the Alert. Alerts without a timeout should be used when the user must be made aware of the information or condition. When an Alert is dismissed either explicitly by the user or after a timeout, the current displayable is automatically changed to the next screen. When an Alert is displayed, the application can choose which Displayable is to be displayed after
ALERT
the Alert is complete. This is done by using a specialized setCurrent method of class Display: public void setCurrent(Alert alert, Displayable nextDisplayable)
If the normal setCurrent(Displayable nextDisplayable) method is used, the display reverts to the current screen after an Alert exits. The AlertType of an Alert can be set to indicate the nature of the information provided in the Alert. There are five AlertTypes; ALARM, CONFIRMATION, ERROR, INFO, and WARNING. ERROR and WARNING are used for error messages. WARNING should be used when the user has the possibility to prevent the error and ERROR when some non preventable error has already occurred. CONFIRMATION and INFO are used for more positive informational notes. CONFIRMATION is used when the user should confirm that some action has taken place. For example, after the user has selected some element from a settings List, a CONFIRMATION may be presented to the user to indicate that the setting has been changed. The INFO type is used for more generic positive informational notes. The ALARM type should be used when some notification is presented that interrupts the normal interaction in some other way. For example, a calendar application may use the ALARM type for notifying the user that a timed calendar event has been triggered. The AlertType settings affect the presentation of the Alert. For example, if an application does not provide any image for the Alert, then the device implementation may present some default system icon based on the AlertType. For example, an exclamation icon might be used in an ERROR Alert. AlertTypes can also have system sounds associated with them so that the device can audibly alert the user. The presence and selection of sounds is device-dependent. The sound associated with the AlertType can be played anytime by calling the method AlertType.playSound. An example of an Alert is shown below: Alert alert = new Alert("Cinema", "Two tickets purchased", null, AlertType.CONFIRMATION); alert.setTimeout(4000); display.setCurrent(alert);
123
124
CHAPTER 9
9.3.1
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
Commands in Alert
added to an Alert make it easy to create query dialogs with a set of predefined user responses such as “OK” and “Cancel.” When Commands are added to an Alert, the built-in dismiss operation is removed. Similarly, when a CommandListener is set, the automatic advance behavior is deactivated, and the application must take care to call setCurrent when Alert should be removed from the display. An Alert that has two or more application-defined Commands is always modal. If there is only one Command in a timed Alert, then the Command is activated automatically when the timeout occurs. The semantics of an AlertType are slightly different when an Alert is a dialog with multiple answers (Commands.) The alert types generally indicate some forthcoming situation rather than something that has already been happened. For example, ERROR or WARNING can indicate that something erroneous or a harmful situation may result when choosing some of the Commands in Alert; for example, when user data may be lost. CONFIRMATION type should be used in dialogs that indicate less destructive actions. ALARM type is used similarly, but mainly to notify the user of an event that has occurred. For example, the ALARM type might be used to “Snooze” or “Dismiss” an alarm clock application. An example: Commands
Alert alert = new Alert(null, null, null, AlertType.CONFIRMATION); alert.addCommand(okCommand); alert.addCommand(backCommand); alert.setCommandListener(this); String prompt = "Delete address?\n\n"; String detail = "[email protected]"; alert.setString(prompt + detail); display.setCurrent(alert);
9.3.2
Activity Indicator
An Alert may contain a non-interactive Gauge object that is used as an activity or progress indicator. This can be used for creating simple wait or progress dialogs when there is some background process occurring and the user has to wait for the operation to be completed. For example, an activity indicator might be used when an application is downloading a large amount of data from the network. The Gauge class is described more thoroughly in Section 10.7, “Gauge.” There are, however, certain constraints for the Gauge object when it is used as activity indicator in an Alert. For example, the Gauge must be set to non-interactive mode, and there must
FORM
not be any label or any item Commands in it. The constraints are documented in more detail in the MIDP Specification version 2.0. Alert alert = new Alert("Cinema", "Sending message", null, null); alert.setTimeout(4000); Gauge indicator = new Gauge(null, false, Gauge.INDEFINITE, Gauge.CONTINUOUS_RUNNING); alert.setIndicator(indicator); display.setCurrent(alert);
9.4
Form
A Form is a Screen that may contain a combination of Items, including StringItems, ImageItems, editable TextFields, editable DateFields, Gauges, and ChoiceGroups. Any of the subclasses of Item defined by the MIDP Specification may be contained within a Form. The device handles layout, traversal, and possible scrolling automatically. The entire contents of the Form scroll up and down together. Horizontal scrolling is not generally available. This means that the MIDP Specification does not forbid a device to implement this, but it is not endorsed. When a device allows only vertical scrolling, the layout and traversal model is easier and matches the limited set of controls available on a typical mobile information device. Applications must be written with this limitation in mind. For example, a CustomItem subclass needs to designed so that it works in varying screen widths without any horizontal scrolling support. The methods for modifying the sequence of Items stored in a Form include insert, append, delete, get, set, and size. MIDP 2.0 devices also have a deleteAll method. Items within a Form are referenced by indices. The first Item in a Form has an index of zero and the last has the index size()-1. The code sample below creates an empty Form container to be used as an options selection screen. This simple example has a title for the Form and Commands for accepting and canceling the Form contents. This kind of empty Form should be avoided in real applications. Note that we will return back to this example in Chapter 10 when we illustrate the use of the Form class in more detail. The code below serves as a starting point for an “Options” selection form of a photo album application. The example will
125
126
CHAPTER 9
MIDP HIGH-LEVEL USER INTERFACE – SCREEN
continue in Section 10.1, “Item,” where we show how to add different instances to this Form.
Item
class
Form form = new Form("Options"); form.addCommand(backCommand); form.addCommand(okCommand); form.setCommandListener(this); // Items are added later (see below) display.setCurrent(form);
Refer to Chapter 10, “MIDP High-Level User Interface – Form” for more information on using the Form class.
9.5
New for MIDP 2.0
We have marked a number of topics in this chapter as New! with an icon in the book margin. Here is a summary of the most important new high-level user interface features of MIDP 2.0 described in this chapter. Each of the Screen classes has been enhanced to provide more control over presentation and event handling. The Font class has been extended to allow: • the querying of the default Font for static text and input text (see the getFont method). The List class has been extended to allow: • the ability to get and set the Font of each element in the list (see the setFont and getFont methods), • the control of the wrapping or truncation of text within elements (see the setFitPolicy and getFitPolicy methods), • the ability to set the default command for selecting elements (see the setSelectCommand method), • the ability to delete all of the elements in the list with a single method (see the deleteAll method), and
NEW FOR MIDP 2.0
• the ability to set mutable Images as elements of a List (see the append, insert, and constructor methods). The Alert class has been extended to allow: • the Images in an Alert to be mutable (see the setImage method), • a Gauge to be used as a progress indicator in the Alert (see the setIndicator and getIndicator methods), • one or more Commands to be added and to replace the default dismiss command (see the addCommand and removeCommand methods), and • setting a command listener to allow the application to handle Commands and to disable the built-in timer and command handling (see the setCommandListener method).
127
This page intentionally left blank
C H A P T E R
10
MIDP High-Level User Interface – Form A
Form object is a Screen that presents a sequence of Items. Form objects are com-
monly used in MIDP applications to present data that consists of various different types such as text, images, editable date fields, text fields, and so on. This chapter describes the various Item classes and their features in detail, along with a description of class ItemStateListener that can be used to listen for changes in Item objects. In the end of this chapter, the rules for Form layout management are presented.
10.1 Item Class Item is a superclass of all those components that can be attached to a Form. An Item can be contained only in a single Form at a time. The application must remove the item from the Form in which it is currently contained before inserting it into another Form. All Item objects can have a label field, which is a String representing the title of the Item. If the label String is null, then no label is presented. The label is typically displayed near the Item when the Item is visible on the screen. If the screen is scrolling, the implementation tries to keep the label visible at the same time as the Item. 10.1.1 ItemStateListener When the user changes an editable Item in a Form, the application can be notified of the change by implementing the ItemStateListener interface and setting the lis129
130
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
tener on the Form. The itemStateChanged method of the ItemStateListener set on the Form is called automatically when the value of an interactive Gauge, ChoiceGroup, DateField, or TextField changes. The listener is set for the Form using the setItemListener method. It is not expected that the listener is called after every event that causes a change. However, if the value has changed, the listener is called sometime before it is called for another Item, or before a Command is delivered to the ItemStateListener of the Form. Continuing the example started in Section 9.4, “Form,” the ItemStateListener would be set as follows: form.setItemListener(this);
10.1.2 Item Commands In MIDP 2.0, context-sensitive Commands can be added to Items. Commands added to an Item are made available to the user only when the focus is on that Item. As with Commands added to Displayables, the device implementation decides how the Commands are presented in the user interface. For example, the Commands might appear as a context-sensitive menu for the Item or as a normal menu when the Item is being manipulated by the user. Context-sensitive Commands are used much like ordinary Commands in Displayables. The addCommand and removeCommand methods of the Item class control which Commands are associated with Items. There is a dedicated listener type called ItemCommandListener that is notified automatically when the user activates a Command of an Item. The listener of an Item is set with the setItemCommandListener method. One of the Commands of an Item can also be chosen as the default Command using the method setDefaultCommand. A device may make this Command more easily accessible, for example, using the “Select” key of a device if such a key is available. For an example on item command use, refer to the sample code in Section 10.2.1, “Appearance Modes.”
10.2 StringItem Read-only strings can be added to a Form either directly as Strings (Java String objects) or as StringItems. StringItem is a simple class that is used to wrap Strings so they can be treated consistently with the other Items. Strings are converted to StringItems automatically when they are appended to a Form. These kinds
STRINGITEM
of StringItems have null labels. When an Item that was appended as a String is retrieved from a Form, it is returned as a StringItem. Continuing the example started in Section 9.4, “Form,” the following code illustrates how to add a new StringItem to the Form: // Note: 'getImageName' is application-specific String imageName = getImageName(); String si = new StringItem("Photo name:", imageName); form.append(si);
When a sequence of StringItems is displayed, the text is concatenated and wrapped to as many lines as needed. This has the effect that sequential StringItems are displayed as a paragraph of text. Any newline characters within StringItems are treated as row breaks (see Section 10.9.1, “Row Breaks”). Also, a label may cause a row break either before or after the label, or both. Generally, the label is used as a paragraph title. Here is an example that illustrates the use of concatenated StringItems: Form form = new Form("Concatenation"); ... // Add Commands and CommandListener form.append("First"); form.append("paragraph"); form.append("of text."); Item si = new StringItem("Label", "Another"); form.append(si); form.append("text paragraph"); form.append("here as an example."); display.setCurrent(form);
10.2.1 Appearance Modes The StringItem and ImageItem (see Section 10.3, “ImageItem”) classes have an appearance mode attribute that controls the presentation of these items. There are three modes available: PLAIN, HYPERLINK, and BUTTON. By default, the mode is PLAIN in both items. Other modes can be used by creating a StringItem or ImageItem with a specialized constructor that receives an appearance mode argument.
131
132
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
Simply having an item with HYPERLINK or BUTTON appearance mode does not do anything. When either of these modes is used, the application must also add at least one Command to the item. Preferably, the Command is set as the default Command. In addition, an ItemCommandListener must be registered that actually will implement the action for the hyperlink or button. Here’s an example that illustrates the use of the HYPERLINK appearance mode: Form form = new Form("Appearance"); Command backCommand = new Command("Back", Command.BACK, 1); form.addCommand(backCommand); form.setCommandListener(this); Item link = new StringItem(null, "link", Item.HYPERLINK); Command linkCommand = new Command("Go", Command.ITEM, 1); link.setDefaultCommand(linkCommand); link.setItemCommandListener(this); form.append("Follow this "); form.append(link); form.append(".");
Note that the linkCommand variable in the above code is set to the link StringItem whereas the backCommand variable is set to the entire Form. This means that the linkCommand operation is only accessible when the user is manipulating the link item. In other words, the presence of the linkCommand operation is context-sensitive.
10.3 ImageItem Image
objects can be added to a Form either directly as an Image or as an ImageItem.
ImageItem is a simple class that wraps an Image. By default, the ImageItem is placed
next to the previous StringItem or ImageItem. If an ImageItem is wider than the horizontal space available in the row, it is placed in a new row. Images wider than the Form width are clipped. The ImageItem can be given a preferred layout policy with the setLayout method. The directive passed to this method defines whether the image is centered within the Form margins (LAYOUT_CENTER), left-justified (LAYOUT_LEFT), or right-
TEXTFIELD
justified (LAYOUT_RIGHT) and whether a forced line break is created before or after the image (LAYOUT_NEWLINE_BEFORE, LAYOUT_NEWLINE_AFTER). The layout is merely a hint for the device and might not be supported by the device. It also varies from device to device how the alignment directives are actually implemented. In some devices LAYOUT_LEFT might cause the ImageItem to float to the left margin, allowing nearby StringItems to wrap around the side of the image. Continuing the example started in Section 9.4, “Form,” the following code adds an ImageItem to the Form. Image image = Image.createImage( "/images/PhotoAlbum.png"); ImageItem imageItem = new ImageItem(null, // (no label) image, ImageItem.LAYOUT_CENTER | ImageItem.LAYOUT_NEWLINE_AFTER | ImageItem.LAYOUT_NEWLINE_BEFORE, "(preview image)"); form.append(imageItem);
There is also a LAYOUT_2 directive that causes an ImageItem to follow the strictly specified MIDP 2.0 Form layout rules (discussed in Section 10.9, “Form Layout”). This means that the horizontal alignment directives LAYOUT_LEFT, LAYOUT_RIGHT, and LAYOUT_CENTER will behave the same way as in other Item classes. If LAYOUT_2 is not set, then the results are (for backwards compatibility reasons) implementation-specific since MIDP Specification version 1.0 did not define the behavior of the layout directives clearly for ImageItem.
10.4 TextField A TextField is an editable text component that may be placed in a Form. The TextField API is exactly the same as that of TextBox. The only difference is the inherited functionality: TextField inherits from Item whereas TextBox inherits from Screen. Thus, as with TextBox, a TextField has a maximum size, input constraints and input mode (see Section 9.2, “TextBox”), a label, and a String value. The contents of a TextField can be either edited in-line in Form, or the Form may just present static text with a user operation to activate a separate editing view that allows the contents to be edited. The TextField contents within a Form are wrapped.
133
134
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
Devices dictate how many lines a TextField consumes. In some devices, the TextField height can grow dynamically based on the content. An example: TextField textField = new TextField("Photo caption:", "", 32, TextField.ANY); form.append(textField);
10.5 DateField A DateField is a component that may be placed in a Form in order to present date and time (calendar) information. The user is able to select a date or time value for the field. Devices have different kinds of editors for this. Some may allow the user to select a value with a graphical date or time selector, and in others the value is simply entered using the numeric keypad. The value for a DateField can be initially set or left unset. If the value is not set, the DateField.getDate method returns null. The user interface must visually indicate that the date and time are unknown. Each instance of a DateField can be configured to accept either date or time information, or both. This input mode configuration is done by choosing the DATE, TIME, or DATE_TIME mode of this class. The DATE input mode configures the DateField to allow only date information and TIME to allow only time information (hours, minutes). The DATE_TIME mode allows both clock time and date values to be set. An example: DateField date = new DateField("Date", DateField.DATE); date.setDate(new java.util.Date()); // Set date to "now" form.append(date);
GAUGE
10.6 ChoiceGroup A
defines a group of selectable elements that can be placed within a Form. A ChoiceGroup is similar to a List (Section 9.1, “List”), but it supports only the exclusive and multiple choice modes. Also available is a ChoiceGroup-specific POPUP mode. The selection behavior of a pop-up choice is identical to that of an exclusive choice. The pop-up choice differs from an exclusive choice in presentation and interaction. Whereas the EXCLUSIVE type of ChoiceGroup presents all the elements in line as a radio button list, the POPUP type shows only the currently selected element in line in the Form. The other elements are hidden until the user performs an action to show them. When the user performs this action, all elements become accessible. For example, a device may use a pop-up menu to display the elements. Generally, the device is responsible for providing the graphical representation of these ChoiceGroup modes and must provide a visually different representation for different modes. For example, it might use radio buttons for the exclusive choice mode, check boxes for the multiple choice mode, and pop-up menus without any specific graphics for pop-up mode. An example: ChoiceGroup
ChoiceGroup choice = new ChoiceGroup("Size:", Choice.EXCLUSIVE); choice.append("Small", null); choice.append("Large", null); form.append(choice);
10.7 Gauge The Gauge class implements a graphical value display that may be placed in a Form. A Gauge displays a visual representation of a numeric value in the range between zero and the maximum value defined by the programmer. If the Gauge is set to be interactive, user actions can increase and decrease the value. Changes to the Gauge value are reported using an ItemStateListener. If the Gauge is set to be non-interactive, it represents a progress bar that can be used to provide feedback about the progress of long-running operations. The application can set and get the value of Gauge with the setValue(int) and getValue() methods. When Gauge is in noninteractive progress bar mode, the application must periodically update the value
135
136
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
using the setValue method during the operation: the Gauge value should reach the maximum value just before the operation is finished. Also available for a non-interactive Gauge is an indefinite range setting. This is used if there is no known endpoint to the activity. To define an indefinite Gauge, set the maximum value to the special INDEFINITE value. There are two kinds of indefinite Gauges available: CONTINUOUS_RUNNING and INCREMENTAL_UPDATING. These constants are used as Gauge range values. Continuous mode automatically animates the progress animation, whereas incremental mode requires that application call setValue(Gauge.INCREMENTAL_UPDATING) whenever there is an update in progress state. For both of these modes there are separate idle modes that can be set with range values CONTINUOUS_IDLE and INCREMENTAL_IDLE, which indicate that no work is in progress. An application should use the idle modes with the correct pairs because the device progress graphics are typically designed so that, for example, CONTINUOUS_IDLE works well only in CONTINUOUS_RUNNING mode. An example using interactive Gauge is: Gauge gauge = new Gauge("Speed:", true, 10, 5); form.append(gauge);
A non-interactive Gauge can also be placed in an Alert as an activity indicator. See Section 9.3.2, “Activity Indicator,” for details.
10.8 CustomItem The abstract class CustomItem allows applications to create new visual and interactive elements that can be used in Forms. To do this, a new subclass of CustomItem is created: it is responsible for creating the visual representation for the Item, including sizing and rendering. The subclass fully controls what is presented within item area. It defines the colors, fonts, and graphics that are used, including rendering of special highlight and focus states the item may have. Only the label of the item is rendered by the device, but the label is always rendered outside the CustomItem content area.
CUSTOMITEM
A CustomItem can trigger notifications to the ItemStateListener of a Form in which the CustomItem is contained. This is done by calling the notifyStateChanged method inherited from Item. Like all Items, CustomItems have the concept of minimum and preferred sizes. These sizes pertain to the total area of the Item, which includes space for the content, label, borders, and so forth. (See Section 10.9.4, “Item Sizing,” for a full discussion of the areas and sizes of Items.) A CustomItem does not itself fully control this area. There is, however, a smaller region within the CustomItem called the content area that the CustomItem subclass paints and from which it receives input events. A CustomItem subclass overrides the methods getMinContentHeight, getMinContentWidth, getPrefContentHeight, and getPrefContentWidth to return the minimum and preferred sizes for the content area. The device is responsible for calculating the minimum and preferred sizes for the whole item. The device also defines the actual content area space made available for CustomItem. The size of this area is given in calls to the methods sizeChanged and paint: protected void sizeChanged(int w, int h) protected abstract void paint(Graphics g, int w, int h)
The actual size might be smaller than the requested minimum content size if the device cannot allocate the space requested. For example, if no horizontal scrolling is available in a device, there is a device-specific maximum size for item width, which in turn affects the maximum content size for CustomItems. If the minimum or preferred content area size changes, an application must call the method invalidate, and the subsequent calls to the size methods must return the new content area sizes. The method invalidate tells a device that it needs to perform its layout computation, which calls the content size methods to get new values based on the new contents of the CustomItem. 10.8.1 Interaction Modes Each CustomItem is responsible for adapting its behavior to the interaction methods available on a target device. A CustomItem subclass needs to call the method getInteractionModes to inspect the interaction modes that are supported by a particular device. This method returns a bit mask of the supported modes with bits set or unset for the following modes: •
KEY_PRESS, KEY_RELEASE, and KEY_REPEAT
for indicating the level of key press event support. Devices support either none of the key event modes, both press
137
138
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
and release event modes, or all key event modes. It is not valid for a device to support key press events without supporting key release events. •
POINTER_PRESS, POINTER_RELEASE,
•
TRAVERSE_HORIZONTAL and TRAVERSE_VERTICAL for indicating support for inter-
and POINTER_DRAG for indicating the level of pointer event support. Similar to key events, devices support either none of the pointer event modes, both press and release event modes, or all of the pointer event modes.
nal traversal in a given direction, as discussed below. 10.8.2 Traversal An implementation may support traversal inside a CustomItem; that is, the implementation may temporarily delegate the responsibility for traversal to the item itself. Even if there is only one traversal location inside the CustomItem, the item might want to support the internal traversal protocol so that it can perform specialized highlighting, animation, and so forth when the user has traversed into it. The implementation indicates its support for traversal inside a CustomItem by setting one or both of the TRAVERSE_HORIZONTAL or TRAVERSE_VERTICAL bits in the value returned by getInteractionModes. If neither of these bits are set, the implementation is unwilling to let CustomItems traverse internally, or else the implementation does not support traversal at all. If the implementation does support traversal but has declined to permit traversal inside CustomItems, the implementation will supply its own highlighting outside the CustomItem’s content area. The CustomItem need not support internal traversal at all. It can do this by returning false to the initial call to the traverse method. (This is the default behavior if this method has not been overridden by the CustomItem.) If this occurs, the device must arrange for the user to be able to traverse onto and past this item. The device must also arrange for proper scrolling to take place, especially if the item size exceeds the height of the screen, regardless of whether internal traversal is occurring. Refer to the documentation of the traverse method for a full specification of the required behavior and responsibilities of a CustomItem for performing internal traversal.
FORM LAYOUT
10.9 Form Layout The Form class has a layout policy that is organized around rows. A Form grows vertically and scrolls vertically as necessary. The height of a Form varies depending upon the number of rows and the height of each row. The height of each row is determined by the items that are positioned on that row. In MIDP 2.0, the Form layout algorithm considers each Item in turn, starting at Item zero and proceeding in order through each Item until the last Item in the Form has been processed. Items are laid out at the beginning of each row, proceeding across each row in the chosen layout direction, packing as many Items onto each row as will fit, unless a condition occurs that causes the packing of a row to be terminated early. A new row is then added, and Items are packed onto it as described above. Items are packed onto rows, and new rows are added below existing rows as necessary until all Items have been processed by the layout algorithm. This general principle of Form layout is illustrated in Figure 10.1.
Item 1
Item 2
Item 3
Item 4 (Form content area)
Figure 10.1
General principle of Form layout
An application can influence the layout of the Items using the following layout directives: •
LAYOUT_LEFT, LAYOUT_RIGHT,
and LAYOUT_CENTER define the horizontal align-
ment of an items in a row. •
LAYOUT_TOP, LAYOUT_BOTTOM,
and LAYOUT_VCENTER define the vertical align-
ment of an item in a row. •
LAYOUT_NEWLINE_BEFORE
and LAYOUT_NEWLINE_AFTER force row breaks after
and before an item. •
LAYOUT_SHRINK, LAYOUT_VSHRINK, LAYOUT_EXPAND,
and LAYOUT_VEXPAND affect
the way an item is sized. •
indicates that new MIDP 2.0 layout rules are in effect for an item. LAYOUT_2 has no effect for StringItem, CustomItem, or Spacer. LAYOUT_2
139
140
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
These layout directives can be combined using the bitwise OR operator (|) to compose a layout directive value. The horizontal alignment directives are mutually exclusive. Similarly, multiple vertical alignment directives cannot be combined. All the other directives can be combined in any way with the other directives. Such a value is used as the parameter for the setLayout method and is the return value from the getLayout method. The following example uses the setLayout method to set a combined layout directive value for a TextField. A LAYOUT_2 setting for TextField has the effect that other Items may also be placed in the same row. LAYOUT_SHRINK and LAYOUT_VSHRINK indicate that TextField should have the smallest possible size. LAYOUT_RIGHT and LAYOUT_TOP indicate that the TextField is aligned to the top or right side of the row. TextField textField = new TextField(...); textField.setLayout(Item.LAYOUT_2
|
Item.LAYOUT_SHRINK | Item.LAYOUT_VSHRINK | Item.LAYOUT_RIGHT
| Item.LAYOUT_TOP);
The following sections describe the behavior of these layout directives more thoroughly. 10.9.1 Row Breaks The layout algorithm generally attempts to place an Item in a Form on the same row as the previous Item, unless certain conditions occur that cause a “row break.” A row break should be distinguished from a line break. When there is a row break, the next Item is placed at the beginning of a new row in the Form instead of being placed in the same line as the previous Item. In contrast, a line break occurs inside an Item and usually causes the Item to be taller in size. Applications can add forced row breaks by using line feed characters (‘\n’; U+000A) in an unlocked StringItem (these are discussed below) or by adding layout directives LAYOUT_NEWLINE_BEFORE or LAYOUT_NEWLINE_AFTER to Items. The presence of a newline directive does not cause an additional row break if there is one already present, but a line feed character always creates a row break. By default, ChoiceGroup, DateField, Gauge, and TextField Items are presented on their own rows. An application must set the LAYOUT_2 directive in these Items to remove the automatic row breaks from them and to allow several Items on the same row. Still, the device may dictate that the item is always presented on a row by itself.
FORM LAYOUT
// textField1 and dateField1 do not have // LAYOUT_2 set. They are presented // in their own lines.
textField1 dateField1 textField2
dateField2
textField2.setLayout(Item.LAYOUT_2); dateField2.setLayout(Item.LAYOUT_2);
Line breaks occur inside the Item area. For example, text in a TextField can be wrapped to multiple lines causing the TextField to consume more vertical space from Form. This kind of automatic content wrapping is done by the device. An application can also add manual line breaks to a TextField by placing a line feed character (“\n”) in the String that is given as a parameter to the TextField. Thus, it depends on the context in which the text is used whether line feed characters will cause a row break in a Form or just a line break inside an Item. 10.9.2 Label Layout Label positioning is dictated by the device. Labels can be presented in the same line with the Item or on a line before the Item. A device implementation may, for example, have a break (row or line) before every Item that has a label. Also, a label may be restricted to one line only. If this is the case, labels that contain line breaks might be truncated at the line break and cause the rest of the label not to be shown. The label is counted as part of an Item size whenever the label is presented within the same content area as the Item. On the other hand, if the device dictates that a label be presented in the margin of a Form, then the label is not counted as part of the size of the Item. 10.9.3 Current Alignment The layout algorithm has a concept of current alignment. Current alignment can have the value left, center, or right. The current alignment changes when the layout algorithm encounters an Item that has one of the layout alignment directives LAYOUT_LEFT, LAYOUT_CENTER, or LAYOUT_RIGHT. If none of these directives is present in any Item, the current layout directive does not change. This rule has the effect of grouping the contents of the Form into sequences of consecutive Items sharing an alignment value. When the layout algorithm encounters an Item with a differing layout alignment directive, then there is an automatic row break before the Item. The current alignment is maintained internally in the Form and does not affect the layout value as reported by the getLayout method.
141
142
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
item1.setLayout(Item.LAYOUT_LEFT); // item2 uses current alignment
item1
item2
item3.setLayout(Item.LAYOUT_RIGHT);
item3
// item4 uses current alignment
item5
item4
item6
item5.setLayout(Item.LAYOUT_CENTER); // item6 uses current alignment
also has an initial value for current alignment that is dictated by the device implementation. This initial value is used until an Item is laid out that explicitly defines any horizontal layout alignment directives. The initial value of current alignment can be LAYOUT_LEFT or LAYOUT_RIGHT. It is LAYOUT_LEFT if leftto-right item layout policy is used in a device and LAYOUT_RIGHT for right-to-left layout. Since the device implementation dictates the layout policy of a Form, this policy cannot change within the same Form. The device may, for example, choose the policy based on the natural language used in the user interface of a device. For example, English devices use left-to-right, and Arabic devices use right-to-left (see Figure 10.2.) Form
left-to-right
item1
item2
item4
Figure 10.2
item3
right-to-left
item3
item2
item1 item4
Item layout policy dictated by the device implementation
Since the initial value of current alignment is based on the Form layout policy, the current alignment at the start of the layout algorithm is based on the default alignment value of the given layout policy. For example, in Arabic user interfaces, right-to-left aligned content is most common. 10.9.4 Item Sizing Items
have two explicit size concepts: the minimum size and preferred size. Both refer to the total size (height and width) that an item requires when it is presented on the display. The size includes the Item’s content and the necessary internal margins. Also, the label for the Item is included in these sizes if the device implementation renders the label so that it affects the layout. The Form layout algorithm decides which of the sizes are used when the Item is laid out.
FORM LAYOUT
The sizes can be dynamic since they are dependent on the contents of the The minimum size is the smallest size at which the Item can function and display its contents, though perhaps not optimally. The preferred size is the size that allows an item to fully present its contents. Both of the sizes are defined by the device implementation for each built-in Item and by the application for each CustomItem and Spacer. An application can also lock the preferred size of each Item by calling the method setPreferredSize. The minimum size cannot be locked, so the implementation can enforce certain minimum dimensions for Items. When an Item is created, its preferred size is unlocked, and its size is calculated by the device implementation as described above. The application can also lock one dimension of the preferred size and leave the other dimension unlocked. If the content changes, the size on the unlocked dimension is recomputed to reflect the new contents, but the size on the locked dimension remains unchanged. For example, if the application calls setPreferredSize(50, -1), the preferred width will be locked at 50 pixels and the preferred height would be computed based on the content of the Item. Similarly, if the application calls setPreferredSize(-1, 60), the preferred height will be locked at 60 pixels and the preferred width would be computed based on the contents of the Item. This feature is particularly useful for Items with textual content that can be line-wrapped; examples of such Items include StringItem and TextField. Items also have an implicit maximum size provided by the implementation. The maximum width is typically based on the width of the screen space available to a Form. Since Forms can scroll vertically, the maximum height should typically not be limited by the height of the available screen space. Item.
10.9.5 Row Filling If the device implementation has not dictated otherwise, and if space permits two adjacent Form Items, they are placed on the same row. When packing multiple Items onto a single row, the width of each Item is compared with the remaining space on the row. The preferred width of the Item is used for this unless LAYOUT_SHRINK directive has been defined for the Item. If the LAYOUT_SHRINK directive is in place, the minimum size is used instead. If the size is wider than the remaining space, then a row break occurs and the Item is placed on the next row. After a row is detected to be full of Items, there may be leftover horizontal space that is not allocated to any Items. This remaining space of the row is proportionally distributed to the Items in that row by expanding the Item widths. The space is first allocated for Items that have LAYOUT_SHRINK (in other words, to the Items that had been sized to their minimum widths.) These Items are expanded at
143
144
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
most to their preferred sizes. If there is still leftover horizontal space after this, the rest of the space is distributed equally to those Items that use the LAYOUT_EXPAND directive. If there are no such Items, then the free space is left to the row and the Items in the row are horizontally aligned based on the horizontal alignment value shared by the Items. The row height is determined by the tallest Item in a row. The tallest Item is found by checking the heights of all the Items in the row. If an Item has LAYOUT_VSHRINK, its minimum height is used; otherwise, the Item’s preferred height is used in this check. After the row height is known, some of the Items in the row are expanded based on their vertical layout directives. Items that use the LAYOUT_VSHRINK directive are expanded to their preferred height or to the height of the row, whichever is smaller. Items that are still shorter than the row height and that use the LAYOUT_VEXPAND directive are expanded to the height of the row. The LAYOUT_VEXPAND directive on an Item will never increase the height of a row. Remaining Items shorter than the row height are positioned vertically within the row using the LAYOUT_TOP, LAYOUT_BOTTOM, and LAYOUT_VCENTER directives. If no vertical layout directive is specified, then the Item is aligned along the bottom of the row. The sample code below illustrates the use of the LAYOUT_EXPAND, LAYOUT_VEXPAND, and LAYOUT_TOP directives. Figure 10.3 shows how the Items are sized using these directives. The left part of the figure indicates the state before the directives have been applied and right part indicates the result of the directives. These Items have been set using the following directives: item1.setLayout(Item.LAYOUT_EXPAND); item2.setLayout(Item.LAYOUT_DEFAULT); item3.setLayout(Item.LAYOUT_EXPAND); item4.setLayout(Item.LAYOUT_TOP); item5.setLayout(Item.LAYOUT_DEFAULT) item6.setLayout(Item.LAYOUT_VEXPAND);
On the first Form row, item1 and item3 are horizontally expanded so that all empty space in the row is divided between these items. On the second row, item6 is first vertically expanded to the entire row height, and then item4 is aligned to the top of the row.
NEW FOR MIDP 2.0
item1
item2
item3
item4
item5
item6
Figure 10.3
item1 item4
item2 item5
item3 item6
Applying vertical and horizontal layout directives
10.9.6 Spacer Spacer is an Item whose only purpose is to add empty space to the Form layout. This can be done because Spacer allows its minimum size to be set. The minimum width is useful for allocating flexible amounts of space between Items in the same row of a Form. The example below illustrates the use of a horizontal Spacer. StringItem left = StringItem(null, “left“);
left
(spacer)
right
Spacer spacer = new Spacer(10, 2); StringItem right = StringItem(null, “right”); // Have spacer expand horizontally spacer.setLayout(Item.LAYOUT_EXPAND);
Note that the minimum height can be used for enforcing a particular minimum height in a row. For an unlocked Spacer, the preferred width is also the same as the minimum width set by the application.
10.10 New for MIDP 2.0 We have marked a number of topics in this chapter as New! with an icon in the book margin. Here is a summary of the most important new high-level user interface features of MIDP 2.0 described in this chapter. Classes TextBox and TextField have been improved to better control the display and input behavior by: • adding the ability to set a hint for the initial input character set from an extensible set of Unicode subsets (see the setInitialInputMode method),
145
146
CHAPTER 10
MIDP HIGH-LEVEL USER INTERFACE – FORM
• adding a constraint to restrict the input of decimal numbers, including decimal point fraction digits (see the setConstraints method with the DECIMAL constraint), • adding constraint modifiers PASSWORD, SENSITIVE, and NON_PREDICTIVE that restrict how the values are displayed or cached (see the setConstraints method), and • adding constraint modifier hints to indicate that the first letter or each word or sentence should be capitalized (see the setConstraints method). The functionality of the Form and Item classes has been significantly enhanced, as follows: • There are more directives to specify the layout of each Item relative to the previous and successive Item. The options include positioning left, right, center, top, vcenter, and bottom; vertical and horizontal expansion and shrinking; and the control of line breaks (see the getLayout and setLayout methods). •
functionality has been added to provide a way to create empty spaces in the Form layout (see the Spacer class).
Spacer
• New appearance modes plain, button, or hyperlink are available for StringItems and ImageItems. •
Commands can be added and removed from individual Items (see the addCommand
and removeCommand methods). • Interface ItemCommandListener can be used for defining context-sensitive command actions for Items (see the setItemCommandListener method). • Default command can be defined for each Item (see the setDefaultCommand method). • It is possible for a particular Item in a Form to be made current and brought into view of the user (see the Display.setCurrentItem method). • There is an ability to delete all of the Items in a Form using a single method call (see the deleteAll method). • Customized, application-specific Item types can be defined using the new class CustomItem.
NEW FOR MIDP 2.0
Strings
and StringItems displayed in Forms have been enhanced to allow:
• appearance modes for Strings to be plain, button, or hyperlink (see the constructor and getAppearanceMode methods), and • the setting and getting of the Font for a String (see the setFont and getFont methods). Images
and ImageItems used in Forms now allow:
• appearance modes for Images to be plain, button, or hyperlink (see the constructor and getAppearanceMode methods), and •
Images
used in Forms to be mutable (see the constructor and setImage meth-
ods). The Gauge class has been enhanced with explicit support for busy indicators to support: • continuous visual effects being automatically updated by the system, and • incremental visual effects by being updated by the application (see the setValue and setMaxValue methods). Class ChoiceGroup and interface Choice have been updated with the addition of: • a pop-up mode that is similar to exclusive choice except that the visual presentation shows the selected element and the list pops up only to select another element (see the constructor), • the ability to set and get the Font of each element (see the setFont and getFont methods), and • the ability to delete all of the elements in the ChoiceGroup with a single method (see the deleteAll method).
147
This page intentionally left blank
C H A P T E R
11
MIDP Low-Level User Interface Libraries While the high-level user interface API provides maximum portability and development ease, some applications require greater control over the user interface. The MIDP low-level user interface API is designed for applications that need precise placement and control of graphic elements as well as access to low-level input events. Typical examples of application components that might utilize the low-level user interface API are a game board, a chart object, or a graph. Using the low-level user interface API, an application can: • control precisely what is drawn on the display, • handle primitive events like key presses and key releases, and • access concrete keys and other input devices. Applications that program to the low-level user interface API can be portable if the application uses only the standard features; applications should stick to the platform-independent part of the low-level API whenever possible. This means that applications should not directly assume the presence of any keys other than those defined in class Canvas. Also, applications should inquire about the size of the display and adjust their behavior accordingly.
11.1 The Canvas API To directly use the display and the low-level user interface API, the developer uses the Graphics and Canvas classes. The Canvas class provides the display surface, its 149
150
CHAPTER 11
MIDP LOW-LEVEL USER INTERFACE LIBRARIES
dimensions, and callbacks used to handle key and pointer events and to paint the display when requested. The methods of this class must be overridden by the developer to respond to events and to paint the screen when requested. The Graphics class provides methods to paint lines, rectangles, arcs, text, and images to a Canvas or an Image. The combination of the event-handling capabilities of the Canvas and the drawing capabilities of the Graphics class allows applications to have complete control over the application region of the screen. These low-level classes can be used, for example, to create new screens, implement highly interactive games, and manipulate images to provide rich and compelling displays for J2ME devices. 11.1.1 Canvas Dimensions A Canvas does not necessarily have access to the entire screen of a J2ME device. Certain areas of the screen may be reserved for other purposes such as displaying network and battery information. In addition, the use of a title, Ticker, and Commands will further reduce the area available to a Canvas. The current dimensions of a Canvas can be obtained by calling the methods getWidth and getHeight. Furthermore, the sizeChanged method of class Canvas is called whenever the dimensions of the Canvas change, thereby allowing it to update its layout based on the new size. If an application needs to have as much screen space as possible, the setFullScreenMode method may be called to maximize the available area. When full screen mode is enabled, the Ticker and title are not shown even if they have been added to the Canvas. Commands are still shown, although the device may minimize the space used to display them; some devices may also hide system status indicators to maximize the area available for the Canvas. 11.1.2 Redrawing Mechanism The application is responsible for redrawing the screen whenever repainting is requested. The application implements the paint method in its subclass of Canvas. Painting of the screen is done on demand so that the device can optimize the use of graphics and screen resources, for example, by coalescing several repaint requests into a single call to the paint method of class Canvas. Requests to repaint the screen are made automatically by the device as needed; for example, when a Canvas is first shown or when a system dialog has been shown in front of the Canvas and then dismissed. The application itself may also request a repaint of the entire display by calling the repaint method of the Canvas object. If only part of the screen needs to be updated, another repaint
THE Canvas API
method can be given the location, width, and height of the region that needs to be updated. When the paint method is called, the clip region of the provided Graphics object corresponds to the region that needs to be painted (see Section 11.3.2, “Clipping.”) The paint method is responsible for rendering every pixel within the clip region and should not make assumptions about the current state of the pixels. Rendering operations will not affect pixels that lie outside of the clip region. The Canvas cannot render on top of other items on the screen such as the areas occupied by the title or Commands. The performance of graphic-intensive applications can be enhanced greatly by requesting repaints only for the region of the Canvas that changed, and implementing the paint method to only paint the area within the clip region. Since painting is done asynchronously, the application might need to wait for repaint requests to be completed before it can continue. The Canvas.serviceRepaints method blocks until all of the repaint requests queued have resulted in a paint call. If the device is double buffering the display, the Graphics.isDoubleBuffered method returns true. If so, the application need not separately buffer the drawing to get a clean update of the display. Otherwise, the application might be able to optimize its display updates by creating images before they are needed, and then drawing them to the display in its paint method. Use of images is described in Section 11.4, “Creating and Using Images.” 11.1.3 Drawing Model Graphics may be rendered either directly to the display or to an off-screen Image. The destination of the rendered graphics depends on the source of the Graphics object. A Graphics object for rendering to the display is passed to the Canvas object’s paint method. This is the only way to obtain a Graphics object whose destination is the display. The applications may draw using this Graphics object only for the duration of the paint method. A Graphics object for rendering to an off-screen image is obtained by calling the Image.getGraphics method on the desired Image. The Graphics object may be held indefinitely by the application, and drawing methods may be invoked on these Graphics objects at any time. 11.1.4 Canvas Visibility The display on a device is shared among native applications and MIDP applications. A particular application might or might not be displayed on the screen. When the
151
152
CHAPTER 11
MIDP LOW-LEVEL USER INTERFACE LIBRARIES
application’s choice of the current screen is a Canvas, the Canvas is notified when its visibility changes. The Canvas.showNotify and Canvas.hideNotify methods are invoked automatically on the Canvas when it is shown and hidden, respectively. The application should override these methods to be informed of changes in visibility. The paint method of the Canvas is called automatically when it is made visible, so the application does not need to call repaint explicitly. Show and hide notifications are useful if, for example, the Canvas is providing an animation that it should start when shown and stop when hidden.
11.2 Low-Level API for Events in Canvases 11.2.1 Key Events If the application needs to handle key events in its Canvas, it must override the Canvas methods keyPressed, keyReleased, and keyRepeated. When a key is pressed, the keyPressed method is called with the key code. If the key is held down long enough to repeat, the keyRepeated method is called for each repeated keyCode. When the key is released, the keyReleased method is called. Some devices might not support repeating keys, and if not, the keyRepeated method is never called. The application can check the availability of repeat actions by calling the method Canvas.hasRepeatEvents. MIDP target devices are required to support the ITU-T telephone keys. Key codes are defined in the Canvas class for the digits 0 through 9, *, and #. Although an implementation may provide additional keys, applications relying on these keys may not be portable. For portable applications, the action key mappings described below should be used whenever possible, since other key codes are device-specific. 11.2.2 Action Keys The Canvas class has methods for handling portable action events (also known as game actions) from the low-level user interface. The API defines a set of action events: UP, DOWN, LEFT, RIGHT, FIRE, GAME_A, GAME_B, GAME_C, and GAME_D. The device maps the action events to suitable key codes on the device; multiple keys may map to each game action. For example, a device with four navigation keys and a SELECT key in the middle could use those keys for mapping the action events, but it may also use the keys on the numeric keypad (such as 2, 4, 5, 6, and 8). An application should determine the appropriate action for a given key code by calling the method Canvas.getGameAction. If the logic of the application is
Graphics
based on the values returned by this method, the application is portable and runs regardless of the keypad design. The mapping between keys and the abstract action events does not change during the execution of an application. One of the device-specific key codes mapped to a particular action can be retrieved with the method Canvas.getKeyCode. However, since several keys may be mapped to a single action, comparing key events to these key codes is not recommended and Canvas.getGameAction should be used instead. 11.2.3 Pointer Events The Canvas class has methods that the application can override to handle pointer events. Pointer events are events that are generated from a pointing device such as a stylus. If the application needs to handle pointer events, it must override and implement the methods pointerPressed, pointerReleased, and pointerDragged. Not all MIDP target devices support pointer events, and therefore the pointer methods might never be called. The application can check whether the pointer and pointer motion events are available by calling Canvas.hasPointerEvents and Canvas.hasPointerMotionEvents.
11.3 Graphics All graphical operations are performed using a Graphics object. This object encapsulates a context for drawing to a particular target entity, including the current drawing color, clip region, line style, and so on. 11.3.1 Coordinate System The coordinate system’s default origin is located at the upper-left corner, with the numeric values of the x-coordinates monotonically increasing from left to right, and the numeric values of the y-coordinates monotonically increasing from top to bottom. Applications may assume that the horizontal and vertical values of the coordinate system represent equal distances on the actual device display. If the shape of the pixels of the device is significantly different from square, the device does the required coordinate transformation. The coordinate system represents the locations of pixels, not the pixels themselves. Pixels have a width and height equal to 1 and extend down and to the left
153
154
CHAPTER 11
Figure 11.1
MIDP LOW-LEVEL USER INTERFACE LIBRARIES
Pixel coordinate system showing the pixel at (4,3)
of their locating point. For example, the pixel in the upper-left corner of the display is defined as (0,0) and covers the area where 0 > 2) & 0x03)); // Adjust the view window so that the car is always // in the center of the screen mgr.setViewWindow(car.getRefPixelX()-(viewWidth/2), car.getRefPixelY()-(viewHeight/2), viewWidth, viewHeight); // Fill the background with dark gray g.setGrayScale(45); g.fillRect(0,viewOffset, viewWidth, viewHeight); // Render the layers (coins, track, and car) at the // appropriate location on the screen mgr.paint(g, 0, viewOffset); // Render the score g.setColor(0xFFFFFF); g.fillRect(0,0, viewWidth, viewOffset); g.setColor(0x000000); // Flush the screen buffer to the display flushGraphics(); } } }
12.8 New for MIDP 2.0 The Game API is an entirely new feature in MIDP 2.0. With the Game API, application developers can simplify the development of game applications by using a programming paradigm that is well suited to game applications. Since the Game API provides many operations that would otherwise be implemented by the application, the API can significantly reduce the size and complexity of game applications.
195
This page intentionally left blank
C H A P T E R
13
MIDP Sound API This chapter introduces the Sound API of MIDP 2.0. In the first version of the MIDP Specification, sound support was minimal. With the release of the MIDP Specification version 2.0, this area has now been significantly enhanced. A welldefined, scalable architecture for sound and multimedia has been created for devices running J2ME, with primary emphasis on mobile phones using the Mobile Information Device Profile. In addition to offering basic sound programming support in MIDP 2.0, an optional package called the Mobile Media API has been created to enable generic multimedia functionality. A diverse set of applications will benefit from sound and media support in J2ME devices. Examples of such applications include games, speech, and multimedia applications. The purpose of this chapter is to give the reader an overview of the MIDP 2.0 Sound API and the complementary optional package, the Mobile Media API (MMAPI), created by the Java Community Process effort JSR 135.
13.1 Overview of the MIDP 2.0 Sound API 13.1.1 MIDP Media Support MIDP devices range from low-end mass-market phones with basic sound support to high-end media phones with advanced audio and video rendering capabilities. To accommodate these diverse configurations and multimedia processing capabilities, an API with a high level of abstraction and support for optional features is needed. The central goal of the specification work for the Sound API was to address the wide range of application areas. As a result, two API sets were developed: • MIDP 2.0 Sound API • Mobile Media API (MMAPI) 197
198
CHAPTER 13
MIDP SOUND API
The division into two interoperable API sets arose from the fact that some devices are very resource-constrained. It may not be feasible to support a full range of multimedia types, such as video, on some mobile phones. As a result, not all MIDP 2.0 target devices are required to support the full generality of the Mobile Media API, such as the ability to support custom protocols and content types. MIDP Sound API The MIDP 2.0 Sound API is intended for resource-constrained devices such as mass-market mobile phones. The basic level of sound support mandated for all devices is the presence of monophonic buzzer tones. This API is a directly compatible subset of the full Mobile Media API. Furthermore, due to its building block nature, this subset API can be adopted to other J2ME profiles that require sound support. Mobile Media API The full Mobile Media API is intended for J2ME devices with advanced sound and multimedia capabilities. The target devices for the Mobile Media API include powerful mobile phones, as well as PDAs and set-top boxes. Applications Sound and media are a key feature in many applications. Games, music applications, user interface tones, and alerts are examples of application areas that will benefit from the MIDP Sound API. In the following sections, the MIDP Sound API is discussed in more detail. In Section 13.4, “Enhanced Media Support Using the Mobile Media API,” a more detailed look at the MMAPI is provided. 13.1.2 Design Goals The main design goals for the MIDP Sound API were: • Playback of time-based audio and ringing tones. This is the main feature of the sound API. The basic target of the design is to let applications play back media in various formats. • Independence of specific media formats and protocols. The sound API itself is not targeted to support any specific media format or protocol. There are no
OVERVIEW OF THE MIDP 2.0 SOUND API
hard-coded format descriptors in the API. Rather, the formats are handled as MIME types. This provides extensibility and support for future formats. However, in MIDP Specification version 2.0, a set of mandatory protocols and content formats for audio have been defined to ensure interoperability. • Support for tone generation. There is an internal tone sequence format and a method to play single tones. An internal tone sequence format has been added to the API in order to let MIDP applications create simple monophonic tone sequences on their own. 13.1.3 Requirements The design goals stated in the previous section form a set of requirements, which have to be fulfilled by all devices implementing the sound API. The requirements that were defined in MIDP Specification version 2.0 include • low footprint audio playback, • protocol and content format independence, • support for tone generation, • support for general media flow controls (start, stop, etc.), • support for media-specific type controls (such as volume control), and • support for capability queries. This subset differs from the full Mobile Media API requirements in the following ways: • The MIDP 2.0 sound API is audio-only. It excludes all Control classes that are specific to MIDI, video, or graphics. • The sound API does not support custom protocols (via custom DataSource classes). Scalability It is important to note that the building block subset used in MIDP 2.0 is a proper subset of the full Mobile Media API (MMAPI), and it is fully forward-compatible with the MMAPI. In order to add the full Mobile Media API functionality to a MIDP 2.0 device, one only needs to implement the additional classes and methods from that API.
199
200
CHAPTER 13
MIDP SOUND API
Formats and protocols In the context of sound and multimedia processing, protocol handling refers to reading data from a source (such as a file or streaming server) into a media processing system. Content handling usually requires processing the media data (parsing or decoding, for example) and rendering the media to output devices such as a loudspeaker. The MIDP 2.0 sound API is defined in a manner that enables the custom formats and protocols. At the very minimum, the devices must be able to play tones, either via dedicated hardware or via software algorithm. Furthermore, MIDP 2.0 devices • must support tone generation in the media package, • must support 8-bit, 8 KHz, mono linear PCM wav format if any sampled sound support is provided, • may include support for additional sampled sound formats, • must support Scalable Polyphony MIDI (SP-MIDI) and SP-MIDI Device 5-to-24 Note Profile if any synthetic sound support is provided, and • may include support for additional MIDI formats. In other words, the basic requirement for sound support for all mobile information devices is monophonic tone sequencing. Both synthetic audio (MIDI) and sampled audio are optional, and these features may be implemented if the device provides corresponding hardware or software support. The audio content used by MIDlets normally originates in a MIDP 2.0 implementation from three different sources: 1) over-the-air via HTTP 1.1 protocol, 2) via the Record Management System (RMS), or 3) from a JAR file. It should be noted that whereas the sound API supports a generic protocol naming mechanism, MIDP 2.0 only supports HTTP 1.1. With the use of the full Mobile Media API, custom protocols for media streaming can be introduced. 13.1.4 MIDP Sound Architecture The MIDP sound architecture design was based on a set of design goals and requirements agreed to by the MIDP 2.0 expert group. A baseline for sound support that all devices must follow was created. Optional features may be supported, but they are not mandated by the MIDP Specification. The framework of sound and media support in MIDP 2.0 consists of three main components: Manager, Player, and Controls. Figure 13.1 shows an overview of the architecture. A simple way to understand the functionality of the Sound API
OVERVIEW OF THE MIDP 2.0 SOUND API
is to think of the functionality of an ordinary video player (VCR). Class Manager represents the VCR user who loads the tape into the VCR and controls the overall use. The technical functionalities of the VCR, such as playing, stopping, rewinding, or recording, are represented by the Player class. Finally, the Control classes define the actions that determine how the VCR is controlled, for example, by adjusting the volume or by initiating the recording mode.
Manager
creates
Content origin Http, RMS, JAR, etc.
feeds data
Player provides
Control Control
Figure 13.1 Overview of MIDP Sound API Architecture
In more technical terms, the functionality of the sound architecture can be described as follows. Class Manager is the access point for obtaining systemdependent resources such as Player objects for multimedia processing. Applications use the Manager class to request Players and to query supported content types and supported protocols. The Manager class also includes a method to play simple tones. A Player is an object that is used to control and render media that is specific to the content type of the data. The application may obtain a Player by giving a locator string or an InputStream and a content type to the Manager class. A Control is an interface that is used to implement all of the different controls a Player might have. An application can query a Player to check which controls it supports and then ask for a specific Control—for example, VolumeControl—to control volume.
201
202
CHAPTER 13
MIDP SOUND API
13.2 Player Creation and Management In this section, the process of creating and managing sound in a MIDP 2.0 application is described. The functionality of classes Manager and Player are described, and simple application examples are provided to illustrate the details of the API. Figure 13.2 shows the class diagram of the MIDP 2.0 Sound API. (Interfaces are shown in italic font.)
Manager creates
Controllable
Player
Control
ToneControl
VolumeControl
Figure 13.2 Class diagram of the MIDP Sound API
13.2.1 Managing a Media Framework The entry point to the Sound API is the Manager class. Class Manager provides access to an implementation-specific mechanism for constructing Player objects. In addition, class Manager provides means for property queries of content and protocol support. For convenience, it also provides a simplified method to generate simple tones. Property queries The MIDP sound API provides a mechanism for querying the type of content and protocols that the device supports. The property queries are enabled by the methods Manager.getSupportedContentTypes and Manager.getSupportedProtocols. For example, if the given protocol is “http:”, then the supported content types that can be played back with the http protocol will be returned. If null is passed in as the protocol, all the supported content types for this device will be returned. The returned array must be non-empty; in other words, at least one content type has to be supported.
PLAYER CREATION AND MANAGEMENT
13.2.2 Creating Players for Media Data The Player interface controls the rendering of time-based media data. It provides the methods to manage the life cycle of the Player, controls the playback progress, and obtains the presentation components. A Player can be created using one of the two createPlayer methods of the Manager class: // Create a Player to play back media from an InputStream createPlayer(java.io.InputStream stream, String type) // Create a Player from an input locator createPlayer(String locator)
When a Player is created from an InputStream, the type argument specifies the content type of the input media. If null is given, Manager will attempt to determine the type. However, since determining the media type is non-trivial for some media types, it may not be feasible in some cases; Manager may throw a MediaException to indicate the occurrence of such a situation. A Player can also be created using a locator. In this case, a locator string is given in URI syntax that describes the media content. After the Player object is created, it will enter the STARTED state when the program calls the method Player.start. This method will start the playback as soon as possible and will return when the playback is started. The playback will continue in the background and will stop automatically when the end of media is reached. The MIDP Sound API Player states are described in detail in Figure 13-3 and in “Player life cycle” on page 204. Data sources for media Content types identify the type of media data for Player objects when the Player is created using an InputStream. These content types are defined to be the registered MIME types1. In addition, there are some user-defined types that generally follow the MIME syntax (RFC 2045, RFC 2046). For example, here are a few common content types: • Tone sequences: audio/x-tone-seq • Wave audio files: audio/x-wav 1.
See http://www.iana.org/assignments/media-types/ for details of registered MIME types for media.
203
204
CHAPTER 13
MIDP SOUND API
• AU audio files: audio/basic • MP3 audio files: audio/mpeg • MIDI files: audio/midi When a Player is created using a media locator, the locator is specified in URI syntax defined in the following form: :
The “scheme” part of the locator string identifies the name of the protocol being used to deliver the data. For instance, "http://webserver/music.mid” is an example of a valid locator string. Player life cycle A typical media player features the basic commands (or state transition methods) for starting and stopping media playback. In resource-constrained devices, however, special care must be taken to optimize the media playback process for applications. Therefore, the MIDP 2.0 media player architecture features additional states, which are described in more detail below. Figure 13.3 shows a state diagram that illustrates the MIDP 2.0 Player life cycle. The Player object has five states: UNREALIZED, REALIZED, PREFETCHED, STARTED, and CLOSED. The purpose of these life-cycle states is to provide programmatic control over the use of media resources and potentially time-consuming operations. For example, when a Player is first constructed, it’s in the UNREALIZED state. When the state changes from UNREALIZED to REALIZED, the Player performs the communication necessary to locate all of the resources it needs to function (such as communicating with a server or a file system). The realize method allows an application to initiate this potentially time-consuming process at an appropriate time. Typically, a Player moves from the UNREALIZED state to the REALIZED state, then to the PREFETCHED state, and finally on to the STARTED state. A Player stops when it reaches the end of media or when the stop method is invoked. When that happens, the Player moves from the STARTED state back to the PREFETCHED state. Upon calling the Player.stop method, the playback position in the file does not change, so calling Player.start again will continue the playback from the same location. In Figure 13.3, the gray-shaded boxes represent the reservation of audio resource in hardware.
PLAYER CREATION AND MANAGEMENT
Manager.createPlayer
Unrealized realize close Realized deallocate
Closed
prefetch
close
close
start Prefetched
Started stop
Figure 13.3 MIDP Sound API Player state diagram
The basic use of a Player only requires the Player.start and Player.stop methods. However, in order to fully utilize all the functionality of the Player, parameters must be set up appropriately to manage the life-cycle states, and the state transition methods should be used correctly to advance between the various Player states. Additional Player functionalities include looping of audio using the setLoopCount method, and obtaining or setting the current position of media playback using the getMediaTime and setMediaTime methods. Furthermore, the getDuration method can be used to query the length of the media file. PlayerListener Class PlayerListener defines an interface that can be used for receiving asynchronous events generated by Player objects. Applications can implement this interface and register their implementations with the addPlayerListener method of class Player. A number of standard Player events are defined in the PlayerListener interface. Event types are defined as Strings in order to support extensibility because different implementations may introduce proprietary events by adding new event types. The predefined, standard event types are as follows: •
CLOSED.
•
DEVICE_AVAILABLE. Posted when the system or another higher priority applica-
Posted when a Player is closed. The Player may be closed either by the user, or it may be closed by the system after an irrecoverable error has occurred. tion has released an exclusive device that is now available to the Player.
205
206
CHAPTER 13
•
MIDP SOUND API
DEVICE_UNAVAILABLE. Posted when the system or another higher priority appli-
cation has temporarily taken control of an exclusive device that was previously available to the Player. •
DURATION_UPDATED.
Posted when the duration of a Player is updated.
•
END_OF_MEDIA.
•
ERROR.
•
STARTED.
Posted when a Player is started.
•
STOPPED.
Posted when a Player stops in response to the stop method call.
•
VOLUME_CHANGED.
Posted when a Player has reached the end of the media.
Posted when an error had occurred.
Posted when the volume of an audio device is changed.
The playerUpdate method is called to deliver an event to a registered listener when a Player event is observed. 13.2.3 Tone Generation The minimal requirement for all MIDP 2.0 devices is to support the playback of monophonic single tones. Tone generation is important for games and other audio applications. On resource-constrained devices, this is particularly important since tone generation is likely to be the only form of audio capabilities supported. In its simplest form, tone generation is implemented as a single buzzer or simple monophonic tone generation. This feature is enabled by two different methods in the MIDP 2.0 API. The first possibility is to use the Manager class, which provides a method for playing back simple tones (see Section 13.2.4, “Sample Code,” for an example), specified by a note and its duration. A note is given in the range of 0 to 127 inclusive. The frequency of the note can be calculated using the following formula: SEMITONE_CONST = 17.31234049066755 = 1/(ln(2^(1/12))) note = ln(freq/8.176)*SEMITONE_CONST // The musical note A = MIDI note 69 (0x45) = 440 Hz.
This call is a non-blocking call. Notice that this method may utilize CPU resources significantly on devices that do not have hardware support for tone generation. The second possibility to create sequences of single tones is to use the ToneControl API. The use of this API is discussed in more detail in Section 11.3.1.
PLAYER CREATION AND MANAGEMENT
13.2.4 Sample Code In this section, a few simple examples are provided to illustrate tone generation and the creation of new Players using the methods of class Manager. Example: Single tone generation try { Manager.playTone(ToneControl.C4 /* note */, 5000
/* duration in ms */,
100
/* max vol */);
} catch (MediaException e) { }
Example: Creating a player from media stored in JAR Notice that in MIDP 2.0 the wav format is mandatory only in case the device supports sampled audio. try { InputStream is = getClass().getResourceAsStream("music.wav"); Player p = Manager.createPlayer(is, "audio/X-wav"); p.start(); } catch (IOException ioe) { } catch (MediaException me) { }
Example: Creating a player from media in HTTP locator try { Player p = Manager.createPlayer("http://webserver/music.mid"); p.start(); } catch (IOException ioe) { } catch (MediaException me) { }
Notice that in MIDP 2.0, the MIDI format (SP-MIDI) is mandatory only when the device supports sampled audio.
207
208
CHAPTER 13
MIDP SOUND API
13.3 Media Controls objects are used for controlling content-type-specific media processing operations. The set of operations are usually functionally related. Thus a Control object provides a logical grouping of media-processing functions. All Control classes implement the interface Controllable, and the Player interface is a subinterface of Controllable. Therefore, a Player implementation can use the Control interface to extend its media-processing functions. For example, a Player can expose a VolumeControl to allow the volume level to be set. The javax.microedition.media.control package specifies a set of predefined Controls classes. In MIDP 2.0, two controls are specified and required: ToneControl and VolumeControl. The Controllable interface provides a mechanism for obtaining the Controls from an object such as a Player. It provides methods to get all the supported Controls and to obtain a particular Control based on its class name. Control
13.3.1 ToneControl is an interface that enables the playback of a user-defined monotonic tone sequence. A tone sequence is specified as a list of tone duration pairs and userdefined sequence blocks. The list is packaged as an array of bytes. The setSequence method is used for defining the sequence for the ToneControl. Here is the syntax of a tone sequence, described using an Augmented BNF notation. (See http://www.ietf.org/rfc/rfc2234 for details of the Augmented BNF notation.) ToneControl
sequence
= version *1tempo_definition *1resolution_definition *block_definition 1*sequence_event
version
= VERSION version_number
VERSION
= byte-value
version_number
= 1
tempo_definition
= TEMPO tempo_modifier
TEMPO
= byte-value
tempo_modifier
= byte-value
; version # 1
; multiply by 4 to get the tempo (in bpm) used ; in the sequence.
MEDIA CONTROLS
resolution_definition = RESOLUTION resolution_unit RESOLUTION
= byte-value
resolution_unit
= byte-value
block_definition
= BLOCK_START block_number 1*sequence_event BLOCK_END block_number
BLOCK_START
= byte-value
BLOCK_END
= byte-value
block_number
= byte-value
; block_number specified in BLOCK_END has to be ; the same as the one in BLOCK_START sequence_event
= tone_event / block_event / volume_event / repeat_event
tone_event
= note duration
note
= byte-value ; note to be played
duration
= byte-value ; duration of the note
block_event
= PLAY_BLOCK block_number
PLAY_BLOCK
= byte-value
block_number
= byte-value
; block_number must be previously defined ; by a full block_definition volume_event
= SET_VOLUME volume
SET_VOLUME
= byte-value
volume
= byte-value ; new volume
repeat_event
= REPEAT multiplier tone_event
REPEAT
= byte-value
multiplier
= byte-value
; number of times to repeat a tone byte-value
= -128 - 127
; the value of each constant and additional ; constraints on each parameter are specified below
Note that VERSION, TEMPO, RESOLUTION, BLOCK_START, BLOCK_END, PLAY_BLOCK, and SET_VOLUME REPEAT are predefined constants.
209
210
CHAPTER 13
MIDP SOUND API
Example: Tone sequencing The following example illustrates the use of tone sequencing by playing the familiar song “Mary Had a Little Lamb.” /** * "Mary Had A Little Lamb" has "ABAC" structure. * Use block to repeat "A" section. */ byte tempo = 30; // set tempo to 120 bpm byte d = 8;
// eighth-note
byte C4 = ToneControl.C4;; byte D4 = (byte)(C4 + 2); // a whole step byte E4 = (byte)(C4 + 4); // a major third byte G4 = (byte)(C4 + 7); // a fifth byte rest = ToneControl.SILENCE; // rest byte[] mySequence = { ToneControl.VERSION, 1,
// version 1
ToneControl.TEMPO, tempo,
// set tempo
ToneControl.BLOCK_START, 0,
// start define "A" section
E4,d, D4,d, C4,d, E4,d,
// content of "A" section
E4,d, E4,d, E4,d, rest,d, ToneControl.BLOCK_END, 0,
// end define "A" section
ToneControl.PLAY_BLOCK, 0,
// play "A" section
D4,d, D4,d, D4,d, rest,d,
// play "B" section
E4,d, G4,d, G4,d, rest,d, ToneControl.PLAY_BLOCK, 0,
// repeat "A" section
D4,d, D4,d, E4,d, D4,d, C4,d
// play "C" section
}; try { Player p = Manager.createPlayer( Manager.TONE_DEVICE_LOCATOR); p.realize(); ToneControl c = (ToneControl)p.getControl("ToneControl"); c.setSequence(mySequence); p.start(); } catch (IOException ioe) { } catch (MediaException me) { }
MEDIA CONTROLS
13.3.2 VolumeControl is an interface for manipulating the audio volume of a Player object. The volume settings interface allows the output volume to be specified using an integer value that varies between 0 and 100. The level scale specifies volume in a linear scale. It ranges from 0 to 100, where 0 represents silence and 100 represents the highest volume. The mapping for producing a linear multiplicative value is implementation-dependent. Setting mute on or off does not change the volume level returned by method getLevel. If mute is true, no audio signal is produced by the Player; if mute is false, an audio signal is produced and the volume is restored. When the state of the VolumeControl changes, a VOLUME_CHANGED event is delivered to the Player through its PlayerListener. VolumeControl
13.3.3 Custom Controls MIDP Specification version 2.0 defines only two custom controls: ToneControl and VolumeControl. Additional controls are available in the Mobile Media API. These features are discussed in more detail in Section 13.4, “Enhanced Media Support Using the Mobile Media API.” 13.3.4 Sample Code The sample application below defines a simple media player for sampled audio with an attached volume control. The Player is created from an InputStream. A Gauge is used for visualizing and controlling the volume of the player. Simple player functions including start, stop, and rewind are supported. Furthermore, PlayerListener events are defined for printing the player states during the execution of the program. Note that in MIDP 2.0, the wav format is mandatory only when the device supports sampled audio. PlayerMidlet.java import javax.microedition.midlet.*; import javax.microedition.lcdui.*; /** * Simple music player application using the MIDP 2.0 Sound API */ public class PlayerMidlet extends MIDlet implements CommandListener, ItemStateListener {
211
212
CHAPTER 13
MIDP SOUND API
Display display; Command exitCommand = new Command("Exit", Command.EXIT, 99); Command stopCommand = new Command("Stop", Command.ITEM, 1); Command startCommand = new Command("Start", Command.ITEM, 1); Command rewindCommand = new Command("Rewind", Command.ITEM, 2); Form form; Source source; Gauge gauge; int itemNum; public PlayerMidlet() { display = Display.getDisplay(this); // Create the form form = new Form("MIDP 2.0 sound demo"); form.addCommand(startCommand); form.addCommand(exitCommand); form.setCommandListener(this); // Set up interactive gauge for the volume control gauge = new Gauge("Player Volume", true, 100, 50); form.append(gauge); gauge.setLayout(0x800); itemNum = form.append("Value: " + gauge.getValue()); form.setItemStateListener(this); // Instantiate player source = new Source("/sound.wav"); } protected void startApp() throws MIDletStateChangeException { display.setCurrent(form); } protected void pauseApp() { source.stop(); } protected void destroyApp(boolean unconditional) throws MIDletStateChangeException { source.destroy(); }
MEDIA CONTROLS
/** * Define the gauge updates */ public void itemStateChanged(Item item) { if (item == gauge) { // Set the current gauge value to the player volume source.setLevel(gauge.getValue()); form.delete(itemNum); form.append("Value: " + gauge.getValue()); } } /** * Respond to commands issued on the form */ public void commandAction(Command c, Displayable s) { if (c == stopCommand) { source.stop(); form.removeCommand(stopCommand); form.addCommand(startCommand); form.addCommand(rewindCommand); } else if (c == startCommand) { source.start(); form.removeCommand(startCommand); form.removeCommand(rewindCommand); form.addCommand(stopCommand); } else if (c == rewindCommand) { source.rewind(); form.removeCommand(rewindCommand); } else if (c == exitCommand) { try { destroyApp(false); notifyDestroyed(); } catch (MIDletStateChangeException e) { } } } }
213
214
CHAPTER 13
MIDP SOUND API
Source.java import javax.microedition.media.*; import javax.microedition.media.control.*; import java.io.*; public class Source implements PlayerListener { Player p; VolumeControl volC; Source(String fileName) { // Define input stream to read from the sound file InputStream is = getClass().getResourceAsStream(fileName); if (is == null) { System.out.println("Error creating InputStream " + fileName); } try { // Create player: give input stream and media type. // In this demo the sound file is in WAV format. p = Manager.createPlayer(is, "audio/X-wav"); if (p == null) { System.out.println("Error creating Player " + fileName); } else { p.addPlayerListener(this); p.realize();
// Realize the player
p.prefetch();
// Prefetch the player
p.setLoopCount(-1); // Play indefinitely System.out.println("Realized Player: " + fileName); } } catch (IOException e) { System.out.println(e); } catch (MediaException e) { System.out.println(e); }
MEDIA CONTROLS
// Obtain volume control for the player volC = (VolumeControl)p.getControl("VolumeControl"); } public void destroy() { if (p != null) { // Close the player p.close(); } } public void start() { if (p != null) { try { // Start the player from current media time p.start(); } catch (MediaException e) { System.out.println(e); } } } public void stop() { if (p != null && p.getState() == Player.STARTED) { try { // Stop the player. Note that player // does not rewind to beginning when // stop is called p.stop(); } catch (MediaException e) { System.out.println(e); } } } public void rewind() { if (p != null && p.getState() == Player.PREFETCHED) { try { // Rewind the player to beginning by setting // media time to a negative value p.setMediaTime(-1);
215
216
CHAPTER 13
MIDP SOUND API
} catch (MediaException e) { System.out.println(e); } } } public int setLevel(int level) { // Update the player volume return volC.setLevel(level); } /** * Define the player updates */ public void playerUpdate(Player p, String event, Object eventData) { if (event == STARTED) System.out.println("Player started"); else if (event == STOPPED) System.out.println("Player stopped"); else if (event == END_OF_MEDIA) System.out.println("Player at end of file"); else if (event == VOLUME_CHANGED) System.out.println("Player volume changed"); else if (event == CLOSED) System.out.println("Player closed"); } }
ENHANCED MEDIA SUPPORT USING THE MOBILE MEDIA API
13.4 Enhanced Media Support Using the Mobile Media API As discussed earlier in this chapter, MIDP Sound API is a subset of the Mobile Media API (MMAPI) defined by the Java Community Process effort JSR 135. MMAPI includes a lot of additional functionality that is not present in the MIDP 2.0 Sound API. The additional features introduced by the Mobile Media API include the following: • Custom protocols through the DataSource • Synchronization of multiple Players using the TimeBase interface • Interactive synthetic audio • Video and camera functionality • Capture and recording • Metadata The scalability and optional use of the API is crucial for the successful deployment of the API in mobile devices. It is clear that not all implementations of MMAPI will support all multimedia types and input protocols. For example, some of the devices may support only playback of local audio files. The design of the MMAPI allows implementations to provide optional support for different media types and protocols. As with the MIDP 2.0 Sound API, class Manager provides the getSupportedContentTypes and getSupportedProtocols methods to query for supported media types and protocols. An application can also attempt to create a Player from class Manager given the media input. If the content type or the protocol specified is not supported, the Player creation methods will throw an exception. Because MMAPI is an optional package, it does not mandate any particular media types or protocols. Required types and protocols are to be determined by the appropriate profiles adopting MMAPI (for example MIDP 2.0). However, an implementation must guarantee support of at least one media type and protocol. MMAPI also allows implementations to support optional features. For example, some implementations may support only media playback but not recording. MMAPI allows implementations to expose these optional features as applicable. Optional features are organized as Control classes. A Player can be queried for all of its supported Controls using the method getControls or a particular type of Control using the method getControl.
217
218
CHAPTER 13
MIDP SOUND API
MMAPI mandates support of some features for some media types. Other features are recommended while others are entirely optional. This guarantees some uniformity across different implementations. The implementation alternatives are categorized into features sets. When a Player is created for a particular type, it must follow the guidelines given in the specification and implement the appropriate Control types. The following feature sets are defined for five different types of media: • tone sequence (controls for built-in monophonic tone sequence format), • sampled audio (controls for handling sampled audio data), • interactive MIDI (controls for handling MIDI event streaming, for example, in games), • MIDI (controls for full-functionality synthetic audio applications), and • video (controls for video playback and still-image capture support.) 13.4.1 DataSource Class DataSource encapsulates protocol handling. It hides the details of how the data is read from its source, and whether the data is coming from a file, streaming server, or a proprietary delivery mechanism. Class DataSource provides a set of methods to allow a Player to read data. 13.4.2 Advanced Controls MMAPI defines a total of 12 rized in Table 13.1.
Control
classes. These
Control
classes are summa-
Table 13.1 Mobile Media API controls MMAPI Controls
Overview
FramePositioningControl
Interface to control precise positioning to a video frame for Players.
GUIControl
Extends Control and is defined for controls that provide GUI functionality.
MetaDataControl
Used to retrieve metadata information included within the media streams.
MIDIControl
Provides access to MIDI rendering and transmitting devices.
NEW FOR MIDP 2.0
Table 13.1 Mobile Media API controls MMAPI Controls
Overview
PitchControl
Raises or lowers the playback pitch of audio without changing the playback speed.
RateControl
Controls the playback rate of a Player.
RecordControl
Controls the recording of media from a Player. This control records what is currently being played by the Player.
StopTimeControl
Specifies a preset stop time for a Player.
TempoControl
Controls the tempo, in musical terms, of a song.
ToneControl
Interface to enable playback of a user-defined monotonic tone sequence.
VideoControl
Controls the display of video and provides a method for taking snapshots.
VolumeControl
Interface for manipulating the audio volume of a Player.
The ToneControl and VolumeControl interfaces are specified in the MIDP 2.0 Sound API. For video and camera functionality, FramePositioningControl and GUIControl are provided. MIDI specific controls include MIDIControl for controlling a sound synthesizer using MIDI messages, PitchControl for changing the pitch in music applications (such as Karaoke), RateControl for changing the playback rate of a player, and TempoControl for controlling the playback tempo of a song. Additional controls include MetaDataControl, which allows the addition of auxiliary data related to a media stream, and StopTimeControl, which allows for setting a preset stop time for playback. The set of controls in the MMAPI specification provides a versatile means for creating audio, MIDI, video, and camera support in MIDlets. In future releases of the API, new controls may be introduced.
13.5 New for MIDP 2.0 In the MIDP Specification version 1.0, sound support was minimal. With the release of the MIDP Specification version 2.0, sound support has been significantly extended. A well-defined, scalable Sound API has been created for devices supporting the Mobile Information Device Profile. A diverse set of applications—including games and media applications—will benefit from the MIDP 2.0 Sound API.
219
This page intentionally left blank
C H A P T E R
14
MIDP Persistence Libraries The MIDP Specification provides a mechanism for MIDlets to persistently store data and retrieve it later. This persistent storage mechanism, called the Record Management System (RMS), is modeled after a simple, record-oriented database. This chapter introduces the key features and characteristics of the Record Management System.
14.1 The Record Management System Conceptually, RMS provides records and record stores, as shown in Figure 14.1. A record store is a collection of records that is persistent across multiple invocations of a MIDlet. Each record is an array of bytes. Each record in a record store can be of a different length and can each store data differently. For example, in Figure 14.1 the topmost record, Record ID 1, may contain a String followed by an int, while the second record, Record ID 5, may contain an array of short numbers. Associated with each record in a record store is a unique identifier called the recordId. This identifier can be used to retrieve a record from the record store (see getRecord in Section 14.2.3, “Manipulating Records in a Record Store”). In Figure 14.1, “adjacent” records in the record store do not necessarily have consecutive recordIds. The underlying implementation may in fact reorganize records within the store or place two consecutively placed records in “far” apart locations. All that is guaranteed is that if a record is added to the record store, it will retain its recordId until deleted. A recordId is assigned via a monotonically, increasingby-one algorithm. There is no provision for “wrap around” of recordIds. However, since the data type for recordIds is an integer that is capable of storing a number as large as 2,147,483,647, it is highly unlikely that a given recordId will ever be reused within a record store, especially since mobile information devices usually have limited persistent storage. 221
222
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
recordId 1 recordId 5 recordId 10 recordId 2 RecordStore
Figure 14.1 Structure of a record store MIDlets within a MIDlet suite can access one another’s record stores directly; however, no locking operations are provided by the RMS. Therefore, if a MIDlet suite uses multiple MIDlets or threads to access a record store, it is the developer’s responsibility to coordinate these access operations with the synchronization primitives provided by the Java programming language. Note that the system software of the mobile information device is responsible for maintaining the integrity of RMS record stores throughout the normal use of the platform, including reboots, battery changes, and so forth. Therefore, the programmer does not have to worry about these issues. The sharing of RMS record stores is controlled by the MIDP application model (see Section 19.1.4, “MIDlet Suite Execution Environment”). Under this model, record stores are shared by all MIDlets within a MIDlet suite but are not normally shared with other MIDlet suites. For example, in Figure 14.2, the record store called Alpha of MIDlet_Suite_1 is separate and distinct from the record store Alpha of MIDlet_Suite_2. Therefore, MIDlet_Suite_1 cannot access the record stores of MIDlet_Suite_2 and vice versa. Note that in MIDP 2.0, mechanisms were added such that a MIDlet suite can make one or more of its record stores available to MIDlets in all MIDlet suites installed on the device. This is described further in Section 14.2.2, “Shared Record Stores.”
MANIPULATING RECORD STORES AND RECORDS
MIDIet_Suite_1
MIDIet_Suite_2
MID_1
MID_1
Alpha
MID_2
Omega
MID_2
Alpha
Figure 14.2 Separation of RMS name spaces
14.2 Manipulating Record Stores and Records Record stores have two basic types of operations: those that deal with manipulating the record store as a whole and those that deal with manipulating the records within the record store. A summary of different record store and record manipulation operations is provided in the following sections. 14.2.1 Manipulating a Record Store The programmer accesses record stores by name. These names are case-sensitive and may contain between 1 and 32 Unicode characters. The name space for record stores is a flat, non-hierarchical space.1 Within a MIDlet suite, record store names are unique. In other words, MIDlets within a MIDlet suite are not allowed to create more than one record store with the same name. On the other hand, no such restriction applies to different MIDlet suites: a MIDlet within one MIDlet suite is allowed to have a record store with the same name as a MIDlet in another MIDlet suite. In that case, the record stores are distinct and separate. A MIDlet can obtain a list of all the record stores owned by 1.
Note: The name space of record stores is separate from that of resources (resources are accessed by calling the method java.lang.Class.getResourceAsStream.) Thus, the name of a record store can be lexically equivalent to that of a resource, but the two are separate entities.
223
224
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
the containing MIDlet suite by calling the class static method listRecordStores of class RecordStore. In order to access a record store, the record store must be opened first. A MIDlet can open one of its record stores with the method openRecordStore that takes two parameters: a String containing the name of the record store, and a boolean indicating whether the record store should be created if it does not exist yet. The method openRecordStore returns an object of type RecordStore, which provides access to the following methods that return information about the associated record store: •
getName: returns a String that represents the name with which this record was
opened or created. •
getNumRecords: returns an int that represents the number of records currently
in the record store. •
getSize:
•
getSizeAvailable:
•
getNextRecordID:
•
getVersion: returns an int that represents the version of the record store. Each
returns an int that represents the current number of bytes contained in the record store. returns an int that represents the number of remaining bytes in the device that the record store could potentially occupy. Note that the number returned by this method is not a guarantee that the record store can actually grow to this size, since another MIDlet may allocate space for another record store.
returns an int that represents the recordId for the next record added to the record store. time a record is added, deleted, or modified in the record store, the version number of the record store is incremented by 1.
•
returns a long that represents the last modification time of the record store. The time returned is in the same format as used by method System.currentTimeMillis. The modification time of a record store is changed each time its version changes (see the description above.) getLastModified:
The two final operations on a record store are closing and deleting it. A record store is closed by invoking the method closeRecordStore. Note that a record store is not closed until all outstanding opens have been matched with a corresponding close operation. In other words, as long as there are open references to a record store, it will not be closed. When a record store is finally closed, all record listeners are removed (see Section 14.2.5, “Filtering, Comparing, Listening, and Enu-
MANIPULATING RECORD STORES AND RECORDS
merating Records”), and any attempts to perform any operations on the record store object cause a RecordStoreNotOpenException to be thrown. A record store is deleted by passing its name as a String to the static method deleteRecordStore of class RecordStore. A record store must be closed before it can be deleted. 14.2.2 Shared Record Stores New APIs in MIDP 2.0 allow for the explicit sharing of record stores if the MIDlet creating the record store chooses to give such permission. At the time of record store creation, a MIDlet can choose whether the record store should be available only to MIDlets within its MIDlet suite or available to all MIDlets installed on the device. If a record store is shared, the MIDlet can also choose whether MIDlets in other MIDlet suites should have read-only access or be allowed to write to the record store. There are no fine-grained access controls available for granting access to only a subset of the MIDlets on a device. To create a shared record store, the MIDlet calls the openRecordStore method, which takes four parameters: • a String containing the name of the record store, • a boolean indicating whether the records store should be created (if it does not yet exist), • an integer indicating the access mode requested (shared or private), and • a boolean indicating whether MIDlets from other MIDlet suites are granted write access to the record store, or only read-only access. Sharing is accomplished through the ability to name a record store created by another MIDlet suite. That is, record stores are identified using the unique name of the MIDlet suite plus the name of the record store. MIDlet suites are identified by the MIDlet-Vendor and MIDlet-Name attributes from the manifest and/or application descriptor (see Section 19.1.3, “MIDlet Attributes”). To open a shared record store from another MIDlet suite, the MIDlet calls the openRecordStore method that takes three String parameters: the name of the record store, and the vendor name and MIDlet suite name of the MIDlet suite that created the shared record store. As described in Section 19.3.2, “MIDlet Suite Removal,” when a MIDlet suite is deleted all of its record stores are also removed. This includes any shared record stores that it owns.
225
226
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
14.2.3 Manipulating Records in a Record Store Within a record store, individual records can be added, retrieved, modified, and deleted. The most common methods for manipulating records are summarized below: •
addRecord:
•
deleteRecord:
•
getRecordSize:
•
getRecord: has two forms: The first form takes a recordId as a parameter and
takes a byte array, an offset, and a length as parameters. A recordId is returned for a record created from the byte array subset starting at the given offset through the given length. Note that this is a blocking operation and the method will not return until the record has been written to the underlying persistent storage. takes a recordId as a parameter and removes the record represented by that recordId from the record store. takes a recordId as a parameter and returns the size of the associated record in bytes.
returns a copy of the record. The second form takes a recordId, and a usersupplied byte array and offset. This form of the method returns a copy of the record into the byte array starting at the given offset. •
setRecord:
takes a recordId, a byte array, an offset, and a length as parameters. The record identified by the recordId is overwritten from the beginning with data from a subset of the byte array subset identified by the offset and length.
14.2.4 Converting Record Data to and from Byte Arrays Before data can be saved into a record store, it must be converted into an array of bytes. Using CLDC classes such as DataInputStream, DataOutputStream, ByteArrayInputStream, or ByteArrayOutputStream, developers can pack and unpack different data types into and out of byte arrays. As an example, consider a game MIDlet that needs to record scores and names of players. The code fragment below illustrates how such a record (byte array) might be created: ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream outputStream = new DataOutputStream(baos); // Add the score (an int) then the name of the player (a UTF) // to the DataOutputStream. outputStream.writeInt(score); outputStream.writeUTF(name);
MANIPULATING RECORD STORES AND RECORDS
// Now, extract the byte array (record) byte[] theRecord = baos.toByteArray();
Once the record has been created, it can be inserted into a record store using the addRecord operation introduced in Section 14.2.3, “Manipulating Records in a Record Store.” 14.2.5 Filtering, Comparing, Listening, and Enumerating Records The records of a record store may be processed in various ways. To provide programmer-defined ways to filter, search, and sort a record store, RMS provides the four Java interfaces discussed below. The RecordFilter interface The RecordFilter interface allows the programmer to define filters for searching records. This interface requires the programmer to supply a method called matches that accepts one record as a parameter. This method returns a boolean indicating whether or not the given record matches the user-defined search criteria. For instance, consider the following example in which a record store contains different types of records, with the type being indicated by the first byte. In this example, Integer records are indicated by the first byte being ‘I’. The following filter returns true if the candidate record is an Integer record: public class IntegerFilter implements RecordFilter { public boolean matches(byte[] candidate) throws IllegalArgumentException { return candidate[0] == 'I'; } }
The RecordComparator interface The RecordComparator interface allows the programmer to define comparison operations for records. This interface defines the method compare that takes two records as parameters. This method returns one of the following class-static values from the RecordComparator class: •
EQUIVALENT: returned if the two records are considered equivalent for this sort
order. •
FOLLOWS:
•
PRECEDES:
returned if the first record follows the second for this sort order. returned if the first record precedes the second for this sort order.
227
228
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
To carry forth the previous example, let’s assume that the Integer records discussed above have the format of a record type indicator (in this case: ‘I’) followed by a four-byte Integer. Furthermore, let’s assume that we want to sort the records in ascending order according to value of the four-byte Integer field. A record comparator to accomplish this could be written as follows (with error checking omitted): class IntegerCompare implements RecordComparator { public int compare(byte[] b1, byte[] b2) { DataInputStream is1 = new DataInputStream( new ByteArrayInputStream(b1)); DataInputStream is2 = new DataInputStream( new ByteArrayInputStream(b2)); /** * Skip record type (1 byte), then read ints */ is1.skip(1); is2.skip(1); int i1 = is1.readInt(); int i2 = is2.readInt(); if (i1 > i2) return RecordComparator.FOLLOWS; if (i1 < i2) return RecordComparator.PRECEDES; return RecordComparator.EQUIVALENT; } }
The RecordListener interface In order to monitor the addition and modifications of records to a record store, RMS provides the RecordListener interface. This interface defines three methods that a class must implement. Each method takes two parameters: a RecordStore and a recordID: •
recordAdded:
•
recordChanged:
called when a record is modified in the record store.
•
recordDeleted:
called when a record is deleted in the record store.
called when a record is added to the record store.
MANIPULATING RECORD STORES AND RECORDS
The following code fragment shows a simple record listener that prints out a line indicating what type of operation is being done to a record store: /** * Add the listener to the record store */ recordStore.addRecordListener((RecordListener) new myListener()); ... public class myListener implements RecordListener { final private static int ADDED = 1; final private static int CHANGED = 2; final private static int DELETED = 3; private void handleCall(int type, RecordStore rs, int rid) { System.out.print("Record store " + rs.getName() + " and record id " + rid + " was "); switch (type) { case myListener.ADDED: System.out.println("added"); break; case myListener.CHANGED: System.out.println("changed"); break; case myListener.DELETED: System.out.println("deleted"); break; } } public void recordAdded(RecordStore rs, int rid) { handleCall(myListener.ADDED, rs, rid); } public void recordChanged(RecordStore rs, int rid) { handleCall(myListener.CHANGED, rs, rid); } public void recordDeleted(RecordStore rs, int rid) { handleCall(myListener.DELETED, rs, rid); } }
229
230
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
The RecordEnumerator interface The final interface provided by RMS is the RecordEnumeration interface. A class implementing this interface provides a mechanism to enumerate over all the records in the record store. Although a developer can implement this interface, the most common usage of record enumeration is simply using the enumerateRecords provided by the RecordStore class. The enumerateRecords method returns an instance of a class that implements the RecordEnumeration interface. It takes three parameters: a RecordComparator, a RecordFilter, and a boolean that indicates that the returned enumerator should register itself as a listener in order to keep it updated with ongoing activity on the record store. The most efficient way to get each record in a record store is to supply neither a RecordComparator nor a RecordFilter: simpleRE = recordStore.enumerateRecords(null, null, false); while (re.hasNextElement()) { byte b[] = re.nextRecord(); ... }
This example would return, in an undefined order, every record in the record store while ignoring changes made to the record store by other MIDlets or threads. A more complex example is enumerating through a subset of records in the record store and sorting them in a user-defined manner. Using our previous examples of the RecordComparator and the RecordFilter, we can construct a record enumerator that only returns the records containing Integer numbers in numerically ascending order with the following code fragment: IntegerFilter iFilt = new IntegerFilter(); IntCompare iCompare = new IntegerCompare(); intRE = recordStore.enumerateRecords((RecordFilter)iFilt, (RecordComparator)iCompare, false); while (IntRE.hasNextElement()) { byte b[] = re.nextRecord(); ... }
Suppose that our record store had two types of records: Integer and String, with the String records starting with an ‘S’ and the Integer records beginning with an ‘I’. If our record store contained the following records:
SAMPLE CODE (RMSMIDlet.java)
Record 1: 'I', 100 Record 2: 'S', "Joy" Record 3: 'I', 50 Record 4: 'S', "Zachary" Record 5: 'S', "Abby" Record 6: 'I', 25
then the enumeration returned by Record 1.
intRE
would be
Record
6, Record
3,
then
14.3 Sample Code (RMSMIDlet.java) The following small sample application, RMSMIDlet.java, demonstrates some of the capabilities of RMS. Only the main class and one non-public implementation class of this application are shown. The RMSMIDlet example creates two record stores called Personal and Business and allows the user to view the contents of the record store and the details of the individual records using the operations discussed in Section 14.2.1, “Manipulating a Record Store”). When the MIDlet begins, the application opens the screen that is depicted in the figure above. If the user selects the OK command, then the content of the selected database (in this case, Personal) is shown, as depicted in the figure to the right. If the user navigates through the MENU command and selects the DETAIL command, then the detail screen is shown. (See the figure on the next page.) Class RMSMIDlet is implemented as a MIDlet, so its structure and functionality follows the general guidelines defined for MIDlet classes. This means that the class must implement the methods startApp, pauseApp, and destroyApp to define the behavior upon application startup, pausing, and exit, respectively.
231
232
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
The class also implements the CommandListener interface in order to listen to command input from the user. The implementation of class RMSMIDlet utilizes a package private (non-public) class CreateAddressBook in order to create and populate the application’s database with sample address book entries.
CreateAddressBook.java package examples.addressbook; import java.lang.*; import java.io.*; import java.util.*; import javax.microedition.rms.*; /** * Static helper class that creates a record * store from data in an array. */ class CreateAddressBook { // Don't allow this class to be instantiated private CreateAddressBook() {} /** * Helper method that creates a record * store from data in an array. * Returns: *
true
if RMS store was created
*
false
otherwise
*
name
the name of the record store to create
*
seedData
an array w/ data to seed record store
*/ static boolean createRecordStore(String name, String[] seedData) { RecordStore recordStore; boolean ret = false; // Delete any previous record store with same name.
SAMPLE CODE (RMSMIDlet.java)
// Silently ignore failure. try { RecordStore.deleteRecordStore(name); } catch (Exception rse) {} // Create new RMS store. If we fail, return false. try { recordStore = RecordStore.openRecordStore(name, true); } catch (RecordStoreException rse) { return ret; } ret = true; // assume success // Now, populate the record store with the seed data for (int i = 0; i < seedData.length; i += 3) { byte[] record = SimpleRecord.createRecord(seedData[i], seedData[i+1], seedData[i+2]); try { recordStore.addRecord(record, 0, record.length); } catch (RecordStoreException rse) { ret = false; break; } } // Get here when adds are complete, or an error occurred. // In any case, close the record store. We shouldn't // have a failure, so silently ignore any exceptions. try { recordStore.closeRecordStore(); } catch (RecordStoreException rsne) {} return ret; } }
233
234
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
RMSMIDlet.java package examples.addressbook; import java.lang.*; import java.io.*; import java.util.*; import javax.microedition.lcdui.*; import javax.microedition.rms.*; import javax.microedition.midlet.*; /** * A simple class that shows various functionality of RMS. * The general flow of this MIDlet is: * *
In the constructor (See RMSMIDlet),
*
create and populate two record stores, one of personal
*
contacts, the other with business contacts.
*
Display the first screen. This screen shows a list
*
of all RMS stores found in the MIDlet suite's name
*
space. This screen allows the user to select a
*
record store and either display pertinent information
*
about the record store such as size, etc., or to view
*
the contents of the selected store. When the contents
*
of a record store are viewed, they are sorted by last
*
name, although this can be changed by instantiating a
*
SimpleComparator object with the appropriate
*
sort order parameter.
* *
Traversal from screen to screen is handled
*
by RMSMIDlet, commandAction.
* */ public class RMSMIDlet extends MIDlet implements CommandListener { private Display myDisplay;
// handle to the display
private Alert alert;
// used to display errors
// Our commands to display on every screen. private Command CMD_EXIT; private Command CMD_DETAILS; private Command CMD_OK;
SAMPLE CODE (RMSMIDlet.java)
// Our screens private List mainScr; private List detailScr; private List dataScr; // An array of all RMS stores found in this // MIDlets name space. private String[] recordStoreNames; /** * Seed data for creating personal contacts RMS store */ private final String personalContacts[] = { "John", "Zach", "2225556669", "Mark", "Lynn", "5125551212", "Joy", "Beth", "2705551234", "Abby", "Lynn", "4085558566", }; /** * Seed data for creating business contacts RMS store */ private final String businessContacts[] = { "Ted", "Alan", "4125552235", "Sterling", "Wincle", "9995559111", "Deborah", "Elaine", "4445552323", "Suzanne", "Melissa"," 5125556064", "Frank", "Kenneth", "7775551212", "Dwight", "Poe", "1115557234", "Laura", "Beth", "2055558888", "Lisa", "Dawn", "2705551267", "Betty", "June", "5555551556", "Yvonne", "Poe", "6665558888", "Lizzy", "Loo", "5025557971", "John", "Gerald", "3335551256", }; /** * Display warning on the screen and revert to main screen * * A warning string to display */
235
236
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
private void doAlert(String s) { alert.setString(s); myDisplay.setCurrent(alert, mainScr); } /** * Notify the system we are exiting. */ private void doExit() { destroyApp(false); notifyDestroyed(); } /** * In our simple MIDlet, all screens have the same commands, * with the possible exception of the detailScr. * * Also set up the command listener to call commandAction. * See RMSMIDlet#commandAction */ private void addCommonCommands(Screen s, boolean doDetails) { s.addCommand(CMD_OK); s.addCommand(CMD_EXIT); if (doDetails) { s.addCommand(CMD_DETAILS); } s.setCommandListener(this); } /** * The public constructor. In our constructor, we get * a handle to our display and create two record stores. * In the event of an error, we display an alert. */ public RMSMIDlet() { CMD_EXIT = new Command("Exit", Command.EXIT, 3); CMD_DETAILS = new Command("Details", Command.SCREEN, 2); CMD_OK = new Command("OK", Command.OK, 1); myDisplay = Display.getDisplay(this); alert = new Alert("Warning"); alert.setTimeout(2000);
SAMPLE CODE (RMSMIDlet.java)
CreateAddressBook.createRecordStore("Personal", personalContacts); CreateAddressBook.createRecordStore("Business", businessContacts); // Now, get a list of RMS stores and add their // names to the mainScr. recordStoreNames = RecordStore.listRecordStores(); mainScr = new List("Select RMS Store", List.IMPLICIT, recordStoreNames, null); addCommonCommands(mainScr, true); } /** * Called by the system to start our MIDlet. */ protected void startApp() { myDisplay.setCurrent(mainScr); } /** * Called by the system to pause our MIDlet. * No actions required by our MIDLet. */ protected void pauseApp() {} /** * Called by the system to end our MIDlet. * No actions required by our MIDLet. */ protected void destroyApp(boolean unconditional) {} /** * Generate a screen with a sorted list of the contents * of the selected RMS store identified by index. * If any errors encountered, display an alert and * redisplay the mainScr. * * * index an index into recordStoreNames */
237
238
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
public void genDataScr(int index) { SimpleComparator rc; RecordEnumeration re; RecordStore rs; dataScr; byte record[]; try { rs = RecordStore.openRecordStore( recordStoreNames[index], false); } catch (RecordStoreException e) { doAlert("Could not open " + recordStoreNames[index]); return; } // Create an enumeration that sorts by last name rc = new SimpleComparator( SimpleComparator.SORT_BY_LAST_NAME); try { re = rs.enumerateRecords(null, rc, false); } catch (RecordStoreNotOpenException e) { doAlert("Could not create enumeration: " + e); return; } // Create a screen and append the contents of the // selected RMS store. dataScr = new List(recordStoreNames[index] + " Data", List.IMPLICIT); addCommonCommands(dataScr, false); try { while (re.hasNextElement()) { byte[] b = re.nextRecord(); dataScr.append(SimpleRecord.getFirstName(b) + " " + SimpleRecord.getLastName(b), null); } } catch (Exception e) { doAlert("Could not build list: " + e); dataScr = null;
SAMPLE CODE (RMSMIDlet.java)
} finally { try { rs.closeRecordStore(); } catch (RecordStoreException e) {} } } /** * Generate a screen that shows some of the details * of the selected RMS store. * * RMS store information displayed: * - name * - number of records * - size, in bytes * - available size, in bytes * - version number * * index
an index into recordStoreNames
*/ public void genDetailScr(int index) { RecordStore rs; detailScr = null; try { rs = RecordStore.openRecordStore( recordStoreNames[index], false); } catch (Exception e) { doAlert("Could not open " + recordStoreNames[index]); return; } detailScr = new List(recordStoreNames[index] + " Details", List.IMPLICIT); addCommonCommands(detailScr, false);
try { detailScr.append("Name: "
+ rs.getName(), null);
detailScr.append("# recs: " +
239
240
CHAPTER 14
MIDP PERSISTENCE LIBRARIES
rs.getNumRecords(), null); detailScr.append("Size: " + rs.getSize(), null); detailScr.append("Avail: " + rs.getSizeAvailable(),null); detailScr.append("Version: " + rs.getVersion(), null); } catch (Exception e) { detailScr = null; doAlert("Failed to retrieve data"); return; } finally { try { rs.closeRecordStore(); } catch (RecordStoreException e) {} } } /*** * Respond to command selections. * Commands are: * EXIT: if selected, then exit (see RMSMIDlet, doExit) * OK:
if selected, interpreted in the context of
*
the current screen.
* * This method implements a state machine that drives * the MIDlet from one state (screen) to the next. */ public void commandAction(Command c, Displayable d) { // Every screen has an EXIT command. // Handle this consistently for all screens. if (c == CMD_EXIT) { doExit(); return; } // Switch based on screen. if (d == mainScr) {
NEW FOR MIDP 2.0
// Main screen: two commands to handle. If // OK was selected, then generate the dataScr // and make it active. If DETAILS was selected, // generate the detailScr and make it active. if ((c == List.SELECT_COMMAND) || (c == CMD_OK)) { genDataScr(mainScr.getSelectedIndex()); myDisplay.setCurrent(dataScr); } else if (c == CMD_DETAILS) { genDetailScr(mainScr.getSelectedIndex()); myDisplay.setCurrent(detailScr); } } else if (d == detailScr) { // If OK selected, go back to mainScr if (c == CMD_OK) { myDisplay.setCurrent(mainScr); } } else if (d == dataScr) { // If OK selected, go back to mainScr if (c == CMD_OK) { myDisplay.setCurrent(mainScr); } } } }
14.4 New for MIDP 2.0 The most requested feature for RMS in MIDP 2.0 was the ability to share record stores between MIDlet suites. This was addressed by adding an access mode to class RecordStore so that the owner of the RecordStore can allow shared or private access, and can differentiate between read-only or read-write access modes. The MIDlet suite that creates the RecordStore owns it and controls access to it. Other MIDlet suites can open shared record stores by giving the MIDlet suite name and the record store name. This new functionality makes it possible to share persistent data between MIDlet suites.
241
This page intentionally left blank
C H A P T E R
15
MIDP Networking and Serial Communications MIDP target devices operate on a wide variety of wireless and wired networks with incompatible transport protocols. In addition, wireless networks have less bandwidth, more latency, and less stable connections than wired networks. The MIDP Specification version 2.0 must accommodate these differences and allow for future network technologies. To do so, MIDP uses standard network programming mechanisms and practices and takes advantage of the existing network infrastructure. MIDP specifies that HTTP and HTTPS are required protocols for all devices. In addition, it defines APIs for optional protocols: datagrams, sockets, secure sockets, and serial communication ports. (See Chapter 16, “Secure Networking” for more information on the secure networking protocols.)
15.1 Characteristics of Wireless Data Networks The MIDP Specification version 2.0 addresses two types of wireless data networks: circuit-switched data (CSD) and packet-switched data (PSD). A wireless circuitswitched network (also called a session-based network) assigns a user a radio channel, which it dedicates to the connection until the data transfer is done. During the data exchange, the channel cannot be used for anything else. The GSM cellular phone network is a circuit-switched data network. Data over a circuit-switched network is usually billed on a time basis, like voice transmissions. Using a circuit-switched wireless network for data transfer can be expensive because data rates in today’s wireless networks are rather low. In a GSM phone, for example, the data rate is usually about 9.6 kilobits per second (kbps). 243
244
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
The other type of wireless data network is packet-switched. In packet-switched data transmissions, the data exchange is broken up into small packets that usually have a fixed length. Packets from several different data exchanges, each from different users, can be sent in time slots of the same radio channel. The packets are mixed during transmission and reassembled in the correct order by the recipients. Packet-switched data uses the radio spectrum more efficiently than circuitswitched data. In addition, packet-switched data is usually billed by the amount of data sent, so packet-switched networks are generally cheaper for data transfer. The next-generation wireless-network technologies promise much greater data rates than the networks in widespread use today. The second-and-a-half generation (2.5G) wireless technologies, such as General Packet Radio Service (GPRS), and third-generation (3G) technologies, such Wideband Code Division Multiple Access (WCDMA), are generally packet-switched technologies. For example, the theoretical maximum data transfer rate of GPRS is 171.2 kilobits per second, and third generation wireless networks offer theoretical data rates up to a few megabits per second.
15.2 Network Interface Considerations MIDP devices must support the HTTP protocol, a rich, widely used protocol that can be implemented relatively easily over a variety of wireless networks. HTTP lets devices take advantage of the extensive server-side infrastructure already in place for wired networks. Furthermore, because no unrequested HTTP packets can arrive at the device, implementing the networking interface is easier. Supporting the HTTP protocol does not imply that the device must support a particular Internet Protocol (IP). A device can implement HTTP using IP protocols such as TCP/IP, or non-IP protocols such as WAP or i-Mode. If a device uses a non-IP protocol, a computer called a gateway bridges the wireless protocol to and from HTTP servers on the Internet and provides IP-based network facilities such as server name resolution (for example, DNS). Many wireless networks have evolved to support IP-based protocols, so the MIDP Specification version 2.0 defines the corresponding APIs and behaviors. The new MIDP 2.0 APIs are SocketConnection (Section 15.5, “SocketConnection”), ServerSocketConnection (Section 15.6, “ServerSocketConnection”), and UDPDatagramConnection (Section 15.7, “UDPDatagramConnection”). In addition, the CommConnection API (Section 15.8, “CommConnection”) supports serial communications. Support for these protocols is optional, but most networks are expected to support them. They enable MIDlets using the protocols to run consistently across implementations.
THE HTTPCONNECTION INTERFACE
Implications for application developers When designing MIDP applications, it is important to keep in mind that many networking and communications API calls can be time-consuming and can potentially block the application thread. For instance, networking operations such as opening connections or receiving data from a server can cause the application thread to be blocked while waiting for the network activity to be completed. Application developers should design their applications so that the applications do not invoke any time-consuming network operations in the callback functions that are invoked as a result of user interface actions. For instance, CommandListener functions should not generally invoke networking functions, as listeners require a separate thread to keep the user interface functionality from interfering with the responsiveness of the application. In addition, upon invoking time-consuming networking operations, the application should always display a progress screen, such as Gauge, and include a “Cancel” command to allow the user to escape from potentially indefinitely blocking network activity.
15.3 The HttpConnection Interface The interface javax.microedition.io.HttpConnection defines the MIDP HTTP API. This interface is unchanged from MIDP 1.0. The interface extends the interface javax.microedition.io.ContentConnection to provide additional fields and methods that parse URLs, set request headers, and parse response headers. (Refer to the documentation of interface ContentConnection on page 69.) 15.3.1 States of an HTTP Connection An HTTP connection exists in one of three states: setup, connected, or closed. A connection is in the setup state after it is opened and before the request has been made to the server. The application sets information needed to connect to the server, such as the request parameters and headers. (They must be set before the request is sent.) The methods setRequestMethod and setRequestProperty set the values; the getRequestMethod and the getRequestProperty methods retrieve them. A connection enters the connected state when the request is sent. This occurs when the application calls a method that requires a response value or closes the output stream, if any. These methods indicate the end of the request. A connection enters the closed state when the connection is closed. Although none of the methods of the HttpConnection object can be used when the connection is closed, its InputStream or OutputStream might still contain data. The
245
246
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
streams may be used until they are closed. The following code fragment shows an input stream being used after its connection has been closed: // Open the connection and input stream HttpConnection c = (HttpConnection)Connector.open(...); InputStream is = c.openInputStream(); ... // Close the connection. Can't call HttpConnection methods // after this, but InputStream methods are still available. c.close(); while ((int ch = is.read()) != -1) { ... } // Close the input stream. Can't call InputStream methods after this is.close();
15.3.2 Security of HTTP Access to the HTTP connection may be restricted by device policy. Trusted MIDlet suites request access with the javax.microedition.io.Connector.http permission, as described in Section 18.3, “Trusted MIDlet Suite Security Model.” The device may try to authorize the MIDlet when the MIDlet calls the Connector.open method with a valid URL. If the authorization fails and the MIDlet is not allowed to use the HTTP API, the Connector.open method throws a java.lang.SecurityException. 15.3.3 Establishing a Connection Applications open HTTP connections with the CLDC method javax.microedi(Refer to Section 5.3.2, “The Generic Connection Framework.”) The method takes a single String URL parameter in the URI (Uniform Resource Identifier) form as defined by the IETF standard RFC2396 Uniform Resource Identifiers [reference 5]. Opening the connection might block the application thread until the server responds. The application should make sure this code runs in a thread separate from the user interfaces callbacks. The following code fragment opens a connection to the home page of the Java™ Programming Language.
tion.io.Connector.open.
HttpConnection c = (HttpConnection)Connector.open("http://java.sun.com/");
THE HTTPCONNECTION INTERFACE
The resulting connection supports the HTTP 1.1 protocol as defined by RFC2616 [reference 9]. The connection is in the setup state. 15.3.4 Parsing URLs While an HTTP connection is open, a MIDlet can parse the components of its URL. The URL-parsing methods are: •
getProtocol:
returns the protocol component of the URL.
•
getHost:
returns the host component of the URL.
•
getPort:
returns the port number component of the URL.
•
getFile:
returns the file component of the URL.
•
getQuery: returns the query component of the URL (the text after the first ques-
tion mark (?) character in the URL). •
getRef:
returns the reference component of the URL (the text after the crosshatch (#) character in the URL). The following example uses these accessor methods:
// Open the Connection String HTTP_URL = "http://localhost:8080/myApp?first=joe?last=cool"; HttpConnection c = (HttpConnection)Connector.open(HTTP_URL); // Can now use the URL parsing methods System.out.println("Protocol: " + c.getProtocol()); System.out.println("Host: " + c.getHost()); System.out.println("Port: " + c.getPort()); System.out.println("File: " +
c.getFile());
System.out.println("Query: " + c.getQuery()); System.out.println("Reference: " + c.getRef());
When run, the code prints the following lines: Protocol: http Host: localhost Port: 8080 File: /myApp Query: first=joe?last=cool Reference: null
247
248
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.3.5 HTTP Request Headers The HTTP protocol provides a rich set of request headers that allow a MIDlet to negotiate the form, format, language, session, and other attributes of the content posted or retrieved. The protocol also provides response headers. It is the responsibility of a MIDlet to choose the request headers to use and to process response headers. When a MIDlet communicates with a known service, it needs to handle only a subset of headers. It can omit and ignore the others. The following methods set the request method and headers. A MIDlet can use them when its connection is in the setup state. •
setRequestMethod:
•
setRequestProperty:
•
getRequestMethod:
•
getRequestProperty:
sets the request method to one of the following POST, GET, or HEAD; if not set, then the default is GET. sets the name and value of a request header.
returns the current request method. returns a previously set request property.
Of the request properties that can be set, the User-Agent, and Authorization properties merit special discussion.
Accept-Language,
The User-Agent Header In the HTTP specification, a request header called User-Agent identifies the current client to the server. As specified by RFC2616 [reference 9], the field contains features separated by blanks. A feature consists of a name and optional version number. The MIDP Specification version 2.0 does not require that a MIDlet set the User-Agent field. A MIDlet can use it, though, to identify its device to the server. The following code fragment sets the User-Agent field to the version numbers of the CLDC and MIDP implementations running on the device: StringBuffer sb = new StringBuffer(60); // Add the Configuration to the string that is the User-Agent value sb.append("Configuration/"); sb.append(System.getProperty("microedition.configuration")); // For each profile, append it to the User-Agent string String prof = System.getProperty("microedition.profiles") int i = 0, j = 0; while ((j = prof.indexOf(’ ’, i)) != -1) { sb.append(" Profile/");
THE HTTPCONNECTION INTERFACE
sb.append(prof.substring(i, j)); i = j + 1; } sb.append(" Profile/"); sb.append(prof.substring(i)); // Set the User-Agent field c.setRequestProperty("User-Agent", sb.toString());
The Accept-Language Header The Accept-Language header requests a document in a particular language. The header can be set with the value of the system property microedition.locale, which identifies the current locale of the device. (See Section 20.2, “System Properties” for more information.) The following code fragment shows the AcceptLanguage header being set with the microedition.locale value. String locale = System.getProperty("microedition.locale"); if (locale != null) { c.setRequestProperty("Accept-Language", locale); }
The Authorization Header The HTTP protocol provides several mechanisms that a client and server can use to to implement a challenge-response authentication scheme [reference 10]. One scheme, the basic authentication scheme, has the client send a userId-password pair to the server in the Authorization header. The server uses the authentication data to give the client access to a protected resource, or realm. The server only handles a request to access a realm if it can validate the user identifier and password the client supplied. To use a basic authentication scheme, the Authorization header must contain the string Basic, a space, and then the base64 [reference 3] encoding of a string composed of the user-ID, a colon, and password. For example, if a client needed to access a protected resource that requires a user-ID of book and a password of bkpasswd, the MIDlet would send the following header field: Authorization: Basic Ym9vazpia3Bhc3N3ZA==
where the ‘Ym9vazpia3Bhc3N3ZA==’ string is the base64 encoding of book:bkpasswd. The Authorization header can also be used for other authentication schemes. See RFC2617 [reference 10] for more information.
249
250
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.3.6 Using an HTTP Connection After a MIDlet sets the appropriate headers it can use the connection. The connection’s action depends on the value (GET, POST, or HEAD) set with the setRequestMethod method. Using the GET Request Method The GET method retrieves information. The following code fragment shows the common situation in which an application opens an HttpConnection, checks the connection’s status (which sends the request), and then reads data from the connection using the InputStream of the connection. HttpConnection c; InputStream is; try { // Open the connection c = (HttpConnection)Connector.open("http://java.sun.com/"); // Get the HTTP response code, which sends the request // Only HTTP_OK (200) means that the content is returned int status = c.getResponseCode(); if (status != HttpConnection.HTTP_OK) { throw new IOException("Response code not OK"); } else { // Handle other recoverable responses like redirects } // Open the InputStream and read until end of file // (-1) is returned is = c.openInputStream(); int ch; while ((ch = is.read()) != -1) { // Process the byte from the stream; } } finally { // Close the connection and the InputStream if (is != null) { is.close(); } if (c != null) { c.close(); } }
THE HTTPCONNECTION INTERFACE
Using the POST Request Method requests can send more data and parameters to a server than GET requests. When using a POST request, a MIDlet can provide parameters as part of the URL (as with a GET request). In addition, the MIDlet can write a stream of bytes over the network in order to supply the server with additional data. The example below shows a POST request. The example opens the connection and sets up the request headers. It then opens an OutputStream and writes additional data or commands into the stream before sending the request to the server.
POST
HttpConnection c; InputStream is; OutputStream os; try { // Open the connection c = (HttpConnection)Connector.open(url); // Make this a POST request c.setRequestMethod(HttpConnection.POST); // Get the output stream and write a command os = c.openOutputStream(); os.write("LIST games\n".getBytes()); os.flush(); // Get the status code, causing the request to be sent // Only HTTP_OK (200) means the request was accepted status = c.getResponseCode(); if (status != HttpConnection.HTTP_OK) throw new IOException("Response status not OK");
} Using the HEAD Request Method The HEAD request method is like the GET request method except the server does not return a message body in the response. All of the information in the HTTP headers is identical. An application usually uses a HEAD request to test whether a URL is valid or modified.
251
252
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.3.7 HTTP Response Headers An HTTP server responds to a request by sending one or more headers that describe the content of the response, such as the type, encoding, length, and so on. The requested content is sent next. The HttpConnection object parses and stores the response headers until the connection is closed. The MIDlet must get any headers it needs from the connection before closing it. It uses the information to interpret the returned content. The methods that fetch and convert the commonly used fields to the appropriate primitive type are: •
getResponseCode:
•
getResponseMessage:
•
getEncoding:
•
getType:
•
getLength:
•
getDate:
•
getExpiration:
•
returns the value of the response code. returns the value of the response message.
returns the value of the content-encoding as a string.
returns the content-type header field as a string. returns the content-length header field as a size in bytes.
returns the value of the date header in milliseconds. returns the value of the expires header in milliseconds.
getLastModified:
returns the value of the last-modified header in
milliseconds. Additional response headers are also available. Methods provide access to the fields by index or name as a String, an integer, or a time in milliseconds. If a header may appear more than once (as Set-Cookie can) a MIDlet must iterate through the response headers using getHeaderFieldKey to identify which headers have multiples. The methods to iterate through and get the values of the fields are: •
getHeaderField(String name): returns the value of the named header field as
a String. •
getHeaderField(int n): returns the value of the n
•
getHeaderFieldKey(int n):
th
header (starting from zero).
returns the name of the nth header (starting from
zero). •
getHeaderFieldInt(String name, int n): returns the value of the named field
converted to an integer. •
getHeaderFieldDate(String name, long def): returns the value of the named
field in milliseconds.
SAMPLE CODE (NETCLIENTMIDLET.JAVA)
All of the header-related methods catch any exceptions that occur in making the connection and return default values. To avoid missing a network error or incorrectly acting upon it, a MIDlet should call getResponseCode, check the return value, and be prepared to handle any exceptions before getting the response headers. 15.3.8 Closing an HTTP Connection An
application
closes
an
edition.io.Connector.close
HTTP connection with the javax.micromethod. The following example shows a connection
being closed. try { c.close(); } catch (IOException e) { ... }
15.4 Sample Code (NetClientMIDlet.java) The following application, NetClientMIDlet, demonstrates how HTTP can be used to log in to a server, send data, and receive a response. The MIDlet begins by displaying the instructional screen shown in the top figure. If the user selects OK, the MIDlet sends a POST request that contains a user identifier and password for a basic authentication scheme. It also sends the message Esse quam videri (“To be rather than to seem.”) After sending the message, the MIDlet reads the returned values. A screen full of the values are shown in the next figure: a string identifying itself (such as “NetServer Servlet” as shown in the bottom figure), followed by a date string, the original POST message body, the message body reversed, and a complete list of headers read from the POST request. (The figure only shows the first header.) The example consists of three classes. The NetClientMIDlet class extends the MIDlet class. It implements the MIDlet life cycle methods and has the device dis-
253
254
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
play the screens shown in the figures. The ConnectionManager class opens the HTTP connection to a server, sends the information, and reads the response. The BasicAuth class transforms the user identifier and password into a base64 encoded string. NetClientMIDlet.java This class creates the MIDlet’s user interface and manages its states. The constructor creates the MIDlet’s screens. The startApp method displays the main screen, which is an instructional screen, the first time it is called. If the user selects OK on the main screen, the run method is called. The run method creates a ConnectionManager instance and sets the connection manager’s msg field to “Esse quam videri”, its user field to book, and its password field to bkpasswd. The run method then has the connection manager handle the request and displays the results that the connection manager returns. // Package and import declarations package examples.netclient; import java.lang.*; import java.io.*; import java.util.*; import javax.microedition.lcdui.*; import javax.microedition.midlet.*; // Example use of the HTTP networking interface. It opens an // HTTP POST connection to a server and uses it to authenticate // with an HTTP Basic Authentication scheme and send a string // to the server. This MIDlet then reads and displays the response. public class NetClientMIDlet extends MIDlet implements CommandListener, Runnable { private Display display;
// handle to the display
private TextBox mainScr;
// main screen
private Command cmdOK;
// OK command
private Command cmdExit;
// EXIT command
private Form progress;
// Progress Form
// Creates the MIDlet, its main screen, its progress screen, // and its commands. It also caches the MIDlet’s display. public NetClientMIDlet() { display = Display.getDisplay(this);
SAMPLE CODE (NETCLIENTMIDLET.JAVA)
mainScr = new TextBox("NetClient", "Press OK to connect to network service", 1024, TextField.UNEDITABLE); cmdOK = new Command("OK", Command.SCREEN, 1); cmdExit = new Command("Exit", Command.EXIT, 1); mainScr.addCommand(cmdOK); mainScr.addCommand(cmdExit); mainScr.setCommandListener(this); display.setCurrent(mainScr); progress = new Form("Progress"); Gauge g = new Gauge("Waiting...", false, Gauge.INDEFINITE, Gauge.CONTINUOUS_RUNNING ); progress.append(g); progress.addCommand(cmdExit); progress.setCommandListener(this); } // The system calls this method to start the MIDlet. protected void startApp() {} // The system calls this method to pause the MIDlet. // Does nothing: there are no global resources to release. protected void pauseApp() {} // The system calls this method to exit the MIDlet. // Does nothing: there are no global resources to release. protected void destroyApp(boolean unconditional) {} // Gets and displays data from the server public void run() { // Create and set parameters to communicate with the server ConnectionManager h = new ConnectionManager(); h.setMsg("Esse quam videri"); h.setUser("book"); h.setPassword("bkpasswd"); // Communicate with the server byte[] data = h.Process();
255
256
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
// Display the result of the communication if (data == null || data.length == 0) { // Tell user no data was returned Alert alert = new Alert("Alert", "No information available", null, AlertType.ERROR); display.setCurrent(alert, mainScr); } else { // Create data screen TextBox dataScr = new TextBox("Data Screen", "", 1, TextField.UNEDITABLE); dataScr.addCommand(cmdOK); dataScr.addCommand(cmdExit); dataScr.setCommandListener(this); dataScr.setMaxSize(data.length); dataScr.setString(new String(data)); display.setCurrent(dataScr); } } // Respond to user commands, invoke the next task public void commandAction(Command c, Displayable d) { if (c == cmdOK) { if (d == mainScr) { // Communicate with the server without blocking UI display.setCurrent(progress); new Thread(this).start(); } else { // Display the main screen display.setCurrent(mainScr); } } else if (c == cmdExit) { // Exit the MIDlet destroyApp(false); notifyDestroyed(); } } }
SAMPLE CODE (NETCLIENTMIDLET.JAVA)
ConnectionManager.java The ConnectionManager class manages the HTTP POST connection. The run method of the NetClientMIDlet class creates an instance of the class, and then calls the process method of the new instance. The constructor sets the strings for the User-Agent and Accept-Language headers. The process method opens the HTTP connection by calling the open method. The example hard codes the URL of the server in the variable baseurl; the variable refers to a simple Java servlet that accepts HTTP POST connections. After it opens the connection, the process method sets the HTTP request type to HttpConnection.POST to allow the MIDlet to write data to the server. It then sets the HTTP header fields to the values shown in Table 15.1. Table 15.1 HTTP header values Header
Value
User-Agent
The string Profile/MIDP-1.0 Configuration/CLDC-1.0
Accept-Language
The value of the system property microedition.locale or the string en-US if the property is not set
Content-Length
The length of the field msg
Content-Type
The string text/plain
Authorization
The string Basic followed by a space, followed by the base64 encoding of user:password
As the final step in preparing the request, the process method opens the connection’s output stream, writes a message, and closes the output stream. At that point the network connection is made, the stored headers are flushed, and the msg field is written to the server. The connection manager calls the getResponseCode method to see whether the connection was successful. Its subsequent actions depend on the status code. There are three response cases to handle: •
HttpConnection.HTTP_OK:
•
HttpConnection.HTTP_MOVED_TMP, HttpConnection.HTTP_MOVED_PERM,
The connection was opened and the data was written. In this case, the connection manager opens an InputStream and reads the response data from the server.
HttpConnection.HTTP_TEMP_REDIRECT:
or The server is trying to redirect the re-
257
258
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
quest. In this case, the connection manager reads the location header and uses the new URL. • The connection was not opened for an unexpected reason; in this case, the connection manager throws an IOException. package examples.netclient; import java.lang.*; import java.util.*; import java.io.*; import javax.microedition.io.*; // Establishes an HTTP POST connection to the server defined by // baseurl, sends headers and a message, and reads the response. // It sets the following HTTP headers: // User-Agent:
CLDC and MIDP version strings
// Accept-Language: microedition.locale or "en-US" if that is null // Content-Length:
the length of msg
// Content-Type:
text/plain
// Authorization:
"Basic" + the base 64 encoding of user:password
class ConnectionManager { private HttpConnection con; private InputStream is; private OutputStream os; private final String baseurl = "http://127.0.0.1:8080/Book/netserver"; private String ua; private String locale; private String msg; private String user; private String password; // Creates the connection manager and creates the values for the // User-Agent and Accept-Language headers. ConnectionManager() { StringBuffer sb = new StringBuffer(60); sb.append("Configuration/"); sb.append( System.getProperty("microedition.configuration"));
SAMPLE CODE (NETCLIENTMIDLET.JAVA)
// For each profile, append it to the user agent string String prof = System.getProperty("microedition.profiles"); int i = 0, j = 0; while ((j = prof.indexOf(’ ’, i)) != -1) { sb.append(" Profile/"); sb.append(prof.substring(i, j)); i = j + 1; } sb.append(" Profile/"); sb.append(prof.substring(i)); ua = sb.toString(); // Initialize the current locale locale = System.getProperty("microedition.locale"); if (locale == null) { locale = "en-US"; } } // Processes an HTTP connection request and returns the result // in a form that can be displayed for the end user. byte[] Process() { byte[] data = null; try { // Open connection, send data, and check response status open(); // Read the response (open would throw an IOException // if there were nothing to read.) int n = (int)con.getLength(); if (n > 0) { int bytesread = 0; data = new byte[n]; for (int offset = 0; offset < n; offset += bytesread) { bytesread = s.read(data, offset, n-bytesread); } } } catch (IOException ioe) {
259
260
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
// Close the connection and any open streams } finally { try { if (con != null) { con.close(); } if (os != null) { os.close(); } if (is != null) { s.close(); } } catch (IOException ioe) { return data; } } } // Open a connection to the server private void open() throws IOException { int status = -1; String url = baseurl; String auth = null; is = null; os = null; con = null; // Loop until a connection is made (in case of redirects) while (con == null) { // Set up the connection values (headers, and so on) con = (HttpConnection)Connector.open(url); con.setRequestMethod(HttpConnection.POST); con.setRequestProperty("User-Agent", ua); con.setRequestProperty("Accept-Language", locale); con.setRequestProperty("Content-Type", "text/plain"); con.setRequestProperty("Accept", "text/plain"); if (user != null && password != null) { con.setRequestProperty("Authorization", "Basic " + BasicAuth.encode(user, password)); }
SAMPLE CODE (NETCLIENTMIDLET.JAVA)
// Write the message to the output stream. Opening // the output stream might flush the headers os = con.openOutputStream(); os.write(msg.getBytes()); os.close(); os = null; // check status code (if the headers and message // were not flushed before, they will be sent now.) status = con.getResponseCode(); switch (status) { case HttpConnection.HTTP_OK: // Success! Calling method will read the response break; case HttpConnection.HTTP_TEMP_REDIRECT: case HttpConnection.HTTP_MOVED_TEMP: case HttpConnection.HTTP_MOVED_PERM: // Redirect: get the new location url = con.getHeaderField("location"); con.close(); con = null; break; default: // Error: throw an I/O exception con.close(); throw new IOException("Response status not OK:" + status); } } // Open input stream so the caller can read the response is = con.openInputStream(); } // Access methods for the fields of the class // Set the message to send to the server void setMsg(String s) { msg = s; }
261
262
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
// Set the user name to use to authenticate to server void setUser(String s) { user = s; } // Set the password to use to authenticate to server void setPassword(String s) { password = s; } }
BasicAuth.java The BasicAuth class is a utility class; it cannot be instantiated. It has a static method, encode, that creates and returns a string that holds the base64 encoding of its two string arguments. Note that the encode method provides only a subset of the functionality required by RFC2045 [reference 3]. It does not handle strings longer than 76 characters, line breaks, and so forth. package examples.netclient; // Encodes a user name and password in the base64 format that // HTTP Basic Authorization requires. This is a utility class: it // provides a static method and cannot be instantiated. class BasicAuth { // make sure no one can instantiate this class private BasicAuth() {} // Conversion table private static byte[] cvtTable = { (byte)'A', (byte)'B', (byte)'C', (byte)'F', (byte)'G', (byte)'H', (byte)'K', (byte)'L', (byte)'M', (byte)'P', (byte)'Q', (byte)'R', (byte)'U', (byte)'V', (byte)'W', (byte)'Z', (byte)'a', (byte)'b', (byte)'c', (byte)'f', (byte)'g', (byte)'h', (byte)'k', (byte)'l', (byte)'m', (byte)'p', (byte)'q', (byte)'r', (byte)'u', (byte)'v', (byte)'w', (byte)'z', (byte)'0', (byte)'1', (byte)'2', (byte)'5', (byte)'6', (byte)'7', (byte)'+', (byte)'/' };
(byte)'D', (byte)'I', (byte)'N', (byte)'S', (byte)'X',
(byte)'E', (byte)'J', (byte)'O', (byte)'T', (byte)'Y',
(byte)'d', (byte)'i', (byte)'n', (byte)'s', (byte)'x',
(byte)'e', (byte)'j', (byte)'o', (byte)'t', (byte)'y',
(byte)'3', (byte)'4', (byte)'8', (byte)'9',
SAMPLE CODE (NETCLIENTMIDLET.JAVA)
// Encodes a name-password pair appropriate to // use in an HTTP header for Basic Authentication. // name the user's name // passwd the user's password // returns String the base64 encoded name:password static String encode(String name, String passwd) { byte input[] = (name + ":" + passwd).getBytes(); byte[] output = new byte[((input.length / 3) + 1) * 4]; int ridx = 0; int chunk = 0; // // // //
} }
Loop through input with 3-byte stride. For each chunk of 3-bytes, create a 24-bit value, then extract four 6-bit indices. Use these indices to extract the base64 encoding for this 6-bit character for (int i = 0; i < input.length; i += 3) { int left = input.length - i; // We have at least three bytes of data left if (left > 2) { chunk = (input[i] 18]; output[ridx++] = cvtTable[(chunk&0x3F000) >>12]; output[ridx++] = cvtTable[(chunk&0xFC0) >> 6]; output[ridx++] = cvtTable[(chunk&0x3F)]; } else if (left == 2) { // Down to 2 bytes; pad with 1 '=' chunk = (input[i] 18]; output[ridx++] = cvtTable[(chunk&0x3F000) >>12]; output[ridx++] = cvtTable[(chunk&0xFC0) >> 6]; output[ridx++] = '='; } else { // Down to 1 byte; pad with 2 '=' chunk = input[i] >18]; output[ridx++] = cvtTable[(chunk&0x3F000) >>12]; output[ridx++] = '='; output[ridx++] = '='; } } return new String(output);
263
264
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.5 SocketConnection The SocketConnection interface extends interface javax.microedition.io.StreamConnection to define the API to TCP/IP or similar socket streams. (Refer to the doc-
umentation of interface StreamConnection on page 69.) Applications that need to accept connections from other applications must use ServerSocketConnection instead. See Section 15.6, “ServerSocketConnection” for more information. An application opens a socket on a target host by calling the Connector.open method. The application must provide a URI string that starts with ‘socket://’ and is followed by a host name and port number separated by a colon. For example, ‘socket://host.com:79’ has the correct syntax to open a socket connection on the host.com system at port 79. In the string the MIDlet can specify the host as a fully qualified host name or IPv4 number. Note that RFC1900 [reference 2] recommends the use of host names rather than IP numbers. Using the host name means the MIDlet can still make the connection, even if the host’s IP number is reassigned. For example, ‘socket://host.com:79’ is preferred to ‘socket://183.206.241.133:79’. If the connection string uses incorrect syntax, Connector.open throws an IllegalArgumentException exception. The Connector.open method returns a SocketConnection instance. It has methods that enable the MIDlet to get the local and remote addresses and the local and remote port numbers, and to control socket options. 15.5.1 Getting the Local Address and Port Number An application can get the local host address and port number for an open connection. (This information is needed primarily by applications that use a ServerSocketConnection to allow clients to make inbound connections to a system-assigned port. See Section 15.6, “ServerSocketConnection” for more information.) The getLocalAddress method returns the local IP number to which the socket is bound. Calling System.getProperty(“microedition.hostname”) returns the host name of the device, if it is available. The getLocalPort method returns the local port to which this socket is bound. If an application sends address and port information to a remote application so that it can connect to the device, the application should try to send the host name of the device. IP addresses can be dynamically assigned, so a remote application with only an IP address will not be able to make contact if the device IP number changes. If a host name is available, sending it would help the remote application be more robust.
SOCKETCONNECTION
15.5.2 Getting the Remote Host Address and Port An application can get the remote host address and port number for an open connection. The getAddress method returns the remote host (as either a host name or an IP address) to which the socket is bound. The getPort method returns the remote port to which this socket is bound. The methods get their return values from the string passed to Connector.open. 15.5.3 Getting and Setting Socket Options An application can control some low-level socket options to optimize interactions with the network. The socket options inform the low-level networking code about the application’s intended usage patterns. The options are listed in Table 15.2. The setSocketOption method sets the value for a socket option for the connection. The getSocketOption method returns the value for a socket option for the connection or 1 if the value is not available. Both methods throw an IllegalArgumentException if the value is not valid (for example, if the value is negative) or the option identifier is not valid. For example, if a MIDlet calls the setSocketOption method to assign buffer sizes, the device can use this as a hint about the sizes to set the underlying network I/O buffers. The system might adjust the buffer sizes to account for better throughput available from Maximum Transmission Unit (MTU) and Maximum Segment Size (MSS) data available from current network information. Table 15.2 Socket options Option
Description
DELAY
Small-buffer writing delay. Setting this option to zero disables the TCP Nagle algorithm for small buffer operations. Setting it to a nonzero value enables it.
KEEPALIVE
Keep-alive feature. Setting this option to zero disables the keep-alive feature. Setting it to a non-zero value enables it.
LINGER
Number of seconds to wait before closing a connection with pending data output. Setting the linger time to zero disables the linger wait interval.
RCVBUF
Size of the receiving buffer, in bytes.
SNDBUF
Size of the sending buffer, in bytes.
265
266
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.5.4 Closing Streams Every stream connection has an associated Connection object, InputStream and OutputStream. These objects have their own close methods and, on systems that support duplex communication over the socket connection, closing the input or output stream shuts down only that side of the connection. For example, closing the InputStream does not stop the OutputStream from sending data. Both the input and output stream must be closed before the connection is completely closed. Conversely, the application will receive an IOException if it tries to use a closed input stream, output streams, or socket connection. 15.5.5 Security of SocketConnection Access to a socket connection is restricted to prevent unauthorized transmission or reception of data. MIDlet suites needing to use sockets must request the javax.microedition.io.Connector.socket permission for Trusted MIDlet suites as described in Section 18.3, “Trusted MIDlet Suite Security Model.” The device may try to authorize the MIDlet when the MIDlet calls the Connector.open method with a valid socket connection string. If the authorization fails and the MIDlet is not allowed to use the socket API, the Connector.open method throws a java.lang.SecurityException. The device might also check the MIDlet’s permission when the MIDlet calls the openInputStream, openDataInputStream, openOutputStream, or openDataOutputStream methods. 15.5.6 Example The following example shows the use of a SocketConnection to send and receive text from the echo port of a remote host. Refer to previous examples for the complete handling of exceptions and closing of streams and the connection. // Open the socket and its associated streams. Set the linger time SocketConnection sc = (SocketConnection)Connector.open("socket://host.com:7"); sc.setSocketOption(SocketConnection.LINGER, 5); DataInputStream is
= sc.openDataInputStream();
DataOutputStream os = sc.openDataOutputStream(); // Write to and read from the remote echo port os.writeUTF("Hello World\n"); os.flush(); String result = is.readUTF();
ServerSocketConnection
// Close the connection and its streams is.close(); os.close(); sc.close();
15.6
ServerSocketConnection
The ServerSocketConnection interface defines the server socket stream API. A server socket connection is not a socket or stream connection; it only establishes that the application is accepting incoming connections. The ServerSocketConnection interface extends the interface javax.microedition.io.StreamConnectionNotifier, which listens for incoming connections. (Refer to the documentation of interface StreamConnectionNotifier on page 69.) An application establishes a server socket connection by calling the Connector.open method. The application must supply a URI string with the host omitted. For example, “socket://:7” defines an inbound server socket on port 7 (the echo port). If the application also omits the port number, the device dynamically selects an available port. For example, “socket://” defines an inbound server socket on a port allocated by the system. If the connection string is invalid, the Connector.open method throws an IllegalArgumentException. When the application needs to connect to the socket (for example, to handle an incoming request) it invokes the acceptAndOpen method of the server socket connection. The acceptAndOpen method returns a SocketConnection instance. See Section 15.5, “SocketConnection,” for information on the returned instance. As with other blocking network calls, the application should invoke these methods only in a thread designated for the purpose; use of the user interface callbacks to invoke these methods will block the user interface. 15.6.1 Getting the Local Address and Port Number An application can get the address and port on which the device will accept connections. The getLocalAddress method returns the IP address of the device. The getLocalPort method returns the assigned port number. See Section 15.5.1, “Getting the Local Address and Port Number” for more information, but remember that the values returned from the ServerSocketConnection versions of the methods are not the address and port of an active SocketConnection.
267
268
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.6.2 Security of ServerSocketConnection Access to a server socket connection is restricted to prevent unauthorized transmission or reception of data. MIDlet suites needing to use server sockets must request the javax.microedition.io.Connector.serversocket permission for Trusted MIDlet suites as described in Section 18.3, “Trusted MIDlet Suite Security Model.” The device tries to authorize the MIDlet when the MIDlet calls the Connector.open method with a valid server socket connection string. If the authorization fails and the MIDlet is not allowed to use the server socket API, the Connector.open method throws a java.lang.SecurityException. The device also checks the MIDlet’s permission when the MIDlet calls the acceptAndOpen method and might check when the MIDlet calls the openInputStream, openDataInputStream, openOutputStream, or openDataOutputStream methods. 15.6.3 Example The following example shows a ServerSocketConnection providing an echo service. (It does not, however, use the standard echo port, which is port 7.) The example also omits the exception handling needed in a complete program. // Create the server listening socket for port 1234 ServerSocketConnection scn = (ServerSocketConnection) Connector.open(“socket://:1234”); // Wait for a connection SocketConnection sc = (SocketConnection) scn.acceptAndOpen(); // When a connection is made, set the socket’s options sc.setSocketOption(DELAY, 0); sc.setSocketOption(LINGER, 0); sc.setSocketOption(KEEPALIVE, 0); sc.setSocketOption(RCVBUF, 128); sc.setSocketOption(SNDBUF, 128); // Get the input and output streams of the connection DataInputStream is = sc.openDataInputStream(); DataOutputStream os = sc.openDataOutputStream(); // Read the input data and echo it back to the sender String result = is.readUTF(); os.writeUTF(result);
UDPDatagramConnection
// Close the server socket, its socket, and the socket’s streams is.close(); os.close(); sc.close(); scn.close();
15.7 UDPDatagramConnection The UDPDatagramConnection interface extends the interface java.microedition.io.DatagramConnection to define a UDP datagram connection. (Refer to the documentation of interface DatagramConnection on page 69.) The UDP datagram protocol is defined by the IETF standard RFC768 [reference 1]. The protocol is message-oriented; delivery and duplicate protection are not guaranteed. Applications use UDP datagram connections to exchange messages with minimal overhead, but if ordered reliable delivery of streams of data is required, a SocketConnection is a better choice. An application opens a UDP datagram connection by calling the Connector.open method. The application must provide a URI string that starts with “datagram://” and is followed by a host name and port number separated by a colon. If the string has neither the host nor port fields, the device allocates an available port. If the connection string is invalid, an IllegalArgumentException is thrown. 15.7.1 Getting the Local Address and Port Number An application can get the local host address and port number for an open connection. (This information is needed primarily for applications that use UDPDatagramConnections to allow clients to send datagrams to a dynamically assigned port.) The getLocalAddress method returns the local IP number to which the socket is bound. Calling the method System.getProperty(“microedition.hostname”) returns the host name of the device, if it is available. The getLocalPort method returns the local port to which this socket is bound. If an application sends address and port information to a remote application so that it can connect to the device, the application should try to send the host name of the device. IP addresses can be dynamically assigned, so a remote application with only an IP address will not be able to make contact if the device IP number changes. If a host name is available, sending it would help the remote application be more robust.
269
270
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.7.2 Datagrams The UDPDatagramConnection interface inherits methods to create, send, and receive datagrams from the interface javax.microedition.io.DatagramConnection. Once created, a datagram can be used and reused for reading or writing. A Datagram consists of an address and a data buffer. The address is a URL string in the same syntax as described for the method Connector.open. If the datagram will be sent, the application uses the Datagram.setAddress method to assign a destination address. (The address must include both the host and port.) If the Datagram was received, the address contains the source address. The data buffer is a byte array with an offset and a length. An application can access the byte array either directly or indirectly through the datagram’s DataInputStream for reading and DataOutputStream for writing. The datagram’s getOffset and setOffset methods are the accessor methods for the offset of the first byte of data. The getLength and setLength methods are the accessor methods for the number of bytes of data in the datagram. The data buffer, offset, and length must be set before the Datagram is sent. Before receiving a Datagram, the buffer, offset, and length must also be set to indicate the bytes available to store the incoming message. The datagram also has a reset method that is used to initialize the internal state used for reading and writing. Mixing reads, writes, and direct access to the data buffer is not recommended because the interactions between them are complex. The number of bytes that the UDPDatagramConnection can handle for each send and receive may be limited. The getNominalLength method returns the normal size that the transport can handle in a single packet. The getMaximumLength method returns the upper limit on the size of a datagram. Some transports fragment a large datagram into smaller pieces for transport and reassemble them at the destination. 15.7.3 Closing Connections An application closes a UDP datagram connection with the javax.micromethod. The UDPDatagramConnection methods throw an IOException if an application attempts to call the methods after the connection has been closed.
edition.io.Connector.close
UDPDatagramConnection
15.7.4 Security of UDPDatagramConnection Access to datagrams is restricted to prevent unauthorized transmission or reception of data. MIDlet suites needing to use datagrams must request the javax.microedition.io.Connector.datagram permission for Trusted MIDlet suites as described in Section 18.3, “Trusted MIDlet Suite Security Model.” The device may try to authorize the MIDlet when the MIDlet calls the Connector.open method with a valid datagram connection string. If the authorization fails and the MIDlet is not allowed to use the UDP datagram connection API, the Connector.open method throws a java.lang.SecurityException. The device might also check the MIDlet’s permission when the MIDlet calls the receive or send methods. 15.7.5 Example Applications can use datagrams to asynchronously send and receive information. The following example uses a thread to receive datagrams of the maximum possible size on a known port and process the messages it receives. When it receives a zero length datagram it closes the connection and terminates. public void run() { UDPDatagramConnection c = null; Datagram dgram; try { // Open the UDP Datagram Connection c = (UDPDatagramConnection) Connector.open("datagram://:4444"); int max = c.getMaximumLength(); // Create a new datagram with a maximum-sized data buffer dgram = c.newDatagram(max); byte[] buf = dgram.getData(); // Read in and process datagrams (stop at an empty datagram) while (true) { dgram.setLength(max); c.receive(dgram); int len = dgram.getLength(); if (len == 0) { // All done: close and return break;
271
272
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
} else { // Process the data process(buf, len); } } } catch (IOException ex) { // handle the exception } finally { // Close the connection try { c.close(); } catch (IOException ex) { } }
15.8 CommConnection The CommConnection interface defines an API for a logical serial port connection. The CommConnection extends the StreamConnection interface, through which bytes are transferred using input and output streams. The underlying operating system defines the logical serial ports that can be used. Such a port does not need to correspond to a physical RS-232 serial port. For instance, IrDA IRCOMM ports are commonly configured as logical serial ports within the device. An application opens a serial port by calling the Connector.open method. The application must provide a URI string that begins with “comm:” followed by a port identifier, followed optionally by a semicolon and a semicolon-separated list of parameter-value pairs. The name of a parameter is separated from its value with an equals sign (=). Spaces are not allowed in the string. For example, “comm:COM0;baudrate=19200” is a valid string. The port identifier is a logical device name defined by the device. Port identifiers will probably be device-specific, so applications should use them with care. (See Section 15.8.3, “Recommended Convention for Naming Ports.”) Applications can get a comma-separated list of valid port identifiers for a particular device and operating system by calling the System.getProperty method with the key microedition.commports. Any additional parameters must be separated by a semicolon. If a particular optional parameter is not applicable to a particular port, the device is permitted to ignore it. Legal parameters are listed in Table 15.3. If the application supplies an illegal or unrecognized parameter, the Connector.open method throws an IllegalArgumentException. If the device supports a parameter value, it must be hon-
CommConnection
ored. If the device does not support a parameter value, the Connector.open method throws a java.io.IOException. If an option duplicates a previous option, the last value overrides the previous value. Table 15.3
CommConnection
parameters for opening serial connections
Parameter
Default
baudrate
platform dependent
Description Speed of the port in bits per second (such as 9600 or 19200)
bitsperchar
8
Number of bits per character (7 or 8)
stopbits
1
Number of stop bits per char (1 or 2)
parity
none
Parity (even, odd, or none)
blocking
on
Whether to wait for a full buffer. (on, which means wait, or off, which means do not wait)
autocts
on
Whether to wait for the CTS line to be on before writing (on, which means wait, or off, which means do not wait)
autorts
on
Whether to turn on the RTS line when the input buffer is not full (on, which means turn on the RTS line when the input buffer is not full, or off, which means the RTS line is always on)
Only one application may be connected to a particular serial port at a given time. The Connector.open method throws a java.io.IOException if an application tries to open the serial port when the connection is already open. 15.8.1 Getting and Setting the Serial Port Speed The application may need to know or set the baud rate (speed) of the serial port to communicate with an external device. There are two ways to set the baud rate. The application can set it in the Connector.open method by putting the optional parameter baudrate into the method’s URI string argument. The application can also set the baud rate after the connection is open with the setBaudRate method. If the application does not set a value, the baud rate defaults to a device-specific default value. If the application requests a baud rate that the device does not support, the system
273
274
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
may substitute a valid baud rate. The application determines the actual baud rate of the connection by calling the getBaudRate method. 15.8.2 Security for CommConnection Access to serial ports is restricted to prevent unauthorized transmission or reception of data. MIDlet suites needing to use serial ports must request the javax.microedition.io.Connector.comm permission for Trusted MIDlet suites as described in Section 18.3, “Trusted MIDlet Suite Security Model.” The device may try to authorize the MIDlet when the MIDlet calls the Connector.open method with a valid serial port connection string. If the authorization fails and the MIDlet is not allowed to use the serial port connection API, the Connector.open method throws a java.lang.SecurityException. The device might also check the MIDlet’s permission when the MIDlet calls the methods openInputStream, openDataInputStream, openOutputStream, or openDataOutputStream methods. 15.8.3 Recommended Convention for Naming Ports A logical port name can use any combination of alphanumeric characters except a semicolon. Although logical port names can be defined to match a platform’s naming conventions, implementations of the virtual machine should use the following convention: port names should contain a text abbreviation indicating port capabilities followed by a sequential number for the port. The following device name types should be used: •
COM#:
•
IR#:
where COM is for RS-232 ports and # is a number assigned to the port.
where IR is for IrDA IRCOMM ports and # is a number assigned to the
port. This naming scheme allows the API users to generally determine the type of port that they would like to use. For instance, if an application wants to beam a piece of data, the application could look for IR# ports for opening the connection. The alternative is a trial-and-error approach with all available ports. 15.8.4 Examples This section provides two examples of serial port access using the CommConnection interface. The first example shows how a CommConnection would be used to access a simple program that echoes the characters it receives. The second example shows
CommConnection
how to discover the serial ports available on the device and select the first available serial port. The following example shows a program that echoes characters through a CommConnection. // Open the CommConnection and its streams CommConnection cc = (CommConnection)Connector.open("comm:com0;baudrate=19200"); int baudrate = cc.getBaudRate(); InputStream is = cc.openInputStream(); OutputStream os = cc.openOutputStream(); // Write characters and read them back in int ch = 0; while (ch != ’Z’) { os.write(ch); ch = is.read(); ch++; } // Close the connection and its streams is.close(); os.close(); cc.close();
The following example shows how to discover the available serial ports on the device and select the first available serial port. // Get the comma-separated list of ports String port1; String ports = System.getProperty(“microedition.commports”); int comma = ports.indexOf(’,’); if (comma > 0) { // Parse the first port from the available ports list port1 = ports.substring(0, comma); } else { // Only one serial port available port1 = ports; }
275
276
CHAPTER 15
MIDP NETWORKING AND SERIAL COMMUNICATIONS
15.9 New for MIDP 2.0 MIDP Specification version 2.0 introduced several new network and communication APIs. The SocketConnection API can be used for reliable connections with servers without the overhead of HTTP. The ServerSocketConnection API allows a device to handle incoming connections. The UDPDatagramConnection API provides for low overhead but unreliable delivery of datagrams and has certain device and network caveats. The CommConnection API defines operations for accessing serial ports on a device if they are available. It must be kept in mind that there are many mobile devices that do not provide support for sockets, and therefore the availability of the networking protocols will vary from one device to another. The networks provided by different network operators may also have limitations in the support of specific networking protocols. Also, access to some of the protocols may be prohibited because of the security policies of the device or the network. Close cooperation with the device manufacturer and the network operators’ developer programs will be helpful in understanding how to use these APIs and how they may be enabled in particular networks.
C H A P T E R
16
Secure Networking Many mobile applications, especially those intended for mobile commerce, need secure transport protocols in order to ensure the integrity and confidentiality of transactions that are initiated by the applications. Secure protocols such as Secure Sockets Layer (SSL) and Transport Layer Security (TLS) have been in common use on the Internet for some time. The MIDP Specification version 2.0 now brings secure networking protocols also to the developers of J2ME applications. The MIDP Specification version 2.0 defines two secure networking interfaces: HttpsConnection and SecureConnection. The HttpsConnection interface extends the interface HttpConnection, and the SecureConnection interface extends the interface SocketConnection. When a MIDlet opens an HTTPS connection or a secure socket connection, the client device and the server establish a secure link by negotiating the secure protocol and cipher suite, and by exchanging credentials. Because the client and server components of mobile applications are usually designed and deployed together to satisfy a particular business need, the serverside infrastructure can define the confidentiality and integrity requirements. The client-side implementations needs to verify only that the client is communicating with the correct site and protocols. Secure networking protocols supported by MIDP 2.0 include SSL and TLS as well as the Wireless Application Protocol (WAP) secure protocol WTLS. Each protocol places requirements on certificates used for secure networking, as described in Section 16.4, “MIDP X.509 Certificate Profile.”
277
278
CHAPTER 16
SECURE NETWORKING
16.1 Checking the Security Properties of a Connection The device and the server negotiate the secure connection parameters based on mutually agreeable secure suites. After the connection has been established, the application can retrieve a SecurityInfo object and verify the integrity and server credentials of a negotiated connection. A MIDlet using an HTTPS or secure connection gets the object by calling the getSecurityInfo method on the open connection. If the MIDlet’s connection is not secure enough, it can report an error and close the connection. The application can use the SecurityInfo object to get the protocol name, protocol version, cipher suite, and certificate for a secure network connection. Table 16.1 lists the names and versions of the protocols available by calling the getProtocolName and getProtocolVersion methods of the SecurityInfo interface. Table 16.1 Secure protocols and version numbers Secure Protocol
Protocol Name
Version
SSL V3
“SSL”
“3.0”
TSL 1.0
“TLS”
“3.1”
WTLS (WAP-199)
“WTLS”
“1”
WAP TLS Profile and Tunneling Specification
“TLS”
“3.1”
The getCipherSuite method of the SecurityInfo interface returns the name of the cipher suite used for the connection. The name is usually one of the standard ciphers listed in the CipherSuite column of the CipherSuite definitions table in Appendix C of RFC 2246 [reference 4]. Non-TLS implementations should select the cipher suite name according to the key exchange, cipher, and hash combination used to establish the connection. This will ensure that equivalent cipher suites have the same name regardless of protocol. If the getCipherSuite method returns a non-null name that is not in Appendix C of RFC 2246 [reference 4], the cipher suite’s contents are specific to the device and server.
CHECKING THE SECURITY PROPERTIES OF A CONNECTION
16.1.1 Server Certificate An application calls the getServerCertificate method of the SecurityInfo object to get the server’s certificate. A Certificate object contains a subject, issuer, type, version, serial number, signing algorithm, dates of valid use, and serial number. The subject is the entity that vouches for the identity of the server; the issuer is the distinguished name of the entity that vouches for the identity of the subject. An application gets the subject from the getSubject method of the Certificate object and the issuer from the getIssuer method. The getIssuer method never returns null. The subject and issuer strings are formatted using the rules for the printable representation for X.509 distinguished names given in Section 16.1.2, “Printable Representation for X.509 Distinguished Names.” The type and version of the certificate are returned by the getType and getVersion methods of the Certificate object. The format of the version number depends on the specific type and specification, but is never null. For X.509 certificates, the value returned is X.509, and the version, per RFC 2459 [reference 7], is 2. The application gets the name of the algorithm used to sign the certificate from the getSigAlgName method of the Certificate object. The algorithm names returned should be one of the labels defined in RFC 2459, Section 7.2 [reference 7]. For example, md5WithRSAEncryption is a valid return value. The getSerialNumber method returns the printable form of the serial number of this Certificate or null if there is no serial number. A binary serial number should be formatted as a string using the binary-printable representation: a colonseparated list of bytes in which each byte is represented by two hex digits (capital letters for A–F). For example, “0C:56:FA:80” is in binary-printable representation. Each X.509 certificate is valid for only a specified period of time. The getNotBefore method of the Certificate object returns the time before which the certificate may not be used. The time is the milliseconds before which the certificate is not valid; the value zero means the certificate does not have its validity restricted by time. The getNotAfter method is the time after which the certificate is not valid. The time is the milliseconds after which the certificate is not valid (the expiration date); Long.MAX_VALUE is returned if the certificate does not have its validity restricted by time. Both times must be positive.
279
280
CHAPTER 16
SECURE NETWORKING
16.1.2 Printable Representation for X.509 Distinguished Names The distinguished name (DN) for an X.509 certificate is a semicolon-separated list of attributes. Each attribute has an object ID (represented by a label or a binary-printable representation) and a value. Table 16.2 lists common attributes and their labels. For example, “C=US;O=Any Company, Inc.;CN=www.anycompany.com” is a DN. Table 16.2 Labels for X.500 distinguished name attributes Object ID
Label
Binary-Printable Representation
id-at-commonName
CN
55:04:03
id-at-surname
SN
55:04:04
id-at-countryName
C
55:04:06
id-at-localityName
L
55:04:07
id-atstateOrProvinceName
ST
55:04:08
id-at-streetAddress
STREET
55:04:09
id-at-organizationName
O
55:04:0A
id-atorganizationUnitName
OU
55:04:0B
emailAddress
EmailAddress
2A:86:48:86:F7:0D:01:09:01
For string comparison purposes, the following rules define a strict printable representation that can be used for literal comparisons of distinguished names. 1. Attributes are separated by a semicolon. 2. There is no added white space around separators. 3. The attributes are in the same order as in the certificate; attributes are not reordered. 4. If an object-ID is in Table 16.2, the label from the table will be substituted for the object-ID. Otherwise, the object-ID is formatted as a string using the binary-printable representation described in Section 16.1.1, “Server Certificate.” 5. Each object ID or label within an attribute will be separated from its associated value by an equals sign (=), even if the value is empty. Any non-string value is formatted as a string using the binary-printable representation described in Section 16.1.1, “Server Certificate.”
HTTPSCONNECTION
16.2 HttpsConnection HTTPS is the secure version of the HTTP protocol [reference 9]. (See Section 15.3, “The HttpConnection Interface,” for more information.) The MIDP Specification version 2.0 requires a secure HTTP connection to comply with one or more of the following specifications: • HTTP over TLS: documented in both RFC 2818 [reference 11] and TLS Protocol Version 1.0 as specified in RFC 2246 [reference 4]. • SSL V3: specified in The SSL Protocol Version 3.0 [reference 12]. • WTLS: specified in the Wireless Application Protocol Wireless Transport Layer Security document WAP-199 [reference 13]. • WAP™ TLS Profile and Tunneling Specification WAP-219-TLS [reference 14]. The HttpsConnection interface extends the interface HttpConnection to define MIDP HTTPS API. The HttpsConnection interface has the same methods and behaviors as its superinterface, and adds information about the security parameters of the connection. An application accesses an HttpsConnection by calling the Connector.open method. The application must supply a URI with the scheme “https:”. RFC 2818 [reference 11] defines the scheme. A secure link must be established so the request headers can be sent securely. The secure link may be established as early as in the invocation of the Connector.open method. It may also be established when the application opens the connection’s input or output stream or calls methods that cause a transition to the connected state. (See Section 15.3, “The HttpConnection Interface,” for information on these methods.) Any method that can cause a secure link to be established may experience security-related failures; such methods throw a CertificateException to indicate these failures. 16.2.1 Security of HttpsConnection Access to the secure HTTP connection may be restricted to prevent unauthorized transmission or reception of data. Trusted MIDlet suites needing to use HTTPS must request the javax.microedition.io.Connector.https permission as described in “Trusted MIDlet Suite Security Model” on page 308. The device may try to authorize the MIDlet when the MIDlet calls the Connector.open method with a valid HTTPS connection string. If the authoriza-
281
282
CHAPTER 16
SECURE NETWORKING
tion fails and the MIDlet is not allowed to use the HTTPS API, the Connector.open method throws a SecurityException. The device might also check the MIDlet’s permission when the MIDlet calls the openInputStream, openDataInputStream, openOutputStream, and openDataOutputStream methods. 16.2.2 Example The following example shows a MIDlet using an HttpsConnection. The example opens the connection, reads the server’s response, and closes the connection and its input stream. The example does not set any request headers. It uses the default request method of GET, does not request that the response be in any particular language, and so on. See Section 15.3.5, “HTTP Request Headers,” for more information. void getViaHttpsConnection(String url) throws CertificateException, IOException { HttpsConnection c = null; InputStream is = null; try { // Open the secure connection using the URL provided c = (HttpsConnection)Connector.open(url); // Get the InputStream. This opens the connection if it was // not already done by Connector.open(). Opening the // connection does the SSL handshake and reads the // HTTP response headers. The implementation stores the // headers until the application requests them. is = c.openDataInputStream(); // Always check the response code if (c.getResponseCode() == HttpConnection.HTTP_OK) { // Get the length of the data int len = (int)c.getLength(); if (len > 0) { // If have the length, read it all in at once byte[] data = new byte[len]; int actual = is.readFully(data); ... } else { // If don’t have the length, read char by char int ch;
SECURECONNECTION
while ((ch = is.read()) != -1) { ... } } } else { // Handle error response codes // ... } } finally { // Close the connection and its input stream. if (is != null) is.close(); if (c != null) c.close(); } }
16.3 SecureConnection The SecureConnection interface defines the API for a secure socket connection. Interface SecureConnection, like its superinterface SocketConnection, allows a client to connect to a server and has the added benefit of a secure transport. The MIDP Specification version 2.0 requires that a SecureConnection comply with one or more of the following specifications: • TLS Protocol Version 1.0: specified in RFC 2246 [reference 4]. • SSL V3: specified in The SSL Protocol Version 3.0 [reference 12]. • WAP(TM) TLS Profile and Tunneling Specification: specified in WAP-219TLS-20010411-a [reference 14]. There is no support for the complementary server-side secure connection in the MIDP Specification version 2.0. An application opens a secure connection on a target host by calling the Connector.open method. The application must supply a GCF string with the scheme ssl, a host, and a port number. The host may be a fully qualified host name or an IPv4 number. For example, “ssl://host.com:79” defines a target socket on the host.com system at port 79. RFC 1900 [reference 2] recommends the use of names rather than IP numbers for best results in the event of IP number reassignment. Some networks and devices, however, may support only IP addresses since DNS name resolution may introduce additional latency and costs.
283
284
CHAPTER 16
SECURE NETWORKING
Unlike an HTTPS connection, the Connector.open method always opens the secure connection. If the secure connection cannot be established due to errors related to certificates, the Connector.open method throws a CertificateException. 16.3.1 Security of SecureConnection Access to secure connections may be restricted to prevent unauthorized transmission or reception of data. Trusted MIDlet suites needing to use an SSL/TLS connection must request the javax.microedition.io.Connector.ssl permission as described in Section 18.3, “Trusted MIDlet Suite Security Model.” The device may try to authorize the MIDlet when the MIDlet calls the Connector.open method with a valid connection string. If the authorization fails and the MIDlet is not allowed to use the secure socket API, the Connector.open method throws a SecurityException. The device might also check the MIDlet’s permission when the MIDlet calls the openInputStream, openDataInputStream, openOutputStream, and openDataOutputStream methods. 16.3.2 Example The following example shows how a SecureConnection would be used to access a program at a remote location that echoes back the characters sent to it. // Open the connection, check its protocol, and set its options SecureConnection sc = (SecureConnection)Connector.open("ssl://host.com:79"); SecurityInfo info = sc.getSecurityInfo(); boolean isTLS = (info.getProtocolName().equals("TLS")); sc.setSocketOption(SocketConnection.LINGER, 5); // Open the connection’s streams InputStream is
= sc.openInputStream();
OutputStream os = sc.openOutputStream(); // Write to the output stream and read from the input stream os.write("Hello World\n".getBytes()); int ch = 0; while (ch != -1) { ch = is.read(); } // Close the connection and its streams
MIDP X.509 CERTIFICATE PROFILE
is.close(); os.close(); sc.close();
16.4 MIDP X.509 Certificate Profile MIDP 2.0 devices are expected use standard Internet and wireless protocols and techniques for their transport and security. The protocols and techniques are based on the following Internet standards for public key cryptography: • WAP Certificate Profile Specification WAP-211-WAPCert-20010522-a [reference 15] (WAPCert). Devices must conform to all mandatory requirements in WAPCert, Appendix C, and should conform to all of its optional requirements except: ■
WAPCert Section 6.2, User Certificates for Authentication.
■
WAPCert Section 6.3, User Certificates for Digital Signatures.
• RFC 2437 – PKCS #1 RSA Encryption Version 2.0 [reference 6]. • RFC 2459 – Internet X.509 Public Key Infrastructure [reference 7]. MIDP 2.0 implementations must support X.509 Certificates and are permitted to support other certificate formats. RFC 2459 [reference 7] contains sections that are not relevant to a MIDP 2.0 implementation, however. The WAP Certificate Profile does not mention these functions. Implementations should exclude: ■
■
Requirements from Paragraphs 4 of Section 4.2 – Standard Certificate Extensions. A MIDP 2.0 implementation does not need to recognize extensions that must or may be critical, including certificate policies, name constraints, and policy constraints. Section 6.2 Extending Path Validation. Support for Policy Certificate Authority or policy attributes is not required.
285
286
CHAPTER 16
SECURE NETWORKING
16.4.1 Certificate Extensions A MIDP implementation must consider a version 1 X.509 certificate equivalent to a version 3 certificate with no extensions. A MIDP 2.0 device must recognize key usage (see RFC 2459 [reference 7] section 4.2.1.3) and basic constraints (see RFC 2459 [reference 7] section 4.2.1.10). It must be able to process certificates with unknown distinguished name attributes and unknown non-critical certificate extensions. It must also recognize the serialNumber attribute defined by WAPCert [reference 15] in distinguished names for Issuer and Subject. Although a MIDP 2.0 device may not recognize a certificate’s authority and subject key identifier extensions (see RFC 2459 [reference 7] sections 4.2.1.1 and 4.2.1.2), it must support certificate authorities that sign certificates using the same distinguished name using multiple public keys. 16.4.2 Certificate Size A MIDP 2.0 device must be able to process certificates that are not self-signed root certificate authority (CA) certificates of sizes up to at least 1500 bytes. 16.4.3 Algorithm Support A MIDP 2.0 device must support the RSA signature algorithm with the SHA-1 hash function, sha1WithRSAEncryption, as defined by PKCS #1. Devices that support these algorithms must be capable of verifying signatures made with RSA keys of lengths up to and including 2048 bits. A MIDP 2.0 device should support both the md2WithRSAEncryption signature algorithms and the md5WithRSAEncryption signature algorithm as defined in RFC 2437 [reference 6]. A MIDP 2.0 device that supports these algorithms must be capable of verifying signatures made with RSA keys of lengths up to and including 2048 bits. 16.4.4 Certificate Processing for HTTPS A MIDP 2.0 device must recognize the extended key usage extension defined in RFC 2818 [reference 11] if it is present and marked critical. When the extension is present, the device must verify that the extension contains the id-kp-serverAuth object identifier (see RFC 2459 [reference 7] section 4.2.1.13). SSL and TLS allow the web server to include the redundant root certificate (a self-signed root CA certificate) in the server certificate message. Web servers should not include it in a certificate chain. The device must ignore it if it is a version 1 certificate (as it will most likely be.)
NEW FOR MIDP 2.0
16.5 New for MIDP 2.0 The secure networking functionality described in this chapter is new in MIDP 2.0. The secure networking operations ensure the integrity and privacy of communications using standard secure network protocols. Interface HttpsConnection provides the application developer with the familiar popular network programming protocol HTTPS that integrates easily with the existing network servers and services. The SecureConnection interface extends the flexibility of sockets to the network infrastructure built on the reliable and robust SSL and TLS protocols. Both secure connection types make it easy to write robust and secure network applications.
287
This page intentionally left blank
C H A P T E R
17
Event-Driven Application Launch The MIDP Specification version 2.0 defines an option to automatically launch a MIDlet when a notification is received. Notifications can be network- or alarmbased. Network notifications, also known as push notifications, can occur when the device receives an incoming network connection for one of its MIDlets. Alarmbased notifications can occur at a time set by a MIDlet. Automatic launching is not a required device feature. Devices can support both types of notifications, only one type, or neither. Notifications can cause MIDlets to be launched without direct user intervention; users could be unaware of the activity. For example, if a device launches a MIDlet at a preset time, the user may not be present or paying attention. A number of security concerns arise from the potential to launch applications without direct user intervention. Security permissions and policy provide safeguards, however. They ensure that MIDlets can perform only activities allowed by the user. (MIDlets, whether launched automatically or at the request of the user, are always subject to the security policy of the device and any permissions the user has granted. See Section 18.3, “Trusted MIDlet Suite Security Model,” for more information.) For example, a user can require the device to ask permission before automatically launching a MIDlet.
17.1 Alarm-Based MIDlet Launch It can often be useful for a MIDlet to be launched at a preset time to provide information to the user in a timely fashion. For example, a MIDlet that sells movie tickets
289
290
CHAPTER 17
EVENT-DRIVEN APPLICATION LAUNCH
might set an alarm to warn the ticket-holding user about the impending start time of the movie. To use alarm-based notification, a MIDlet calls the PushRegistry.registerAlarm method. The MIDlet must supply the name of the MIDlet to launch (it must be a MIDlet in the same MIDlet suite) and a launch time. The named MIDlet must have been registered in the JAD file or the JAR manifest with a MIDlet-n attribute. Providing a launch time of zero removes any alarm. The push registry supports one alarm per MIDlet. If a registration occurs for a MIDlet that already has an alarm set, the new registration is used. The PushRegistry.registerAlarm method returns the old registration time in milliseconds since January 1, 1970, 00:00:00 GMT. Note that the time returned could be in the past. It returns zero for the MIDlet’s first alarm registration. Errors may occur during alarm registration. If the runtime system does not support alarm-based application launch, the registerAlarm method throws a ConnectionNotFoundException. If the MIDlet class name provided is null or is not in a MIDlet-n attribute in the MIDlet suite’s JAR manifest or JAD file, the registerAlarm method throws a ClassNotFoundException. If the MIDlet does not have permission to register an alarm, the registerAlarm method throws a SecurityException. (See Section 17.5, “Security of the Push Registry,” for more information.) A device could be unable to launch the MIDlet for the alarm. For example, a MIDlet cannot be launched if the device is off at the wake-up time. Similarly, the MIDlet cannot be launched if it is running at the wake-up time. As a result, MIDlets should be written to check the current time against the scheduled wakeup time. They can use class java.util.TimerTask to manage time-based events while they are running. (See Section 20.1, “Timer Support,” for more information.) As a general rule, do not use the alarm to periodically launch a MIDlet to check for new information. Polling is an inefficient use of phone and network resources. It can run down the battery if it activates the device too often and can incur extra network-usage costs, while providing little or no value to the consumer. Instead, use push notification: have the network service send messages to the MIDlet when new information should be presented to the user. If push notification cannot be used (for example, if the device does not support it), MIDlets that use alarm-based notification should be written to collapse or compress any duplicate events for MIDlets in the suite. This will help to avoid the usability problems associated with starting the MIDlet too frequently.
NETWORK-BASED MIDLET LAUNCH
17.2 Network-Based MIDlet Launch Devices can use protocols from the Generic Connection Framework (GCF) for their push functionality. (For more information, refer to Chapter 15, “MIDP Networking and Serial Communications.”) Launching a MIDlet when a network connection is received is an efficient mechanism to alert users to time-critical information. Not all protocols are appropriate for use as push connections. Even if a device supports a protocol for inbound connections, the device is not required to use that protocol in its push mechanism. For example, a device might support server socket connections in a MIDlet, but might not support launching a MIDlet in response to receiving a server socket connection. The three tasks that enable a MIDlet to be started to handle a push notification are registration, listening, and processing of the connection. During the registration phase, the system is given the expected network connection, the MIDlet to run, and a source-address filter. Listening is done by the Application Management Software (AMS). (See Section 19.2, “MIDP System Software,” for more information.) The AMS listens for the registered connections associated with MIDlets that are not running. Processing occurs when a registered connection is made: the AMS will run the corresponding MIDlet, and the MIDlet then assumes control of its connections. The steps for registration, listening, and processing are described in more detail below. MIDlets use the methods of the javax.microedition.io.PushRegistry class to find and open connections. It uses the normal GCF classes to read, write, and close the connection. When the MIDlet suite is active it is responsible for handling incoming connections. When the MIDlet suite is destroyed, AMS resumes listening for registered connections. 17.2.1 Registering a MIDlet to Be Launched MIDlet suites must register for push notifications. They can register either statically or dynamically. Static registration is done by adding attributes to the application descriptor, the JAR manifest, or both. It is called static registration because it uses information that is present at installation time. Static registrations remain valid until the MIDlet suite is removed from the device. Dynamic registration is done with the methods of the PushRegistry class. It is called dynamic registration because MIDlets can enable and disable push notifications as needed. They can also modify registrations as needed. If a MIDlet requires a particular connection in order to function correctly and will not need to change that connection while the MIDlet is on the device, the
291
292
CHAPTER 17
EVENT-DRIVEN APPLICATION LAUNCH
application developer should use static registration. Two MIDlet suites on a device cannot use the same connection. If two MIDlet suites have a push connection in common, they cannot be on the device at the same time and still function correctly. The device checks for connection conflicts at installation. If all the static push declarations can be fulfilled, then installation proceeds. If not, the user is notified that there are conflicts, and the MIDlet suite is not installed. (Refer to Chapter 19, “MIDlet Deployment,” for connection-conflict errors.) The end-user typically uninstalls one MIDlet in order to successfully install the other. If a MIDlet can be flexible in its push connections, the application developer should use dynamic registration. That is, dynamic registration is for MIDlets that can use (but do not require) a connection, require a connection for only a short period of time, do not need a well-known endpoint, or might have to change the connection during their lifetime. For example, consider a MIDlet that exchanges data with a server application using a private protocol and can allow the device to allocate a port. The MIDlet could open a connection without specifying a port number, causing the device to allocate an available port. Using the information in the open connection (such as the allocated port), the MIDlet would dynamically register the connection. The MIDlet would also send the connection information to the server application. The MIDlet and server application can then use this connection until the MIDlet unregisters or changes it. 17.2.2 Mechanics of Static Push Registration An application developer declares a static push registration with the MIDlet-Push-n attribute. The attribute can be in either the MIDlet suite’s JAD file or JAR manifest. During installation, the device registers the MIDlet to accept those connections. Each push registration entry consists of a colon-separated attribute-value pair. The attribute is to the left of the colon (:); the value is the comma-separated list to the right: MIDlet-Push-n: ConnectionURL, MIDletClassName, Filter
•
MIDlet-Push-n: attribute name. Multiple push registrations can be provided in
a MIDlet suite. The numeric value for n starts from 1 and must use consecutive ordinal numbers for additional entries. The first missing entry terminates the list. Any additional entries are ignored. (Note that the n value of this attribute does not correspond to the n value of the MIDlet-n attribute. MIDlet-Push-1 does not have to declare a push connection for the MIDlet-1.) •
ConnectionURL:
connection string used in the Connector.open method.
NETWORK-BASED MIDLET LAUNCH
•
MIDletClassName:
MIDlet responsible for the connection. The MIDlet class name must correspond to a MIDlet class name in a MIDlet-n attribute. If the named MIDlet appears more than once in the suite, the first matching entry is used. The device uses this information when it displays messages to the user regarding the applications. For example, it displays messages when it has detected push connections or when the user has granted or revoked permissions.
•
Filter:
restriction on which senders are valid for launching the requested MIDlet. The syntax and semantics of the Filter field depend on the addressing format used for the protocol. However, every filter can use the wildcard characters “*” and “?”. The semantics of those wildcard characters are:
■
■
*: matches any string, including an empty string. When the Filter value is only this character, connections will be accepted from any sender. ?:
matches any single character.
The MIDP Specification version 2.0 defines the syntax for datagram and socket inbound connections. The Filter for these push attributes must contain a numeric IP address in the same IPv4 and IPv6 formats as their respective URLs. (An IPv6 address includes the square brackets, as in the URL.) It is possible to use wild cards in the IP addresses. For example, 129.70.40.* allows subnet resolution. The port number is not part of the filter. When other specifications define push semantics for additional connection types, they must define the expected format for the connection URL string and the expected syntax for the filter field. The following example shows two entries. One would reserve a stream socket at port 79 and the other a datagram connection at port 50000. (Port numbers are maintained by IANA and cover well-known, user-registered, and dynamic port numbers. See IANA Port Number Registry.) MIDlet-Push-1: socket://:79, com.sun.example.SampleChat, * MIDlet-Push-2: datagram://:50000, com.sun.example.SampleChat, *
Static push registrations can cause errors during installation. Conditions that cause installation failure are syntax errors in the push attributes, declaring a connection endpoint that another MIDlet has already reserved, declaring a protocol that the device does not support for push, and referencing a MIDlet class name that is not listed in the MIDlet-n attributes of the MIDlet suite. A conflict-free installation reserves the requested connections for the exclusive use of the MIDlets in the MIDlet suite. If another application tries to open one of the connections, the attempt will fail with an IOException. In contrast, if a MIDlet in the suite tries to open one of the connections, the call will succeed unless the suite already has the connection open.
293
294
CHAPTER 17
EVENT-DRIVEN APPLICATION LAUNCH
17.2.3 Mechanics of Dynamic Push Registration The PushRegistry.registerConnection method registers a dynamic connection with Application Management Software (AMS). Once registered, the dynamic connection acts just like a statically registered connection. The arguments for the dynamic connection registration are the same as the Push-MIDlet-n attribute used for static registrations: the MIDlet must provide the connection string, the MIDlet to launch, and the filter string. The connection string includes the scheme, host, and port number as appropriate. The connection string can also include optional parameters, separated with semicolons. The MIDlet to launch must be listed in one of the MIDlet suite’s MIDlet-n attributes. The filter argument indicates which senders’ addresses are allowed to launch the MIDlet. See Section 17.2.2, “Mechanics of Static Push Registration,” for more information. Several kinds of errors can occur during dynamic registration. The device throws an IllegalArgumentException if the connection or filter arguments are null, a ClassNotFoundException if the MIDlet argument is null or names a class that cannot be found in the MIDlet suite, a ConnectionNotFoundException if the runtime system does not support push notification for the requested connection protocol, and an IOException if the connection is already registered or if there are insufficient resources to handle the registration request. The device throws a SecurityException if the MIDlet does not have permission to register a push connection. See Section 17.5, “Security of the Push Registry,” for more detail. The listConnections method gets a MIDlet suite’s registered connections; it returns an array of strings, one for each connection. If the method is called with an argument true, the array contains only the connections that have input available; if the argument is false, the array contains all of the MIDlet suite’s connections. Each connection string can be used with the getMIDlet and getFilter methods to return the other fields from the push registration. The getMIDlet and getFilter methods return null if the connection was not registered by the current MIDlet suite or if the connection argument was null. The unregisterConnection method removes dynamic registrations. An application developer calls the method with the same connection string used for the registration. The unregisterConnection method returns true if the removal was successful and false if the connection was not registered or if the connection argument was null. It throws a SecurityException if the connection was registered by another MIDlet suite. If the user deletes the application from the device, its dynamically registered push connections are unregistered automatically.
LISTENING AND LAUNCHING
17.3 Listening and Launching The Application Management Software (AMS) listens for registered connections and manages the launch of and transition to the appropriate MIDlet. It and the other software on the device provide a seamless integration of native and MIDP applications. The AMS handles the interactions among incoming connections, interrupting the user, starting and stopping applications, and handing off connections to MIDlets. It also enforces the device’s security policy and constraints. For example, if a native application is running when a notification arrives, the AMS must interrupt it. It must give the user control over the interruption (for example, user settings determine whether the interruption is to launch the new MIDlet or to get permission to launch it) and any transition to the MIDlet that responds to the network event. To make the transition, the AMS stops or pauses the running application. It and the other software on the device must work together to make the consumer experience smooth and natural. The AMS would do similar things if a MIDlet was running when a notification arrives. It would call either the pauseApp method or the destroyApp method to change to the MIDlet that responds to the connection. The MIDlet life cycle defines the duties of the interrupted MIDlet. (Refer to “MIDlet States” on page 82.) The implementation handles incoming connections in a way that allows them to be held and passed on to the MIDlet when it is started. The requirements for buffering of connections and messages are protocol-specific. There is a general requirement, though, that if a device buffers data, it must provide the buffered information to the MIDlet. The device should supply any buffered data when the launched MIDlet opens the related connection. When a device supports datagram connections for push notification, it must buffer at least the datagram that caused the startup of the MIDlet. It must also guarantee that when it starts a MIDlet in response to the incoming datagram, the buffered data will be available to the MIDlet when the MIDlet opens the UDPDatagramConnection. The requirement for devices that support socket connections for push notification is different. The device must guarantee that when it starts a MIDlet in response to an incoming socket connection, the MIDlet can accept the connection by opening the ServerSocketConnection, provided that the connection has not timed out.
295
296
CHAPTER 17
EVENT-DRIVEN APPLICATION LAUNCH
17.4 Handling Connections after Launch The MIDlet is responsible for handling incoming connections once it has been started. When a MIDlet associated with a push connection starts, it should first check why it was started. That is, it should get the list of available connections with input available. (See Section 17.2.3, “Mechanics of Dynamic Push Registration,” for information on the listConnections method.) If there are such connections, the MIDlet can assume it was started to handle them. The AMS holds onto the incoming connections until the MIDlet opens them. (This is known as handing off the connections to the MIDlet.) The MIDlet opens a connection by passing a connection string returned by the listConnections method directly to the Connector.open method. To prevent data loss, a MIDlet is responsible for all I/O operations on the connection from the time it calls the Connector.open method until it closes the connection. Application developers should avoid closing the connection too early. If the connection is closed but the MIDlet is still running, neither the AMS nor the application will be listening for push notifications. Inbound data could be lost if the application closes the connection before all data has been received. Application developers should also use a separate thread to perform input and output (I/O) operations and avoid blocking (and possibly deadlocking against) interactive user operations. A push application should behave in a predictable manner when handling asynchronous data it obtains through the push mechanism. A well-behaved application should inform the user that data has been processed. While it is possible to write applications that do not use any user visible interfaces, launching an application that only performs a background function could be a confusing user experience.
SECURITY OF THE PUSH REGISTRY
17.5 Security of the Push Registry The PushRegistry class is protected using the security framework and permissions. A MIDlet suite must have the javax.microedition.io.PushRegistry permission to register an alarm based launch and to statically or dynamically register for network notifications. Push registry permissions are also used to determine whether the user needs to be prompted before launching a MIDlet suite in response to a network or alarm-based notification. The security framework defines the general behavior for user permissions with the interaction modes of oneshot, session, and blanket. Their behavior is specialized for the PushRegistry and AMS, as described in the following list: •
Oneshot: prompt the
•
Session: prompt the
•
Blanket:
user before launching a MIDlet suite in response to a network or alarm-based notification, and for each push registry request (such as registering an alarm or connection).
user before launching a MIDlet suite in response to a network or alarm-based notification, or before the first push registry request (such as registering an alarm or connection) after each launch. The user is not prompted on subsequent uses of the push registry by the MIDlet.
prompt the user once when the MIDlet is being installed, before the first time the MIDlet suite is launched in response to a network or alarm-based notification, and before it uses the push registry.
In addition to needing permission to use the push registry, the MIDlet must also have permission to use server protocols. That is, the push mechanism uses protocols in which the device is acting as the server; it can accept connections from other entities on the network. To use the push mechanisms and accept connections, the MIDlet suite needs permission to use the protocols that it will use when it acts as a server. For example, a chat program that can be started in response to a socket connection notification would need to have the javax.microedition.io.Connector.serversocket permission. The chat program might use the following attributes in the manifest to request the permissions and static registrations it requires: MIDlet-Push-1: socket://:79, com.sun.example.SampleChat, * MIDlet-Permissions: javax.microedition.io.PushRegistry, javax.microedition.io.Connector.serversocket
297
298
CHAPTER 17
EVENT-DRIVEN APPLICATION LAUNCH
17.6 Sample Usage Scenarios This section provides two examples of MIDlets that are launched in response to a network notification. The first example is a Chat application that uses a well-known port for communication. The second example is a Ping application that dynamically allocates a port the first time it is started. 17.6.1 Sample Chat Application The Chat application uses push to receive a message on a well-known port. In order to concentrate on the push functionality, it does not show any corresponding MIDlet that would enable the user to reply to the message. Note: This sample is appropriate for bursts of datagrams because it loops on the connection, processing received messages. The JAD file for the Chat application’s MIDlet suite includes a static push connection registration shown in boldface. It also includes an indication that this MIDlet requires permission to use a datagram connection for inbound push messages. The following example code shows the JAD file: MIDlet-Name: SunNetwork - Chat Demo MIDlet-Version: 1.0 MIDlet-Vendor: Sun Microsystems, Inc. MIDlet-Description: Network demonstration programs for MIDP MicroEdition-Profile: MIDP-2.0 MicroEdition-Configuration: CLDC-1.0 MIDlet-1: InstantMessage, /icons/Chat.png, example.chat.SampleChat MIDlet-Push-1: datagram://:79, example.chat.SampleChat, * MIDlet-Permissions: javax.microedition.io.PushRegistry, javax.microedition.io.Connector.datagramreceiver
The following example code shows the Chat MIDlet. The startApp method launches a thread to handle the incoming data. (An inner class implements the Runnable interface.) Using a separate thread to handle network I/O is the recommended practice. It avoids conflicts between blocking I/O operations and userinteraction events. The thread receives messages until the MIDlet is destroyed. public class SampleChat extends MIDlet { // Current inbound message connection DatagramConnection conn;
SAMPLE USAGE SCENARIOS
// Flag to terminate the message reading thread boolean done_reading; public void startApp() { // List of active connections String connections[]; // Check to see if this session was started due to // inbound connection notification connections = PushRegistry.listConnections(true); // Start an inbound message thread for available // inbound messages for the statically configured // connection in the application descriptor for (int i=0; i < connections.length; i++) { Thread t = new Thread( new MessageHandler(connections[i])); t.start(); } ... } // Stop reading inbound messages and release the push // connection to the AMS listener public void destroyApp(boolean conditional) { done_reading = true; if (conn != null) conn.close(); // Optionally, notify network service that we’re // done with the current session ... } // Optionally, notify network service public void pauseApp() { ... } // Inner class to handle inbound messages on separate thread class MessageHandler implements Runnable { String connUrl ;
299
300
CHAPTER 17
EVENT-DRIVEN APPLICATION LAUNCH
MessageHandler(String url) { connUrl = url; } // Fetch messages in a blocking receive loop public void run() { try { // Get a connection handle for inbound messages // and a buffer to hold the inbound message. DatagramConnection conn = (DatagramConnection) Connector.open(connUrl); Datagram data = conn.newDatagram( conn.getMaximumLength()); // Read the inbound messages while (!done_reading) { conn.receive(data); ... } } catch (IOException ioe) { ... } }
17.6.2 Sample Ping Application The Ping application uses push to receive a a datagram and echo it back to the sender. Pings are often used to check whether a network entity is operational. In this sample, the JAD file associated with the Ping application’s MIDlet suite includes an entry (shown in boldface) indicating that the application will need permission to use the datagram connection for inbound push messages. It does not statically register for push notifications, however. The following example code shows the JAD file: MIDlet-Name: SunNetwork - Demos MIDlet-Version: 1.0 MIDlet-Vendor: Sun Microsystems, Inc. MIDlet-Description: Network demonstration programs for MIDP MicroEdition-Profile: MIDP-2.0 MicroEdition-Configuration: CLDC-1.0 MIDlet-1: JustCallMe, /icons/Ping.png, example.ping.SamplePingMe
SAMPLE USAGE SCENARIOS
MIDlet-Permissions: javax.microedition.io.PushRegistry, javax.microedition.io.Connector.datagramreceiver
The following example code shows the Ping MIDlet. The first time it is run, the MIDlet opens a connection and allows the device to assign it an available port. It uses the open connection during the first session to dynamically register the connection with the push registry and to send the connection to the network entity that might ping the device. The MIDlet can reopen the connection in subsequent sessions in response to a inbound connection notification. public class SamplePingMe extends MIDlet { // Name of the current application for push registration. String myName = "example.chat.SamplePingMe"; // List of registered push connections. String connections[]; // Inbound datagram connection UDPDatagramConnection dconn; public SamplePingMe() { // Check to see if the ping connection has been registered. // This is a dynamic connection allocated on first-time // execution of this MIDlet. connections = PushRegistry.listConnections(false); if (connections.length == 0) { // Request a dynamic port for out-of-band notices. // (Omitting the port number has the system allocate //
an available port number.)
try { dconn = (UDPDatagramConnection) Connector.open("datagram://"); String dport = "datagram://:"
+ dconn.getLocalPort();
// Register the port so the MIDlet will wake up, // if messages are posted after the MIDlet exits. PushRegistry.registerConnection(dport,myName,"*"); // Post my datagram address to the network ...
301
302
CHAPTER 17
EVENT-DRIVEN APPLICATION LAUNCH
} catch (IOException ioe) { ... } catch (ClassNotFoundException cnfe) { ... } } } public void startApp() { // Open the connection if it’s not already open if (dconn == null) { // This is not the first time this is run, because the // dconn has not been opened by the constructor // Check whether the startup has been due to an incoming // datagram connections = PushRegistry.listConnections(true); if (connections.length > 0) { // Open the pending datagram that can be received dconn = (UDPDatagramConnection) Connector.open(connections[0]); // Read the datagram Datagram d = dconn.newDatagram( dconn.getMaximumLength()); dconn.receive(d); } else { // There are no pending datagrams, but open // the connection for later use connections = PushRegistry.listConnections(false); if (connections.length > 0) { dconn = (UDPDatagramConnection) Connector.open(connections[0]); } } } } public void destroyApp(boolean unconditional) { // Close the connection before exiting
NEW FOR MIDP 2.0
if (dconn != null){ dconn.close(); dconn = null; } }
17.7 New for MIDP 2.0 Event-driven application launch is a new feature in MIDP 2.0. This feature makes it possible to create applications that can be launched at a preset time or that can respond to events generated by network services. The ability to define applications that will be launched on a specific network protocol event enables the creation of new kinds of services that can monitor information in the network and can notify a MIDlet suite automatically when the information changes. The event-driven launch of MIDlets is subject to the security policy of a device, and this feature can be enabled and disabled at the discretion of the user.
303
This page intentionally left blank
C H A P T E R
18
Security for MIDlet Suites Security in mobile devices presents many interesting and significant challenges. Mobile devices must enable users to take advantage of the applications and services provided on the Internet while still protecting them and their data. Many parties are interested in the security of mobile devices. Network operators have a strong interest in ensuring the integrity of the data that is sent over their networks so they can provide friendly, useful, lucrative, and reliable services to their customers. Mobile device manufacturers want to create usable, useful devices that provide a compelling experience for consumers. Software developers want to tap into the large and vibrant consumer market to sell games, entertainment, and productivity applications. Consumers want a device that is simple, fun, convenient, and easy to use. Consumers do not want to be inconvenienced, and they are generally discouraged by the presence of security mechanisms that make the devices more difficult to operate. The big challenge is to keep consumer confidence and convenience in balance. If the consumers do not believe that they can use mobile devices easily, safely, and reliably to access services, they will not use them. To be confident users of a device, consumers need to know their responsibilities and be aware of the limits on their liabilities. They need to be confident that they are using reliable technology that will not fail or compromise their privacy or security. They need to know that the companies they deal with have confidence in the device and network, and that the transactions that they initiate are safe. They need to have confidence in knowing that their personal information will not be used in unanticipated ways. They need to know when their use of the device is costing them money. These opportunities and constraints come together in the MIDP 2.0 security model. The MIDP Specification version 2.0 extends the sandbox security model used by MIDP 1.0. It introduces a security model that can safeguard the functions of 305
306
CHAPTER 18
SECURITY FOR MIDLET SUITES
the device that can expose the user to risk, such as the risk of incurring costs associated with wireless network use or the risk to personal privacy. The MIDP 2.0 security model is also extensible to optional APIs, such as SMS. The MIDP 2.0 security model tries to reconcile the competing goals of security and usability. Security concerns usually require frequent checking and rechecking that an action is allowed. Improving the usability of applications usually means reducing the number of steps and choices the user needs to make. Often the users first get annoyed and then habituated to repetitious prompts, and become accustomed to responding without really reading or making a conscious choice each time. This reduces or eliminates the effectiveness of security mechanisms that ask the user to confirm each and every access of protected functions. The MIDP 2.0 security model enables the device to enforce security policy based both on the authentication of the MIDlet suite (verification that it is genuine and has not been tampered with) and on the user choices. The device uses authentication information to define which permissions are allowed and which are delegated to the user. Only when the access permissions are delegated to the user must the implementation protect the resource by requiring an explicit confirmation from the user. This can reduce the number of prompts a user might receive, improving the effectiveness of the security mechanism.
18.1 Assumptions The following assumptions contributed to the design of the security mechanism and ensured ample flexibility in its implementation: • MIDlets do not need to be aware of the security policy except for security exceptions that may occur when using APIs. • A MIDlet suite is subject to a single protection domain and its permissible actions. (See Section 18.3.3, “Protection Domain,” for an explanation of protection domains.) • The internal representation of protection domains and permissions is implementation specific. (See Section 18.3.1, “Permissions,” for an explanation of permissions.) • The user interface for presenting configuration settings and the results of authentication attempts to the user is implementation-dependent and outside the scope of the MIDP Specification version 2.0. • The device must protect its security policy and its information on protection
SANDBOX FOR UNTRUSTED MIDLET SUITES
domains so that they are safe from viewing or modification except by authorized parties. • If the security policy for a device is static and disallows use of some functions of the security framework, then the implementation of unused and inaccessible security functions may be removed. • Security policy allows an implementation to restrict access but must not be used to avoid implementing security-sensitive functionality. For example, unimplemented protocols under the Generic Connection framework must throw a ConnectionNotFoundException, not a security-related exception.
18.2 Sandbox for Untrusted MIDlet Suites The MIDP Specification version 1.0 constrained MIDlet suites to operate in a sandbox that prevented access to sensitive APIs and functions of the device. This model was useful for many applications, and is included and formalized in the MIDP Specification version 2.0. A MIDlet suite compliant with MIDP 1.0 must be able to run on a MIDP 2.0 device as an untrusted MIDlet suite. An untrusted MIDlet suite is a MIDlet suite for which the origin and the integrity of the JAR cannot be reliably determined by the device. Untrusted MIDlet suites execute in a restricted environment where access to the protected APIs or functions is either not allowed or allowed only with explicit user permission. The restricted environment is the untrusted domain. The untrusted domain must allow, with explicit confirmation by the user, access to the protected APIs and functions in Table 18.1. Other restricted APIs on the device may be available to untrusted MIDlet suites depending on the security policy of the device. Table 18.1 APIs for which untrusted MIDlet suites require confirmation API
Protocol
javax.microedition.io.HttpConnection
HTTP
javax.microedition.io.HttpsConnection
HTTPS
307
308
CHAPTER 18
SECURITY FOR MIDLET SUITES
18.3 Trusted MIDlet Suite Security Model Today, many functions are provided by applications built into the device. Trust in the applications comes from trust in the device manufacturer and network operator who are clearly identified. Consumers also need to know and trust downloadable applications and their sources. The MIDP Specification version 2.0 introduces the concept of trusted MIDlet suites, which provides a level of authentication that allows the users to have such confidence. A trusted MIDlet suite is one for which the source, authenticity, and integrity of the JAR can be reliably determined by the device. The procedure for determining whether a MIDlet suite is trusted is devicespecific. Some devices might trust only MIDlet suites obtained from certain servers. Other devices might support only untrusted MIDlet suites. It is also possible for a device to authenticate MIDlet suites with the same strong security mechanisms that web sites rely on everyday: the Public Key Infrastructure (PKI). See Section 18.5, “Establishing Trust for MIDlet Suites by Using X.509 PKI,” for more information. Once the device trusts the MIDlet suite, it can grant the MIDlets in the suite permission to use protected functions. Determining whether to grant a requested permission is known as authorization. 18.3.1 Permissions Devices use permissions to protect access to APIs or functions that require authorization before being invoked. The permissions described in this section refer only to those APIs and functions that need security protection. They do not apply to APIs that do not require authorization and can be accessed by both trusted and untrusted MIDlet suites. (Section 18.4, “APIs That Are Not Security Sensitive,” covers the non-security-sensitive APIs.) A MIDP implementation typically gives trusted applications more access to security-sensitive APIs than untrusted MIDlets. To ensure that access is granted appropriately, the implementation checks permissions prior to each invocation of a protected function. MIDlet suites must have their permission request granted before the implementation provides the function.
TRUSTED MIDLET SUITE SECURITY MODEL
Table 18.2 summarizes the permissions that apply to the restricted APIs. Table 18.2 Summary of Permissions defined by the MIDP Specification Permission
Restricted API
javax.microedition.io. Connector.http
javax.microedition.io. HttpConnection
javax.microedition.io. Connector.https
javax.microedition.io. HttpsConnection
javax.microedition.io. Connector.datagram
javax.microedition.io. UDPDatagramConnection
javax.microedition.io. Connector.datagramreceiver
javax.microedition.io. UDPDatagramConnection
javax.microedition.io. Connector.socket
javax.microedition.io. SocketConnection
javax.microedition.io. Connector.serversocket
javax.microedition.io. ServerSocketConnection
javax.microedition.io. Connector.ssl
javax.microedition.io. SecureConnection
javax.microedition.io. Connector.comm
javax.microedition.io. CommConnection
javax.microedition.io. PushRegistry
javax.microedition.io. PushRegistry
Permission Names The names of permissions are case-sensitive and have a hierarchical organization similar to package names in the Java™ programming language. The names of the permissions for an API must begin with the package name of the API. If the permission is for functionality provided by a specific class in the package, then the permission must begin with both the package and class names. Any additional modifiers may be appended after a period (.) separator. The set of valid characters for permission names is the same as the set for package and class names. Permission names should use the same conventions for capitalization as package names. For example, javax.microedition.io.Connector.datagram is the permission that protects the use of datagram functionality. As the permission name indicates, the class javax.microedition.io.Connector (a static factory class for creating new connection objects) provides the datagram connection. The class also pro-
309
310
CHAPTER 18
SECURITY FOR MIDLET SUITES
vides connection objects for other protocols, hence the period followed by the modifier datagram in the permission name. Creating New Permissions Each API that provides access to protected functionality defines its own permissions. The MIDP Specification version 2.0 defines permissions for its protected APIs. APIs defined outside of the MIDP Specification version 2.0 must have a single document that specifies any necessary permissions and the behavior of the API when it is implemented for MIDP 2.0. 18.3.2 Requesting Permissions for a MIDlet Suite A MIDlet suite might require access to some protected APIs or functions and consider access to others optional. A MIDlet suite that requires access to protected APIs or functions must request the corresponding permissions by listing them in the MIDlet-Permissions attribute of its JAR manifest or application descriptor (JAD). A MIDlet should list permissions using this attribute only if the permissions are critical to the function of the MIDlet suite (that is, the MIDlet will not operate correctly without them). A MIDlet suite that can use protected APIs, but can function correctly without them, should request the corresponding permissions by listing them in the MIDletPermissions-Opt attribute of its JAR manifest or application descriptor. The MIDlet suite should be able to run with reduced functionality without these noncritical permissions. For example, perhaps the user can play a game MIDlet as a single-player game if the permissions cannot be granted, instead of as a networkaware game. For example, to require permission to be launched for an alarm (a PushRegistry function) and to conditionally require a SecureConnection, a MIDlet suite would use the following attribute-value pairs in its JAR manifest or application descriptor: MIDlet-Permission: javax.microedition.io.PushRegistry MIDlet-Permission-Opt: javax.microedition.io.Connector.ssl
Multiple permissions are separated by a comma. Leading and trailing white space and tabs are ignored.
TRUSTED MIDLET SUITE SECURITY MODEL
18.3.3 Protection Domain A protection domain defines a set of permissions and related interaction modes. (See Section 18.3.4, “Interaction Modes for User Permissions,” for more information.) A device places each MIDlet suite into a protection domain. The domain’s permissions are the only permissions that the device can grant to the MIDlets of the suite. For example, Section 18.2, “Sandbox for Untrusted MIDlet Suites,” covered the access rights in the untrusted domain. A protection domain consists of permissions that are either: •
Allowed:
•
User: MIDlet suites
MIDlet suites in the protection domain are given access to the protected function without any user interaction.
in the protection domain are given access to the protected function only after the user authorizes it. The implementation must give the user a prompt, and the user can choose a user permission interaction mode (see the next subsection) or deny the request.
18.3.4 Interaction Modes for User Permissions A User permission requires the user to either deny permission to use a specific API or function or to grant permission by choosing one of the following interaction modes: •
blanket:
•
session:
•
oneshot:
Grants permission for every invocation of an API or function by the MIDlet suite until it is uninstalled or the permission is changed by the user.
Grants permission for invocations of an API or function by the MIDlet until the MIDlet terminates. A session interaction mode must prompt the user on or before the first invocation of the protected API or function. When the user relaunches the MIDlet suite, the prompt must be repeated. Grants permission for only the current invocation of an API or function. A oneshot interaction mode must prompt the user on each invocation of the protected API or function.
The security policy of the device implementation determines the choice of interaction modes for user permissions. The policy defines, for each user permission, the default interaction mode and a set of other interaction modes from which the user may choose. The implementation may offer the user the default interaction mode if it is supplied.
311
312
CHAPTER 18
SECURITY FOR MIDLET SUITES
18.3.5 Granting Permissions to Trusted MIDlet Suites The process of authorizing a MIDlet suite is established by the relationships between: • A set of permissions for the protected APIs and functions on the device. This is a union of all permissions defined by every API on the device for protected functions. • A protection domain consisting of a set of Allowed and User permissions. • A set of permissions requested by the MIDlet suite in the MIDlet-Permissions and MIDlet-Permissions-Opt attributes of its JAR manifest or application descriptor. • The user who may be asked to grant permissions. To authorize a trusted MIDlet suite, the MIDlet suite must be in a protection domain. In addition, the MIDP implementation must have gotten the critical and non-critical permission requests from its JAR manifest or application descriptor, and must remove from consideration any non-critical permissions that are unknown to it. The permissions that can be granted to the MIDlet suite are the intersection of the requested permissions with the union of the Allowed and usergranted permissions in the protection domain. A MIDP implementation authorizes a MIDlet suite for the first time when the user tries to install it. The MIDlet suite must meet the following authorization requirements, or it will not be installed: • If the MIDlet-Permissions and MIDlet-Permissions-Opt attributes are in both the application descriptor and in the JAR manifest, their values must be identical. If the values are not identical, the system will not install the MIDlet suite. • All requested critical permissions must be known to the implementation. If any of the requested critical permissions are unknown, the MIDlet suite is not installed and cannot be launched. • All requested critical permissions must be present in the protection domain. If any of the requested critical permissions are not present in the protection domain, the MIDlet suite is not installed and cannot be launched. A MIDP implementation also authorizes a MIDlet suite when it tries to access a protected API. (During execution, protected APIs must check for the appropriate permissions.) If the MIDlet’s protection domain protects the security-sensitive API with a User permission, the user must provide authorization in order to grant
APIS THAT ARE NOT SECURITY SENSITIVE
those permissions to the MIDlet suite. The MIDP implementation is responsible for making the request to the user and getting the response to allow or deny the request. When the implementation prompts the user, it should provide a description of the requested permissions that is clear enough to enable a well-informed choice. The user must always be able to deny permission. The result of a successful authorization is that the MIDlet suite is granted access to the protected API. If the permission was not granted, the protected API must throw a SecurityException.
18.4 APIs That Are Not Security Sensitive APIs and functions that are not security sensitive are accessible by all MIDlet suites. These APIs are listed in Table 18.3. Table 18.3 APIs freely permitted for all MIDlet suites API
Description
javax.microedition.rms
RMS APIs
javax.microedition.midlet
MIDlet Life-cycle APIs
javax.microedition.lcdui
User Interface APIs
javax.microedition.lcdui.game
The Game APIs
javax.microedition.media javax.microedition.media.control
The multimedia APIs for playback of sound
18.5 Establishing Trust for MIDlet Suites by Using X.509 PKI The mechanisms for signing and authenticating MIDlet suites are based on Internet standards for public key cryptography RFC 2437 [reference 6], RFC 2459 [reference 7], RFC 2560 [reference 8], and WAPCERT [reference 15]. A developer can put a digital signature of the MIDlet suite’s JAR and a certificate in the MIDlet suite’s application descriptor. A digital signature is a piece of data, created with the private key of a private-public key pair, that ensures the JAR has not been tampered with. A certificate contains the corresponding public key that can be used to check the digital signature in the JAR and the signature of an entity that vouches that the public key in the certificate is genuine. The application descriptor can also have
313
314
CHAPTER 18
SECURITY FOR MIDLET SUITES
another certificate that contains the public key of the vouching entity and the signature of the entity that vouches for it. This can continue until there is a certificate for a well-known and trusted entity that does not need another entity to vouch for it; it vouches for itself. Such an entity is called a certificate authority (CA), and the certificate is said to be self-signed. Self-signed certificates are also called root certificates. Root certificates reside on the device, not in the application descriptor. A series of certificates that begins with the JAR signer and ends with a CA is called a certificate chain. Normally the development environment for MIDP applications will include tools to handle signing of a MIDlet suite and putting the appropriate certificates into the suite’s application descriptor, so application developers should not have to understand these details. However, developers may still need to be aware of the protection domains on their target devices so that they can obtain the appropriate certificates. When a user tries to install a signed MIDlet suite, the device authenticates the suite by verifying the signer certificates and JAR signature. Authentication enables the device to assign the MIDlet suite to a protection domain and appropriately authorize the MIDlets. Devices associate protection domains with CAs. For example, the device might assign the MIDlet suites that use the device manufacturer for their root certificate to one domain and the MIDlet suites that use the MIDP implementor for their root certificate to another. The root certificate associated with a protection domain is called the protection domain root certificate. In the case where there is a trusted relationship (possibly bound by legal agreements), the owner of a protection domain root certificate may delegate signing MIDlet suites to a third party and, in some circumstances, the author of the MIDlet. 18.5.1 Signing a MIDlet Suite The signer of a MIDlet suite might be the developer or an entity responsible for distributing, supporting, and perhaps billing for the use of the MIDlet suite. The signer is responsible for ensuring that the MIDlet suite’s applications are not malicious and will not harm assets or capabilities. The signer must exercise duediligence in checking the MIDlet suite before signing it. The signer must have a private and public key pair. The signer uses the private key to sign the MIDlet suite, and provides the public key in an RSA X.509 certificate for the MIDlet suite’s application descriptor. That certificate might be validated by another certificate, and so on, except for the final certificate in the application descriptor. The final certificate in the application descriptor is validated by a protection domain root certificate on the device.
ESTABLISHING TRUST FOR MIDLET SUITES BY USING X.509 PKI
The signature of a MIDlet suite protects only the JAR containing the manifest, the MIDlets’ classes, and any additional resources. The signature does not protect the application descriptor; it is not secured. Attributes defined within the manifest are protected by the signature, but attributes in the application descriptor are not. Because attributes defined in the application descriptor are not secured, when an attribute appears in the manifest, it must not be overridden by a different value from the application descriptor. For trusted MIDlet suites, the value in the application descriptor must be equal to the value of the corresponding attribute in the manifest. If not, the MIDlet suite must not be installed. The MIDlet.getAppProperty method returns the attribute value from the manifest if one is defined. If not defined, the value from the application descriptor, if any, is returned. Note that the requirement for attribute values to be equal differs from MIDP 1.0 and must be used for applications that are signed and verified by these procedures. For untrusted MIDlet suites, the MIDP 1.0 rule gives priority to application descriptor attributes instead of manifest attributes. Examples of MIDlet Suite Signing There are many ways to structure protection domain root certificates and their associated signing policies. These examples show two possibilities. Example 1 – Developer Owns Signing Certificate
This example covers the case where the developer owns the signing certificate and uses it to sign the application. In this case, the origin of the MIDlet suite is encoded into the application descriptor; it is the identity of the signer. 1. Developer creates a MIDlet. 2. Developer encodes permission requests into the JAR’s manifest and creates a final MIDlet suite JAR. 3. Developer generates a private-public key pair with a signing certificate and has the certificate signed by one or more protection domain root certificates. 4. Developer’s certificate is used to sign the MIDlet’s JAR and create the associated entries in the application descriptor. 5. MIDlet suite can be distributed with a suitably populated application descriptor and run on a MIDP 2.0-compliant device that has an appropriate protection domain root certificate, as long as the certificate is valid.
315
316
CHAPTER 18
SECURITY FOR MIDLET SUITES
Example 2 – Protection-Domain Stakeholder Owns Signing Certificate
This example covers the case where the signer’s identity (not the MIDlet suite developer) is encoded into the application descriptor. 1. Developer creates a MIDlet. 2. Developer encodes permissions into the JAR’s manifest and creates a final MIDlet JAR. 3. The protection domain stakeholder’s signing certificate (not necessarily the root certificate) is used to sign the MIDlet JAR and create the associated entries in the application descriptor. 4. The MIDlet suite can be distributed with a suitably populated application descriptor and run on a MIDP 2.0-compliant device that has an appropriate protection domain root certificate, as long as the certificate is valid. Creating the Signing Certificate The signer will need to be aware of the authorization policy for the target device and identify which protection domain the MIDlet suite should operate in. The domain’s protection domain root certificate must be the root of the certificate chain. The signer will need to contact the appropriate certificate authority. At the time of this writing, the best place to begin to determine the correct domain and certificate authority is to contact the developer program of the network operator or the device manufacturer. The signer might need to send its distinguished name (DN) and public key (normally, packaged in a certificate request) to the certificate authority who would create a RSA X.509 (version 3) certificate and return it to the signer. If the MIDlet suite will need to run on devices with different protection domains or protection domain root certificates, then the signer would need to use the same public key for verification but get a different signing certificate from each certificate authority. All of the signer certificates in the MIDlet suite’s application descriptor must contain the same public key. The signer should also remain aware of the certificate’s status. If the certificate expires, new installs will not succeed. If the certificate is disabled or revoked, every user on every device that supports revocation will have their execution permissions revoked. Inserting Certificates into the Application Descriptor
The certificate chain, except the root certificate, must be included in the application descriptor. The root certificate will be found on the device. Each certificate in the
ESTABLISHING TRUST FOR MIDLET SUITES BY USING X.509 PKI
path is encoded (using base64 but without line breaks) and inserted into the application descriptor as: MIDlet-Certificate-n-m: base64-encoding-of-certificate
The certificates are numbered to define the sequence in which they are examined. The number n is one (1) for the first certificate chain in the descriptor. The number n should increment by one for each subsequent certification chain. The order defines the sequence in which the certificate chains are tested to see if the corresponding root certificate exists on the device. The number m is one (1) for the signer’s certificate in a certification chain and increments by one for each subsequent intermediate certificate (if any). Creating the RSA SHA-1 Signature of the JAR
The signature of the MIDlet suite JAR is created with the signer’s private key according to the EMSA-PKCS1-v1_5 encoding method of PKCS #1 version 2.0 standard [reference 6]. The signature is base64 encoded, formatted as a single MIDlet-JarRSA-SHA1 attribute without line breaks and inserted in the application descriptor. MIDlet-Jar-RSA-SHA1: base64-encoding-of-Jar-signature
18.5.2 Authenticating a MIDlet Suite When a MIDlet suite is downloaded, a device that recognizes MIDlet suites signed using PKI as trusted must check whether authentication is required. If the attribute MIDlet-Jar-RSA-SHA1 is present in the application descriptor, then the JAR must be authenticated by verifying the signer certificates and JAR signature. Application descriptors without the MIDlet-Jar-RSA-SHA1 attribute are not authenticated but are installed and invoked as untrusted MIDlet suites. Verifying the Signer’s Certificate When a device verifies the signer certificate, it tries to find a certificate chain that ends with a root certificate on the device. (Root certificates may also be present in removable media such as a SIM(WIM) card or a USIM module. The device implicitly trusts these roots to verify the integrity and authentication of MIDlet suites.) To verify a signature, the device extracts a certificate chain from the application descriptor. It first gets attributes MIDlet-Certificate-1-m, where m starts at one and increments by one until there is no attribute with the given name. The value of each attribute is a base64-encoded certificate that it must decode and parse.
317
318
CHAPTER 18
SECURITY FOR MIDLET SUITES
The device validates the certificate chain using the basic path validation processes described in RFC 2459 [reference 7] with the protection domains as the authoritative source of protection domain root certificates. The MIDlet suite is bound to the protection domain that contains the protection domain root certificates that validates the first chain from signer to root and proceed with installation. If no protection domain root certificate validates the first chain, the device checks for other certificate chains. If there are multiple chains present, the device should check the chain with the attributes MIDlet-Certificate-2-m, and so on, until a chain can be validated or there are no more chains to check. Table 18.4 indicates how the results of certificate verification are acted upon. Table 18.4 Actions upon completion of signer certificate verification Outcome of Certificate Chain Validation
Subsequent Action
Attempted to validate n paths, but no public keys of the issuer of the certificate can be found or none of the certification paths can be validated.
Authentication fails; the MIDlet suite will not be installed.
More than one full certificate path established and validated.
Installation proceeds using the first successfully verified certificate path; next step is verification of the JAR signature.
Only one full certificate path established and validated.
Implementation proceeds; next step is verification of the JAR signature.
Verifying the MIDlet Suite JAR The MIDlet suite JAR is verified to insure the integrity of the application. The attribute is retrieved from the application descriptor and decoded from base64 yielding a PKCS #1 signature. The signer’s public key from the signer certificate is used to verify the signature. If the signature verification fails, the MIDlet suite is rejected. The SHA-1 hash of the MIDlet suite JAR must match the message digest in the signature. If it does not match, the device must not install the JAR or allow MIDlets from the MIDlet suite to be invoked. Once the steps of verifying the certificate, verifying the signature, and verifying the JAR all succeed, the MIDlet suite contents are known to be intact and the identity of the signer is known.
MIDlet-Jar-RSA-SHA1
ESTABLISHING TRUST FOR MIDLET SUITES BY USING X.509 PKI
Results of MIDlet Suite Source Verification It is essential that the steps performed to verify the digital signature as previously described lead to proof of the identity of the MIDlet suite signer. The results of the verification have a direct impact on authorization. Table 18.5 summarizes the state in which the device found the MIDlet suite and where the signature verification led. Table 18.5 Summary of MIDlet suite source verification Initial State of MIDlet Suite
Verification Result
Implications for Authorization
JAD not present. JAR was downloaded.
Authentication cannot be performed.
Installation permitted; MIDlet suite is treated as untrusted.
JAD present. JAR is unsigned.
Authentication cannot be performed.
Installation permitted MIDlet suite is treated as untrusted.
JAR signed. No root certificate on the device to validate the certificate chain.
Authentication cannot be performed.
Installation not permitted.
JAR signed. A certificate on the path is expired.
Authentication cannot be completed.
Installation not permitted.
JAR signed. A certificate rejected for reasons other than expiration.
JAD rejected; authentication failed.
Installation not permitted.
JAR signed. Certificate path validated Signature verification fails.
JAD rejected; authentication failed.
Installation not permitted.
JAR signed. Certificate chain validated Signature verified.
Authentication succeeded.
Installation permitted; MIDlet suite assigned to the protection domain associated with the corresponding protection domain root certificate.
319
320
CHAPTER 18
SECURITY FOR MIDLET SUITES
18.5.3 Caching of Authentication and Authorization Results The authentication and authorization processes may store and transfer their results for subsequent use. The MIDP implementation must protect the cached information so that it cannot be tampered with or otherwise compromised between the time it is computed and the time the authorization information is used. It is also essential that the MIDlet suite and security information used to authenticate and authorize a MIDlet suite (that is, the raw material for the authentication and authorization process) is not compromised. This could happen, for example, if the implementation used removable media or other MIDlet suite storage that might be corrupted. 18.5.4 X.509 Certificate Profile for Trusted MIDlet Suites Secured, trusted MIDlet suites use the same base certificate profile as HTTPS. The profile is based on the WAP Certificate Profile, WAP-211-WAPCert-20010522-a [reference 15] which is based on RFC 2459 [reference 7]. See Section 16.4, “MIDP X.509 Certificate Profile,” for more information. Certificate Processing for Over-The-Air (OTA) Delivery Devices must recognize the key usage field. When the field is present, the device must verify that it has the digitalSignature bit set. Devices must recognize the critical extended key usage field. When the field is present, the device must verify that the extension contains the id-kpcodeSigning object identifier. (See RFC 2459 section 4.2.1.13 [reference 7].) The application descriptor should not include a self-signed root certificate in a certificate chain. However, MIDP devices should treat the certificate as any other in a chain and not explicitly reject a chain that contains a X.509v3 self-signed CA certificate. Certificate Expiration and Revocation A device checks expiration and, optionally, revocation of certificates supplied in the application descriptor during the authorization procedure. A device can check for certificate expiration locally because it can get the information from the certificate itself. Certificate expiration verification is an intrinsic and mandatory part of certificate path validation. Certificate revocation is a more complex check, because a device has to send a request to a server and make a decision based on the response. A device can perform certificate revocation, but such mechanisms are not part of MIDP implemen-
RECOMMENDED SECURITY POLICY FOR GSM/UMTS DEVICES
tation and hence do not form a part of MIDP 2.0 security framework. If a device implements certificate revocation, it should support Online Certificate Status protocol (OCSP) [reference 8]. If other certificate revocation protocols are supported, and they indicate that a certificate has been revoked, the device may consider the certificate as revoked regardless of the result returned by the OCSP protocol.
18.6 Recommended Security Policy for GSM/UMTS Devices The MIDP Specification defines the security model and mechanisms to determine whether applications can be trusted, and for them to request specific permissions. The specification does not mandate a specific policy or how those mechanisms are used. The Recommended Security Policy for GSM/UMTS Devices (see the MIDP Specification version 2.0) describes a policy recommended by the GSM operators. The purpose of the policy is to allow consistent application behavior across GSM and UMTS devices and networks.
18.7 New for MIDP 2.0 The entire security model for MIDlet suites is new in MIDP 2.0. Unlike in MIDP 1.0, the MIDlets are no longer restricted to run only in a sandbox. Flexible mechanisms are now provided to establish a security policy for a MIDP device. The new model is extensible for use with J2ME optional packages and other APIs such as the Wireless Messaging API and the Mobile Media API. The new model can take advantage of the existing PKI infrastructure to ensure the integrity and authentication of the source of MIDlet suites. Through the protection domains, the new model enables the implementation of a variety of security policies that meet the needs of security-critical mobile applications and business models.
321
This page intentionally left blank
C H A P T E R
19
MIDlet Deployment Deploying MIDlets involves more than simply writing Java code using the CLDC and MIDP APIs. To transfer the MIDlet to a wireless device, it has to be packaged with the resources it requires, configured for the locale in which it will be used, and placed on a server that supports the over-the-air (OTA) protocol specification so that it can be downloaded by mobile devices. The first thing to understand is the concept of a MIDlet suite.
19.1 MIDlet Suites One of the central goals for the MIDP application model is to provide support for the controlled sharing of data and resources between multiple, possibly simultaneously running MIDlets. To accomplish this goal while retaining a secure environment, the MIDP Specification requires that any MIDlets needing to interact and share data beyond what is enabled with the RMS record sharing in MIDP 2.0 (refer to Section 14.2.2, “Shared Record Stores”), the MIDlets must be placed into a single JAR. This collection of MIDlets encapsulated in a JAR is referred to as a MIDlet suite. The MIDlets within a MIDlet suite share a common name space (for persistent storage), runtime object heap, and static fields in classes. In order to preserve the security and the original intent of the MIDlet suite provider, the MIDlets, classes, and individual files within the MIDlet suite cannot be installed, updated, or removed individually—they must be manipulated as a whole. In other words, the basic unit of application installation, updating, and removal in MIDP is a MIDlet suite. A MIDlet suite can be characterized more precisely by its packaging and its runtime environment. These characteristics are discussed in more detail next. 323
324
CHAPTER 19
MIDLET DEPLOYMENT
19.1.1 MIDlet Suite Packaging A MIDlet suite is encapsulated within a JAR.1 A MIDlet suite provider is responsible for creating a JAR that includes the appropriate components for the target user, device, network, and locale. For example, since the CLDC Specification does not include the full internationalization and localization support provided by Java 2 Standard Edition, a MIDlet suite provider must tailor the JAR components to include the necessary additional resources (strings, images, and so forth) for a particular locale. The contents of the MIDlet suite’s JAR include the following components: • the class files implementing the MIDlet(s), • any resource files used by the MIDlet(s)—for example, icon or image files, and so forth, and • a manifest describing the JAR contents. All the files needed by the MIDlet(s) are placed in the JAR using the standard structure based on mapping the fully qualified class names to directory and file names within the JAR. Each period is converted to a forward slash, ‘/’. For class files, the .class extension is appended. 19.1.2 Application Descriptor Each JAR may be accompanied by an optional2 application descriptor (JAD file.) The application descriptor allows the application management software on the device to verify that the associated MIDlet suite is suitable for the device before loading the full JAR. It also allows MIDlet attributes to be supplied to the MIDlet suite without modifying the JAR. The application descriptor that has the MIME type ‘text/vnd.sun.j2me.appdescriptor’ and the file name extension ‘.jad’.
1.
JAR format specifications are available at
http://java.sun.com/products/jdk/1.4.1/docs/guide/jar/index.html. Refer to the JDK JAR and manifest documentation for syntax and related details. 2. The application descriptor is optional for distributors of MIDlet suites (such as wireless network operators). However, all MIDP-compliant implementations must accept an application descriptor.
MIDLET SUITES
The contents of the application descriptor are described by the following BNF syntax: appldesc: *attrline attrline: attrname ":" WSP attrvalue WSP newlines attrname: 1* attrvalue: *valuechar | valuechar *(valuechar | WSP) valuechar valuechar: newlines = 1*newline ; allow blank lines to be ignored newline: CR LF | LF CR = LF = WSP: 1*( SP | HT ) SP = HT = CTL = separators = "(" | ")" | "" | "@" | "," | ";" | ":" | "'" |